开篇
在高并发系统中,有很多手段来保护系统,如缓存、降级和限流等。
缓存:让数据尽早进入缓存,离程序近一点,不要大量频繁的访问DB,可提供系统访问速度和增大系统处理能力。
降级:当服务出问题或者影响到核心流程的性能,需要将服务暂时屏蔽掉,待高峰期过去或问题解决后再启用。
然后,有些场景不能用缓存和降级来解决。比如电商的双十一,用户的购买,下单等行为,是涉及到大量写操作,而且是核心链路,无法降级的。
限流:通过把并发访问/请求进行限速或者一定时间窗口内的请求限制在一定范围内来保护系统,一旦达到限制速率则可以拒绝服务(定向到错误页面或告知资源没有了)、排队或等待(如秒杀),从而保证系统不被冲垮,同时尽可能提升系统的吞吐量。
限流算法
常见的限流算法:漏桶、令牌桶。计数器也可用来进行粗暴限流实现。
1.漏桶(Leaky Bucket)
漏桶算法可用于流量整形(Traffic Shaping)和流量控制(Traffic Policing)
漏桶算法描述如下:
-
一个固定容量的漏桶,按照常量固定速率流出水滴;
-
如果桶是空的,则不需流出水滴;
-
可以以任意速率流入水滴到漏桶;
-
如果流入水滴超出了桶的容量,则流入的水滴溢出了(被丢弃),而漏桶容量是不变的。
2.令牌桶(Token Bucket)
令牌桶算法是一个存放固定容量令牌(token)的桶,按照固定速率往桶里添加令牌。
令牌桶算法基本可以用下面的几个概念来描述:
- 假设限制10r/s,将按照每100毫秒的固定的速率往桶中添加令牌。
- 桶中最多存放b个令牌,当桶满时,新添加的令牌被丢弃或拒绝。
- 当一个n个字节大小的数据包到达,将从桶中删除n个令牌,接着数据包被发送到网络上。
- 如果桶中的令牌不足n个,则不会删除令牌,且该数据包将被限流(要么丢弃,要么缓冲区等待)。
令牌桶算法实际上由三部分组成:两个流和一个桶,分别是令牌流、数据流与令牌桶。
令牌流与令牌桶
系统会以一定的速度生成令牌,并将其放置到令牌桶中,可以将令牌桶想象成一个缓冲区(可以用队列这种数据结构来实现),当缓冲区填满的时候,新生成的令牌会被扔掉。 这里有两个变量很重要:
- 第一个是生成令牌的速度,一般称为 rate 。比如,我们设定 rate = 2 ,即每秒钟生成 2 个令牌,也就是每 1/2 秒生成一个令牌;
- 第二个是令牌桶的大小,一般称为 burst 。比如,我们设定 burst = 10 ,即令牌桶最大只能容纳 10 个令牌
数据流
数据流是真正的进入系统的流量
有以下三种情形可能发生:
- 数据流的速率 等于 令牌流的速率。这种情况下,每个到来的数据包或者请求都能对应一个令牌,然后无延迟地通过队列;
- 数据流的速率 小于 令牌流的速率。通过队列的数据包或者请求只消耗了一部分令牌,剩下的令牌会在令牌桶里积累下来,直到桶被装满。剩下的令牌可以在突发请求的时候消耗掉。
- 数据流的速率 大于 令牌流的速率。这意味着桶里的令牌很快就会被耗尽。导致服务中断一段时间,如果数据包或者请求持续到来,将发生丢包或者拒绝响应。
漏桶算法和令牌桶算法的比较
|
何时拒绝请求
|
限流策略
|
---|---|---|
漏桶算法 | 漏桶是按照常量固定速率流出请求,流入请求速率任意,当流入的请求数累积到漏桶容量时,则新流入的请求被拒绝; | 漏桶限制的是常量流出速率(即流出速率是一个固定常量值,比如都是 1 的速率流出,而不能一次是 1 ,下次又是 2 ),从而平滑突发流入速率; |
令牌桶算法 | 令牌桶是按照固定速率往桶中添加令牌,请求是否被处理需要看桶中令牌是否足够,当令牌数减为零时则拒绝新的请求; | 令牌桶限制的是平均流入速率(允许突发请求,只要有令牌就可以处理,支持一次拿 3 个令牌, 4 个令牌),并允许一定程度突发流量; |
参考资料
http://m635674608.iteye.com/blog/2339587 高并发系统限流《亿级流量网站架构核心技术》第2部分 高可用 4.限流详解
http://ju.outofmemory.cn/entry/102231 令牌桶算法/Token Bucket Algorithm