一文搞懂常见限流算法:计数器、滑动窗口、漏桶、令牌桶

📢:在开发高并发系统时,有三把利器用来保护系统:缓存、降级和限流。

限流在很多场景中用来限制并发和请求量,比如说秒杀抢购,保护自身系统和下游系统不被巨型流量冲垮等。你要开发一个限流的框架,那么必不可少的就是要选择一种合适的限流算法。限流算法很多,常见的有几类分别是:计数器算法滑动窗口算法漏桶算法令牌桶算法,具体视业务场景,统计的精准度,限流维度而定。下面逐一讲解。

1、计数器算法

计数器算法是限流算法里最简单也是最容易实现的一种算法。主要用来限制一定时间内的总并发数,计数器限流只要一定时间内的总请求数超过设定的阀值则进行限流,是一种简单粗暴的总数量限流,而不是平均速率限流。比如数据库连接池、线程池、秒杀的并发数;

优点:简单粗暴,单机在Java中可用Atomic等原子类或Semaphore,分布式就用Redis incr。

eg:我们规定,对于A接口来说,我们1分钟的访问次数不能超过100个。那么在一开始的时候,我们可以设置一个计数器counter,每当一个请求过来的时候,counter就加1,如果counter的值大于100并且该请求与第一个请求的间隔时间还在1分钟之内,那么说明请求数过多,限流;如果该请求与第一个请求的间隔时间大于1分钟,且counter的值还在限流范围内,那么就重置 counter


缺点:有一个十分致命的问题,那就是临界问题

eg:假设第1分钟中的第59秒的时候,来了100个请求,这个时候是没有超过100的限制。然后第2分钟的第1秒来了100个请求,相隔几毫秒,一下子进来200个请求,明显大于我们的限流阈值100。也就是说在时间窗口的重置节点处突发请求,可以瞬间超过我们的速率限制。用户有可能通过算法的这个漏洞,瞬间压垮我们的应用。所以这个算法不够完美是不是?


为了解决这个临界区问题,我们引入了滑动窗口算法

2、滑动窗口算法

滑动窗口,又称rolling window。上边提到的计数器算法中,比如限制1分钟内的访问次数,那么这个1分钟就是一个固定的时间窗口,而滑动窗口是将固定窗口再进行细分成多个窗口。

eg:比如将1分钟的固定窗口细分成6个窗口,那么每个窗口的时间就是10秒。如图整个红色的矩形框表示一个时间窗口,窗口是一直滑动的,每过10秒,我们的时间窗口就会往右滑动一格。按照上边我们的假设:假设第1分钟中的第59秒的时候,来了100个请求,落到灰色格子里,而第2分钟的1:00到达的100个请求会落在橘黄色的格子中,而这时我们的时间窗刚好检测到整个1分钟内(红色框),总请求数量一共是200个,超过了限定的100个,所以此时能够检测出来触发了限流。

Spring Cloud 中的熔断框架 Hystrix,以及 Spring Cloud Alibaba 中的Sentinel 都采用滑动窗口来做数据统计。

优点:减少了临界值带来的并发超过阈值的问题。

由此可见,当滑动窗口的格子划分的越多,那么滑动窗口的滚动就越平滑,限流的统计就会越精确。

3、漏桶算法(漏斗算法)

漏桶算法相对前面的计数算法更加柔性,它的原理也很简单,它是一种恒定速率的限流算法,不管请求量是多少,服务端的处理效率是恒定的。漏桶限制的是请求的流出速率。漏桶中装的是请求。

优点:是能够以固定的速率去控制流量,稳定性比较好。

可以认为就是我们常用的漏斗注水漏水的过程。漏桶接受以任意速率流入的水,并且以固定速率将水流出。当水超过桶的容量时,会被溢出,也就相当于被丢弃。

漏桶算法原理与消息队列思想有些类似,都是进行削峰填谷,经过漏桶后请求就能匀速平滑的流出。它是一种恒定速率的限流算法,不管请求量是多少,服务端的处理效率是恒定的。基于 MQ 来实现的生产者消费者模型,其实算是一种漏桶限流算法。


缺点:就是无法应对突发流量的来袭,以及处理请求会有延迟

eg:假设你的漏桶出口固定了每秒钟只能通过100个请求,如果此时有150个请求,无论你后方的系统能不能抗住这150个请求,通过漏桶算法都会将另外50个请求进行拦截,只能等前面的100个请求结束后才能继续放行剩下的50个请求,无法应对突发流量的来袭。

面对突发请求,服务的处理速度和平常一样,这其实不是我们想要的。我们更想要的是面对突发流量时,在系统平稳运行的同时又能更快的处理请求,而不是一直按照统一的速率来处理。漏桶算法,可能更多的用来保护别人的接口。另外,漏桶中由于请求是暂存在桶中的,所以请求什么时候能被处理,则是有延时的,这并不符合互联网业务低延时的要求。

4、令牌桶算法

令牌桶是一个存放固定容量令牌的桶,按照固定速率往桶里添加令牌,填满了就丢弃令牌,请求是否被处理要看桶中令牌是否足够,当令牌数减为零时则拒绝新的请求。在流量低峰的时候,令牌桶会出现堆积,因此当出现瞬时高峰的时候,有足够多的令牌可以获取,令牌桶允许一定程度突发流量,只要有令牌就可以处理,支持一次拿多个令牌。令牌桶中装的是令牌。


网关层面的限流、或者接口调用的限流,都可以使用令牌桶算法,像 Google 的Guava,和 Redisson 的限流,都用到了令牌桶算法。

优点:令牌桶算法是对漏斗算法的一种改进,除了能够起到限流的作用外,还允许一定程度的流量突发。

与漏桶算法相比,有可能导致短时间内的请求数上升(因为拿到令牌后,就可以访问接口,存在一瞬间将所有令牌拿走的情况),但不会有计数算法那样高的峰值(因为令牌数量是匀速增加的)。所以在应对突发流量的时候令牌桶表现的更佳。

一般自己调用自己的接口,接口会有一定的伸缩性,令牌桶算法,主要用来保护自己的服务器接口。

缺点:例如令牌桶,假如系统上线时没有预热,那么可能会出现由于此时桶中还没有令牌,而导致请求被误杀的情况;

5、限流算法总结

上面我们已经了解了每个限流算法的的特点,并且类比了一些应用场景。综上可知,虽然漏桶、令牌桶对比时间窗口类算法对流量的整形效果更好,但是它们也有各自的缺点。

令牌桶、漏桶算法更适合阻塞式限流的场景,即后台任务类的限流。

而基于时间窗口的限流则更适合互联网实施业务限流的场景,即能处理快速处理,不能处理及时响应调用方,避免请求出现过长的等待时间。

6、限流组件

一般而言我们不需要自己实现限流算法来达到限流的目的,不管是接入层限流还是细粒度的接口限流其实都有现成的轮子使用,其实现也是用了上述我们所说的限流算法。

比如Google Guava 提供的限流工具类 RateLimiter,是基于令牌桶实现的,并且扩展了算法,支持预热功能。

阿里开源的限流框架Sentinel 中的匀速排队限流策略,就采用了漏桶算法。

Nginx 中的限流模块 limit_req_zone,采用了漏桶算法,还有 OpenResty 中的 resty.limit.req库等等。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容