和时间算法的区别是什么?
一个是时间,一个不是时间。
时间,就是1s内1000个请求。 不是时间,就是集合里放了1000个token,现在是以集合的大小为度量单位。而不是以时间。
这是算法的区别。
到底解决了什么问题?
时间的缺点是,时间粒度无论怎么设置,都不能解决本质问题。我们要解决的本质问题是,并发请求数量。这个才是核心。本质上它是与时间无关的,虽然高并发就是短时间请求数量比较多。
但是最最本质的是,你要做什么?你要做的是控制并发请求数量。那就干脆弄一个集合,用集合的大小来限制请求数量。这样就解决了时间粒度的问题。
时间,不是解决不了问题。而是解决不了粒度的问题。集合就可以了解决时间粒度的问题,我就控制一个总数量,这就够了,跟时间无关,但是实际上这样就已经解决了时间粒度的问题,因为时间粒度再细的情况,这个时候哪怕请求再多,我现在是以集合大小为准,超过的请求就都放弃或者排队。
数据结构
集合
token怎么放?
令牌桶、漏桶限流算法
上面我们讲了两种基于时间窗口的限流算法:固定时间窗口和滑动时间窗口算法,两种限流算法都无法应对细时间粒度的突发流量,对流量的整形效果在细时间粒度上不够平滑。本节介绍两种更加平滑的限流算法:令牌桶算法和漏桶算法,在某些场景下,这两种算法会优于时间窗口算法成为首选。实际上令牌桶和漏桶算法的算法思想大体类似,可以把漏桶算法作为令牌桶限流算法的改进版本,所以我们以介绍令牌桶算法为主。
我们先来看下最基础未经过改进的令牌桶算法:
1.接口限制 t 秒内最大访问次数为 n,则每隔 t/n 秒会放一个 token 到桶中;//频率:1ms放1个token
2.桶中最多可以存放 b 个 token,如果 token 到达时令牌桶已经满了,那么这个 token 会被丢弃;//放token的时候,集合满了,就丢弃token。说明现在消费token很慢,请求很少。
3.接口请求会先从令牌桶中取 token,拿到 token 则处理接口请求;拿不到 token 则执行限流。//拿不到token,说明现在请求数量很多。请求数量速度,已经超过了放token的速度。但是放token的速度是固定的,为什么要固定?因为这就是我们机器能处理的请求数量。所以,超过token速度的请求,都被服务器丢弃。
令牌桶算法看似比较复杂,每间隔固定时间都要放 token 到桶中,但并不需要专门起一个线程来做这件事情。每次在取 token 之前,根据上次放入 token 的时间戳和现在的时间戳,计算出这段时间需要放多少 token 进去,一次性放进去,所以在实现上面也并没有太大难度。
和时间窗口的区别?
其实,不管是时间窗口,还是token集合,本质都是计数器。
那么时间窗口的计数器和token集合的计数器,有什么区别呢?
虽然都是计数器,但是维度不同。
一个是按时间单位来计算计数器
1.1ms一个请求
2.1s 1000个请求
3.如果1s内,还有更多的请求,就丢弃或排队
那么这个时候可以看到,就是1000/s,在一段时间内超过了一定数量的请求,然后就开始限流。
一个是控制集合里的token数量
1.按t/n的速度,写token到集合
2.请求来了,校验是否能读到token
3.能,就继续;不能就丢弃或排队
漏桶和令牌桶的区别?
如果读的时候,也有控制速度,即和写的时候思路一样,按一定的速度t/n,来读token。那么这个时候,就是漏桶。
即进入和漏出的速度,是一致的意思。
其实本质就是对写token到集合和从token集合读的速度进行控制。
参考
mp.weixin.qq.com/s/k9tm-4lBw… //主要看这个