限流算法:令牌桶、漏桶、GCRA

引言

限流算法中的漏桶/令牌桶被大家所熟知。但生产中进行实现时,真的要通过语言的并发能力模拟一个生产者注水、一个消费者取水吗?如果是不支持并发能力的语言又该怎么办呢?本文带大家从令牌桶/漏桶算法开始,了解实际生产中用到的算法变体:GCRA。

1. 基本限流算法:令牌桶与漏桶

令牌桶 token bucket

令牌桶算法需要创建一个固定容量的桶,再以固定的速度向桶中添加令牌。检查请求是否触发限流,就是要去检查桶中是否有足够的令牌:如果够,则放行请求,并且从桶中删除特定数量的令牌;如果不够,则需要阻拦请求并进一步做其他处理(拒绝、异步、重试等)。

需要注意的是:

  1. 请求的平均速度等于向桶中添加令牌的速度
  2. 对请求突发情况的容忍度决定于桶的容量

算法描述:

  1. 存在参数r和b:r即rate,b即burst。
  2. 每1/r秒向桶中添加一个令牌。
  3. 桶中最多容纳b个令牌。如果添加令牌时桶满了,则丢弃该令牌。
  4. 1个消耗为n的求到达时:
    1. 如果桶中至少存在n个令牌,则移除n个令牌,并放行请求
    2. 如果桶中不足n个令牌,则不移除任何令牌,并阻拦请求

漏桶 leaky bucket

漏桶有固定的容量,流量到达时将被桶整流塑形:当桶不空时,流量从桶底以固定速度流出;如果桶满了,流量将溢出并进一步做其他处理。

更具体的描述是:

  1. 漏桶是一个固定容量的桶,并以固定的速度漏水。
  2. 桶如果空了就停止泄露。
  3. 流量到达时将尝试向桶中注水,以确认流量是否能被确认。
  4. 如果桶满了,上述注水将失败(溢出),且流量不被确认。

漏桶还有两种不同的基础实现方式:基于计数器、基于队列。

基于计数器的实现(Meter,仪表,计量器)。计数器的值代表了水位,流量到达时计数器增加相当于加水,计数器以固定速度减小相当于漏水。加水成功流量才被放行。这种实现接近于上述算法。

在基于队列的实现中,桶以固定长度队列的形式实现,流量流入队列、遵循FIFO,在另一端以固定速度流出。这和计数器实现的一个核心区别是,只要桶不空,流量将被严格塑形为固定的速度,并消除任何突发情况。需要注意的是,这种塑形过于严格,会给流量带来微小的时间位移,在一些实时网络传输场景中这会引发问题。

总结

令牌桶与漏桶在算法底层其实没有差别,二者更倾向于是一类算法的镜像实现:令牌桶提前加水、流量到达时取水,漏桶流量到达时加水、主动漏水。甚至,漏桶本身的两种实现方式,也有不同的特性。在后面的代码实现case中,我们能看到更多的实现层面的差异。

2. 进阶限流算法:GCRA

GCRA为通用信元速率算法(generic cell rate algorithm)是对漏桶算法(计数器模式,而非队列模式)的改进,在实现上更加优雅、能够直接应用于生产。GCRA有两种等价的描述方式:漏桶模式和虚拟调度模式。漏桶模式的描述更便于我们入门理解,虚拟调度模式更加优雅、便于深入理解和实现。

漏桶模式

连续状态漏桶continuous state leaky算法定义了一个有限容量的桶,桶以每时间单位1的速度排水,并在每次确认请求后注水T。如果请求到达时桶内水位(X')小于等于τ,则确认请求,否则拒绝请求:

  1. 请求到达时,根据上一次的水位X、上一次请求确认时间LCT、本次请求到达时间t,计算出新水位X'
  2. 新水位X'超过限制τ,则拒绝请求
  3. 新水位X'小于等于τ,则确认请求,并结合请求带来的注水量T计算最终水位
  4. 计算最终水位时,如果之前很久没有请求到达,X'可能为负,此时要取X'=max(0,X')
  5. 注意算法是先确认请求再注水,所以桶的容量(计数器上限)为T+τ

虚拟调度模式

虚拟调度模式中,算法已经很难看到原始漏桶的影子了。算法通过比较请求的"理论到达时间(TAT,Theoretical Arrival Time )"与实际到达时间t来判定其能否被确认:

  1. 算法定义了T,预期的请求间隔时间(可以推导出预期请求速度是1/T)
  2. 算法定义了容忍度τ,即请求可以早于TAT最多τ时间
  3. t<TAT-τ则说明请求到达的过早,不能被确认
  4. 请求被确认时,算法更新下一次的TAT=max(t,TAT)+T
    1. 注意计算TAT时的max操作,这是为了配合容忍度τ:请求可能早于TAT,但没有早于TAT-τ。

总结

GCRA算法是漏桶的生产改进版本。简单学习漏桶、令牌桶算法后,似乎我们在实现时需要一个旁路的定时器取漏水或注水。但实际生产中,没有什么语言能方便地支持这种并发实现,哪怕是go可以用goroutinue做到,性能也极其有限。反倒是时钟信息,集合任何系统、语言都然支持。所以GCRA才是真的能拿到生产上应用的算法。

参考文献:

  1. en.wikipedia.org/wiki/Token_...
  2. en.wikipedia.org/wiki/Leaky_...
  3. en.wikipedia.org/wiki/Generi...
相关推荐
学无止境\n几秒前
[C语言]指针和数组
c语言·数据结构·算法
黄俊懿5 分钟前
【深入理解SpringCloud微服务】手写实现各种限流算法——固定时间窗、滑动时间窗、令牌桶算法、漏桶算法
java·后端·算法·spring cloud·微服务·架构
新缸中之脑5 分钟前
Llama 3.2 安卓手机安装教程
前端·人工智能·算法
夜雨翦春韭24 分钟前
【代码随想录Day29】贪心算法Part03
java·数据结构·算法·leetcode·贪心算法
Curry_Math41 分钟前
Acwing 区间DP & 计数类DP
算法
Tisfy1 小时前
LeetCode 1928.规定时间内到达终点的最小花费:动态规划
算法·leetcode·动态规划·
ん贤1 小时前
贪心算法.
算法·贪心算法
cndes1 小时前
大数据算法的思维
大数据·算法·支持向量机
睡不着还睡不醒3 小时前
【数据结构强化】应用题打卡
算法
sp_fyf_20243 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-05
人工智能·深度学习·神经网络·算法·机器学习·语言模型·自然语言处理