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