在開發高併發系統時有三把利器用來保護系統:緩存、降級和限流。限流(Rate Limit),限流的目的是爲了保護系統不被瞬時大流量沖垮,常見的應用場景類似秒殺,大促峯值QPS在2w以上。
目前比較常見的限流算法有:
- 計數器固定窗口算法
- 計數器滑動窗口算法
- 漏桶算法
- 令牌桶算法
1. 計數器固定窗口算法
計數器固定窗口算法是使用計數器在週期內累加訪問次數,當達到設定的限流值時,觸發限流策略。下一個週期開始時,進行清零,重新計數。
缺點:計數器固定窗口算法通常用於QPS限流和統計總訪問量,對於秒級以上的時間週期來說,會存在一個非常嚴重的問題,那就是臨界問題,比如:
假設我們設定1秒內允許通過的請求閾值是200,如果有用戶在時間窗口的最後幾毫秒發送了200個請求,緊接着又在下一個時間窗口開始時發送了200個請求,那麼這個用戶其實在一秒內成功請求了400次,顯然超過了閾值但並不會被限流。
2.計數器滑動窗口算法
滑動窗口算法是將時間週期分爲N個小週期,分別記錄每個小週期內訪問次數,並且根據時間滑動刪除過期的小週期。
如下圖,假設時間週期爲1min,將1min再分爲2個小週期,統計每個小週期的訪問數量,則可以看到,第一個時間週期內,訪問數量爲75,第二個時間週期內,訪問數量爲100,超過100的訪問則被限流掉了。
由此可見,當滑動窗口的格子劃分的越多,那麼滑動窗口的滾動就越平滑,限流的統計就會越精確。
此算法可以很好的解決固定窗口算法的臨界問題。滑動窗口限流法其實就是計數器固定窗口算法的一個變種。流量的過渡是否平滑依賴於我們設置的窗口格數也就是統計時間間隔,格數越多,統計越精確。
3. 漏桶算法
漏桶算法以一個常量限制了出口流量速率,因此漏桶算法可以平滑突發的流量。其中漏桶作爲流量容器我們可以看做一個FIFO的隊列,當入口流量速率大於出口流量速率時,因爲流量容器是有限的,當超出流量容器大小時,超出的流量會被丟棄。
漏桶算法的特點
-
漏桶具有固定容量,出口流量速率是固定常量(流出請求)
-
入口流量可以以任意速率流入到漏桶中(流入請求)
-
如果入口流量超出了桶的容量,則流入流量會溢出(新請求被拒絕)
漏桶算法限制了流出速率是一個固定常量值,所以漏桶算法不支持出現突發流出流量。
4.令牌桶算法
令牌桶算法是網絡流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最常使用的一種算法。典型情況下,令牌桶算法用來控制發送到網絡上的數據的數目,並允許突發數據的發送。
令牌桶算法的原理是系統會以一個恆定的速度往桶裏放入令牌,而如果請求需要被處理,則需要先從桶裏獲取一個令牌,當桶裏沒有令牌可取時,則拒絕服務。從原理上看,令牌桶算法和漏桶算法是相反的,一個“進水”,一個是“漏水”。
Google的Guava包中的RateLimiter類就是令牌桶算法的解決方案。
總結:
桶算法與令牌桶算法的區別在於,漏桶算法能夠強行限制數據的傳輸速率,令牌桶算法能夠在限制數據的平均傳輸速率的同時還允許某種程度的突發傳輸。
參考:https://blog.csdn.net/weixin_41846320/article/details/95941361