在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流
缓存 缓存的目的是提升系统访问速度和增大系统处理容量降级 降级是当服务出现问题或者影响到核心流程时,需要暂时屏蔽掉,待高峰或者问题解决后再打开限流 限流的目的是通过对并发访问/请求进行限速,或者对一个时间窗口内的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务、排队或等待、降级等处理
本次研究一下限流
限流算法
三种限流算法
- 计数器法
- 漏桶算法
- 令牌桶算法
计数器法
是限流算法中最简单的一种。每个时间间隔设置一个计数器,每收到一个请求计数器加一,当计数器数值达到指定阈值的时候比较计数开始时间和当前时间的差是否大于指定时间间隔,大于时间间隔则计数器清零重新开始计数,否则丢弃请求。
代码如下
1 | import org.apache.commons.lang3.RandomUtils; |
返回结果
1 | 1533891929746 sleep=821,req=30,check=true |
注意这两条结果
1 | 1533891935702 sleep=701,req=85,check=true |
在指定1000ms间隔内其实处理了85+30=115次的请求,大于了限制的100次。这就是计数器算法的缺点——两次计数时间范围边界请求无法控制的问题。
滑动窗口
针对于以上问题,我们引入滑动窗口算法。算法核心思想如下图所示
把计数的时间域划分为多个窗口,每个窗口有自己独立的计数器,随着时间的推移而向前滑动窗口,解决边界问题。(其实是把窗口划分的粒度更小来规避边界问题)