高可用系统设计 | 分布式限流策略:计数器算法、漏桶算法、令牌桶算法
文章目錄
- 限流
- 什么是限流?
- 分布式限流
- 限流算法
- 計(jì)數(shù)器算法
- 固定窗口計(jì)數(shù)器
- 滑動(dòng)窗口計(jì)數(shù)器
- 漏桶算法
- 令牌桶算法
限流
什么是限流?
限流可以認(rèn)為服務(wù)降級(jí)的一種,限流就是限制系統(tǒng)的輸入和輸出流量已達(dá)到保護(hù)系統(tǒng)的目的。
一般來(lái)說(shuō)系統(tǒng)的吞吐量是可以被測(cè)算的,為了保證系統(tǒng)的穩(wěn)定運(yùn)行,一旦達(dá)到的需要限制的閾值,就需要限制流量并采取一些措施以完成限制流量的目的。常見(jiàn)的限流操作如下:
- 拒絕服務(wù):當(dāng)流量達(dá)到上限的時(shí),直接把請(qǐng)求拒絕掉。
- 延遲處理:將請(qǐng)求放入消息隊(duì)列中,等到有能力處理時(shí)再?gòu)钠渲腥〕鰜?lái)處理,會(huì)存在延時(shí)。
- 特權(quán)處理:對(duì)用戶進(jìn)行分級(jí),對(duì)高優(yōu)用戶(如VIP)優(yōu)先處理,其他用戶延遲處理或拒絕服務(wù)。
為什么要限流?
在一些節(jié)假日、秒殺活動(dòng)等用戶高峰期時(shí),用戶的流量會(huì)急劇增加,而我們后端的服務(wù)器的處理能力是有限的,如果我們不能很好的處理這些流量,就會(huì)導(dǎo)致服務(wù)器崩潰宕機(jī),從而影響服務(wù)的可用性。同時(shí),對(duì)于一些不正常的流量,如爬蟲、ddos等情況,我們也需要進(jìn)行規(guī)避,因此限流是必不可少的。
通過(guò)限流,我們能夠解決以下問(wèn)題:
- 熱點(diǎn)業(yè)務(wù)帶來(lái)的突發(fā)請(qǐng)求。
- 調(diào)用方 bug 導(dǎo)致的突發(fā)請(qǐng)求。
- 惡意攻擊請(qǐng)求。
分布式限流
分布式限流就是在分布式系統(tǒng)下,控制每個(gè)服務(wù)器接收的請(qǐng)求數(shù),以保證服務(wù)器來(lái)得及處理這些請(qǐng)求。
當(dāng)我們的應(yīng)用單機(jī)部署時(shí),只要對(duì)單點(diǎn)應(yīng)用進(jìn)行了限流,那么應(yīng)用所依賴的各種服務(wù)也都得到了保護(hù)。
但是在企業(yè)實(shí)際的業(yè)務(wù)場(chǎng)景中,都會(huì)采取分布式系統(tǒng)。單個(gè)節(jié)點(diǎn)的限流只能保證當(dāng)前節(jié)點(diǎn)的流量限制,而無(wú)法保護(hù)依賴的資源。即使對(duì)每一個(gè)節(jié)點(diǎn)都采取單點(diǎn)限流的方式,在集群擴(kuò)縮容的時(shí)候也較為麻煩。
因此在分布式場(chǎng)景下,我們應(yīng)當(dāng)借助一些中間件如Redis、Sentinel、Nginx來(lái)實(shí)現(xiàn)分布式限流,這樣才能更加靈活的控制整個(gè)集群的請(qǐng)求限制。同時(shí)由于我們的限制是針對(duì)整個(gè)集群的,我們所依賴的資源也得到了保障。
限流算法
計(jì)數(shù)器算法
最簡(jiǎn)單的限流算法其實(shí)就是計(jì)數(shù)器,我們只需要針對(duì)不同的場(chǎng)景,對(duì)各種窗口進(jìn)行計(jì)數(shù)。
固定窗口計(jì)數(shù)器
固定窗口計(jì)數(shù)器算法概念如下:
- 將時(shí)間劃分為多個(gè)窗口。
- 在每個(gè)窗口內(nèi)每有一次請(qǐng)求就將計(jì)數(shù)器加一。
- 如果計(jì)數(shù)器超過(guò)了限制數(shù)量,則本窗口內(nèi)所有的請(qǐng)求都被丟棄當(dāng)時(shí)間到達(dá)下一個(gè)窗口時(shí),計(jì)數(shù)器重置。
固定窗口計(jì)數(shù)器雖然實(shí)現(xiàn)簡(jiǎn)單,但是也面臨著雙倍突發(fā)的問(wèn)題。
假設(shè)我們限制每秒鐘只能處理10個(gè)請(qǐng)求,在上一個(gè)窗口的后半秒中通過(guò)了10個(gè)請(qǐng)求,在當(dāng)前窗口的前半秒中又通過(guò)了10個(gè)請(qǐng)求,此時(shí)就在一秒鐘內(nèi)通過(guò)了20個(gè)請(qǐng)求,達(dá)到了窗口限制的兩倍,這時(shí)就有可能超出了服務(wù)器的處理能力,從而導(dǎo)致宕機(jī)。
因此,又引入了滑動(dòng)窗口計(jì)數(shù)器
滑動(dòng)窗口計(jì)數(shù)器
滑動(dòng)窗口計(jì)數(shù)器算法概念如下:
- 將時(shí)間劃分為多個(gè)區(qū)間。
- 在每個(gè)區(qū)間內(nèi)每有一次請(qǐng)求就將計(jì)數(shù)器加一維持一個(gè)時(shí)間窗口,占據(jù)多個(gè)區(qū)間。
- 每經(jīng)過(guò)一個(gè)區(qū)間的時(shí)間,則拋棄最老的一個(gè)區(qū)間,并納入最新的一個(gè)區(qū)間。
- 如果當(dāng)前窗口內(nèi)區(qū)間的請(qǐng)求計(jì)數(shù)總和超過(guò)了限制數(shù)量,則本窗口內(nèi)所有的請(qǐng)求都被丟棄。
滑動(dòng)窗口計(jì)數(shù)器是通過(guò)將窗口再細(xì)分,并且按照時(shí)間來(lái)滑動(dòng),這種算法避免了固定窗口計(jì)數(shù)器帶來(lái)的雙倍突發(fā)請(qǐng)求,但時(shí)間區(qū)間的精度越高,維護(hù)窗口的空間容量就越大。
上述計(jì)數(shù)器的實(shí)現(xiàn)方法,雖然實(shí)現(xiàn)起來(lái)非常簡(jiǎn)單,但是有一個(gè)致命的缺陷,就是無(wú)法解決突發(fā)的流量激增這一場(chǎng)景。
在實(shí)際場(chǎng)景中,流量并不會(huì)平滑到來(lái),在某些特定的時(shí)間段如節(jié)日、使用熱點(diǎn)等時(shí)間會(huì)存在突發(fā)的流量激增,在這種情況下很容易就會(huì)導(dǎo)致服務(wù)器性能打滿,從而出現(xiàn)宕機(jī)等情況。因此,又引入了漏桶和令牌桶算法。
漏桶算法
漏桶算法概念如下:
- 將每個(gè)請(qǐng)求視作水滴放入漏桶進(jìn)行存儲(chǔ)。
- 漏桶以固定速率向外漏出請(qǐng)求來(lái)執(zhí)行,如果漏桶空了則停止漏水。
- 如果漏桶滿了則多余的水滴會(huì)因?yàn)橐绯霰恢苯觼G棄。
如下圖所示,水滴持續(xù)滴入漏桶中,底部定速流出。如果水滴滴入的速率大于流出的速率,當(dāng)存水超過(guò)桶的大小的時(shí)候就會(huì)溢出。
無(wú)論用戶請(qǐng)求有多少,無(wú)論請(qǐng)求速率有多大,漏桶都會(huì)接收下來(lái),同時(shí)漏桶里流出來(lái)的請(qǐng)求是固定速率的,即使是在流量激增的情況下,也保證了服務(wù)器能夠平滑的處理。當(dāng)漏桶因?yàn)槿萘肯拗品挪幌赂嗟恼?qǐng)求時(shí),就會(huì)選擇丟棄部分請(qǐng)求。這種思路其實(shí)就是一種寬進(jìn)嚴(yán)出的策略。
漏桶算法的缺陷也很明顯,當(dāng)短時(shí)間內(nèi)有大量的突發(fā)請(qǐng)求時(shí),即便此時(shí)服務(wù)器沒(méi)有任何負(fù)載,每個(gè)請(qǐng)求也都得在隊(duì)列中等待一段時(shí)間才能被響應(yīng)。所以漏桶策略適用于間隔性突發(fā)流量且流量不用即時(shí)處理的場(chǎng)景。
令牌桶算法
令牌桶策略,指的是桶里放著很多令牌,只有拿到令牌的請(qǐng)求才能被服務(wù)器處理。
令牌桶算法概念如下:
- 令牌以固定速率生成。
- 生成的令牌放入令牌桶中存放,如果令牌桶滿了則多余的令牌會(huì)直接丟棄。當(dāng)請(qǐng)求到達(dá)時(shí),會(huì)嘗試從令牌桶中取令牌,取到了令牌的請(qǐng)求可以執(zhí)行。
- 如果桶空了,那么嘗試取令牌的請(qǐng)求會(huì)被直接丟棄。
超強(qiáng)干貨來(lái)襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生
總結(jié)
以上是生活随笔為你收集整理的高可用系统设计 | 分布式限流策略:计数器算法、漏桶算法、令牌桶算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: ClickHouse 分布式原理:Dis
- 下一篇: java信息管理系统总结_java实现科