大家都知道目前的常规的限流算法有令牌桶和漏桶算法.今天就这些限流常见的算法给大家做一个详细的介绍与实现思路.

固定窗口

这个算法是最为简单的一个算法,Redis存储key和value,key是任意的,value代表一秒内请求的值,设置一个计时器每个一秒钟将限流的key设置为0.
当有请求来临时执行incr key,key超出了一定值后进行限流.

滑动窗口

tcp就是使用的滑动窗口策略来限制发送的速率.但是tcp的滑动窗口是基于发送和接收的包的大小来限制发送的速率.
我们根据其思想可以改为基于时间的滑动窗口.限制1s内最多请求多少次,且是滑动的.

设定两个边界:窗口大小设置为n,窗口的左边界left右边界right.
固定且不可改变,在设定一个指针point.
point指针和right重合代表窗口关闭.
point指针和left指针重合代表窗口内没有流量.不能超过leftright边界.

根据业务请求量设定每隔xpoint指针向左移动1次.当有请求进入时point指针向右移动1次.达到n次后窗口关闭.

滑动窗口限流也可以避免漏桶出现的无法应对顺时大流量的请求.

除此之外我们还可以设计一种可伸缩的窗口,根据不同的环境不同的时间对窗口进行缩放扩大,或者是提高降低point指针移动的速率.

漏桶

分布式滑动窗口限流算法Java实现 滑动窗口 限流_漏桶

漏桶算法:入桶的速率可以不定,但是出桶的速率是恒定的.
实现很简单的我们可以用队列实现,按照固定频次从队列里消费数据.

漏桶算法可以很方便的将并发请求的大流量,转换为平滑的流量.
当然我们需要额外的存储空间存储请求的数据.不像下述的算法,只是限制流量不会做流量的整形.

令牌桶

分布式滑动窗口限流算法Java实现 滑动窗口 限流_滑动窗口_02

按照一定的速率将令牌放入到桶当中,当请求来临时先从桶获取令牌,如果拿到了令牌则继续请求,否则不执行请求.
桶满后新增令牌被丢弃.
桶空或者桶满后根据业务需要可以适当进行扩大和缩小.

总结

令牌桶交互流程比较复杂,实现需要额外的一些令牌的存储空间,漏桶算法没有那么灵活且需要存储等待处理请求的信息.在面对较大的瞬时流量时,令牌桶和滑动窗口算法有着很好的优势,可以较好的应对瞬时流量,流量也可以瞬时传输,对于漏桶而言瞬时的大流量却只能平均速率传输,因为输出的速率是恒定的.
时间间隔的算法没有那么平滑,时间滑动窗口算法实现简单且平滑,可以瞬时传输较大流量,不需要额外的存储空间.