高可用系统设计 | 分布式限流策略:计数器算法漏桶算法令牌桶算法
Posted 凌桓丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高可用系统设计 | 分布式限流策略:计数器算法漏桶算法令牌桶算法相关的知识,希望对你有一定的参考价值。
限流
什么是限流?
限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已达到保护系统的目的。
一般来说系统的吞吐量是可以被测算的,为了保证系统的稳定运行,一旦达到的需要限制的阈值,就需要限制流量并采取一些措施以完成限制流量的目的。常见的限流操作如下:
- 拒绝服务:当流量达到上限的时,直接把请求拒绝掉。
- 延迟处理:将请求放入消息队列中,等到有能力处理时再从其中取出来处理,会存在延时。
- 特权处理:对用户进行分级,对高优用户(如VIP)优先处理,其他用户延迟处理或拒绝服务。
为什么要限流?
在一些节假日、秒杀活动等用户高峰期时,用户的流量会急剧增加,而我们后端的服务器的处理能力是有限的,如果我们不能很好的处理这些流量,就会导致服务器崩溃宕机,从而影响服务的可用性。同时,对于一些不正常的流量,如爬虫、ddos等情况,我们也需要进行规避,因此限流是必不可少的。
通过限流,我们能够解决以下问题:
- 热点业务带来的突发请求。
- 调用方 bug 导致的突发请求。
- 恶意攻击请求。
分布式限流
分布式限流就是在分布式系统下,控制每个服务器接收的请求数,以保证服务器来得及处理这些请求。
当我们的应用单机部署时,只要对单点应用进行了限流,那么应用所依赖的各种服务也都得到了保护。
但是在企业实际的业务场景中,都会采取分布式系统。单个节点的限流只能保证当前节点的流量限制,而无法保护依赖的资源。即使对每一个节点都采取单点限流的方式,在集群扩缩容的时候也较为麻烦。
因此在分布式场景下,我们应当借助一些中间件如Redis、Sentinel、nginx来实现分布式限流,这样才能更加灵活的控制整个集群的请求限制。同时由于我们的限制是针对整个集群的,我们所依赖的资源也得到了保障。
限流算法
计数器算法
最简单的限流算法其实就是计数器,我们只需要针对不同的场景,对各种窗口进行计数。
固定窗口计数器
固定窗口计数器算法概念如下:
- 将时间划分为多个窗口。
- 在每个窗口内每有一次请求就将计数器加一。
- 如果计数器超过了限制数量,则本窗口内所有的请求都被丢弃当时间到达下一个窗口时,计数器重置。
固定窗口计数器虽然实现简单,但是也面临着双倍突发的问题。
假设我们限制每秒钟只能处理10个请求,在上一个窗口的后半秒中通过了10个请求,在当前窗口的前半秒中又通过了10个请求,此时就在一秒钟内通过了20个请求,达到了窗口限制的两倍,这时就有可能超出了服务器的处理能力,从而导致宕机。
因此,又引入了滑动窗口计数器
滑动窗口计数器
滑动窗口计数器算法概念如下:
- 将时间划分为多个区间。
- 在每个区间内每有一次请求就将计数器加一维持一个时间窗口,占据多个区间。
- 每经过一个区间的时间,则抛弃最老的一个区间,并纳入最新的一个区间。
- 如果当前窗口内区间的请求计数总和超过了限制数量,则本窗口内所有的请求都被丢弃。
滑动窗口计数器是通过将窗口再细分,并且按照时间来滑动,这种算法避免了固定窗口计数器带来的双倍突发请求,但时间区间的精度越高,维护窗口的空间容量就越大。
上述计数器的实现方法,虽然实现起来非常简单,但是有一个致命的缺陷,就是无法解决突发的流量激增这一场景。
在实际场景中,流量并不会平滑到来,在某些特定的时间段如节日、使用热点等时间会存在突发的流量激增,在这种情况下很容易就会导致服务器性能打满,从而出现宕机等情况。因此,又引入了漏桶和令牌桶算法。
漏桶算法
漏桶算法概念如下:
- 将每个请求视作水滴放入漏桶进行存储。
- 漏桶以固定速率向外漏出请求来执行,如果漏桶空了则停止漏水。
- 如果漏桶满了则多余的水滴会因为溢出被直接丢弃。
如下图所示,水滴持续滴入漏桶中,底部定速流出。如果水滴滴入的速率大于流出的速率,当存水超过桶的大小的时候就会溢出。
无论用户请求有多少,无论请求速率有多大,漏桶都会接收下来,同时漏桶里流出来的请求是固定速率的,即使是在流量激增的情况下,也保证了服务器能够平滑的处理。当漏桶因为容量限制放不下更多的请求时,就会选择丢弃部分请求。这种思路其实就是一种宽进严出的策略。
漏桶算法的缺陷也很明显,当短时间内有大量的突发请求时,即便此时服务器没有任何负载,每个请求也都得在队列中等待一段时间才能被响应。所以漏桶策略适用于间隔性突发流量且流量不用即时处理的场景。
令牌桶算法
令牌桶策略,指的是桶里放着很多令牌,只有拿到令牌的请求才能被服务器处理。
令牌桶算法概念如下:
- 令牌以固定速率生成。
- 生成的令牌放入令牌桶中存放,如果令牌桶满了则多余的令牌会直接丢弃。当请求到达时,会尝试从令牌桶中取令牌,取到了令牌的请求可以执行。
- 如果桶空了,那么尝试取令牌的请求会被直接丢弃。
以上是关于高可用系统设计 | 分布式限流策略:计数器算法漏桶算法令牌桶算法的主要内容,如果未能解决你的问题,请参考以下文章