导语:流量上涨常常造成系统的不稳定,进而出现雪崩。本文讨论常见的限流算法,以及对比一些开源实现。

一. 常用的限流算法

  1. 计数器:一种比较简单的限流算法,核心是INCRBY和EXPIRE指令。在一段时间内,进行计数,与阀值进行比较,到了时间点,将计数器清0。(缺陷:在整个时间段没有流量,但是在时间临界点突然出现很多请求,例如1分钟限流100,在0秒到58秒没有请求,59秒出现100个请求,1分钟的时候又出现100个请求,短时间内大量请求,系统可能还是会崩溃)
  2. 漏桶:针对计数器的临界点缺陷,提出了漏桶算法。有一个固定的桶,进水的速率是不确定的,但是出水的速率是恒定的,当水满的时候会溢出。它的主要用法是控制请求方发送请求到其他服务器的速率,平滑调用的突发流量。
    漏桶算法示意图
  3. 令牌桶:漏桶的出水速度是恒定的,那么意味着如果瞬时大流量的话,将有大部分请求被丢弃掉(也就是所谓的溢出)。为了解决这个问题,令牌桶进行了算法改进。 生成令牌的速度是恒定的,而请求去拿令牌是没有速度限制的。这意味,面对瞬时大流量,该算法可以在短时间内请求拿到大量令牌
    令牌桶算法示意图
    二. 开源实现
  • 优点:star最高
  • 缺点:功能比较简单,阻塞等待直到获得令牌,不支持分布式,只支持漏桶算法
  • 优点:支持把令牌存储到Redis和memory中,还支持不同的prefix
  • 缺点:适用于服务端,把限流器注册到服务中间件里面。
  • 缺点:HTTP服务端限流,也不支持分布式
  • 优点:阻塞式和非阻塞的都有,实现简单
  • 缺点:不支持分布式
  • 优点:支持Redis,并且是非阻塞的
  • 缺点:试了一下有问题,Git上给作者提了issues
  • 优点:支持Redis
  • 缺点:近四年没有更新
  • 优点:go-redis官方实现,支持分布式,非阻塞,使用简单
  • 缺点:只支持漏桶算法

经过对开源项目的对比和测试,redis_rate支持分布式,是redis官方实现的,版本也一直再更新 ,使用也很方便。对于流量分布比较均匀的场景可以考虑使用