详解限流算法,图示漏桶算法与令牌桶算法( 三 )


  • 第一次请求过来需要获取1个令牌,直接拿到
  • RateLimiter在1秒钟后放一个令牌,第一次请求预支的1个令牌还上了
  • 1秒钟之后第二次请求过来需要获得5个令牌,直接拿到
  • RateLimiter在花了5秒钟放了5个令牌,还上了第二次请求预支的5个令牌
  • 第三个请求在5秒钟之后拿到3个令牌
也就是说,前面的请求如果流量大于每秒放置令牌的数量,那么允许处理,但是带来的结果就是后面的请求延后处理,从而在整体上达到一个平衡整体处理速率的效果 。
突发流量的处理,在令牌桶算法中有两种方式,一种是有足够的令牌才能消费,一种是先消费后还令牌 。后者就像我们0首付买车似的,30万的车很少有等攒到30万才全款买的,先签了相关合同把车子给你,然后贷款慢慢还,这样就爽了 。RateLimiter也是同样的道理,先让请求得到处理,再慢慢还上预支的令牌,客户端同样也爽了,否则我假设预支60个令牌,1分钟之后才能处理我的请求,不合理也不人性化 。
 
RateLimiter的限制
特别注意RateLimiter是单机的,也就是说它无法跨JVM使用,设置的1000QPS,那也在单机中保证平均1000QPS的流量 。
假设集群中部署了10台服务器,想要保证集群1000QPS的接口调用量,那么RateLimiter就不适用了,集群流控最常见的方法是使用强大的redis:
  • 一种是固定窗口的计数,例如当前是2019/8/26 20:05:00,就往这个"2019/8/26 20:05:00"这个key进行incr,当前是2019/8/26 20:05:01,就往"2019/8/26 20:05:01"这个key进行incr,incr后的结果只要大于我们设定的值,那么就打回去,小于就相当于获取到了执行权限
  • 一种是结合lua脚本,实现分布式的令牌桶算法,网上实现还是比较多的
总得来说,集群限流的实现也比较简单 。
 
总结本文主要写了常见的两种限流算法漏桶算法与令牌桶算法,并且演示了Guava中RateLimiter的实现,相信看到这里的朋友一定都懂了,恭喜你们!
令牌桶算法是最常用的限流算法,它最大的特点就是容许一定程度的突发流量 。
漏桶算法同样也有自己的应用之处,例如Nginx的限流模块就是基于漏桶算法的,它最大的特点就是强行限制流量按照指定的比例下发,适合那种对流量有绝对要求的场景,就是流量可以容许在我指定的值之下,可以被多次打回,但是无论如何决不能超过指定的 。
虽然令牌桶算法相对更好,但是还是我经常说的,使用哪种完全就看大家各自的场景,适合的才是最好的 。

【详解限流算法,图示漏桶算法与令牌桶算法】


推荐阅读