限流算法:令牌桶、漏桶、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...
相关推荐
C++忠实粉丝20 分钟前
计算机网络socket编程(5)_TCP网络编程实现echo_server
网络·c++·网络协议·tcp/ip·计算机网络·算法
kim56591 小时前
excel版数独游戏(已完成)
算法·游戏·excel·数独
cv君1 小时前
【AI最前线】DP双像素sensor相关的AI算法全集:深度估计、图像去模糊去雨去雾恢复、图像重建、自动对焦
算法
Ocean☾2 小时前
C语言-详细讲解-P1217 [USACO1.5] 回文质数 Prime Palindromes
c语言·数据结构·算法
沐泽Mu2 小时前
嵌入式学习-C嘎嘎-Day08
开发语言·c++·算法
Non importa2 小时前
汉诺塔(hanio)--C语言函数递归
c语言·开发语言·算法·学习方法
ac-er88882 小时前
PHP 二分法查找算法
开发语言·算法·php
Choshim-2 小时前
7-9 求无向图连通分量的数量
数据结构·算法·深度优先
Eric.Lee20212 小时前
数据集-目标检测系列- 昙花(昙花一现) 检测数据集 epiphyllum >> DataBall
算法·yolo·目标检测·计算机视觉·昙花一现·昙花检测
淀粉肠kk3 小时前
【数据结构】二叉树(2)
数据结构·算法