1、計數器(固定窗口)算法
計數器算法是使用計數器在週期內累加訪問次數,當達到設定的限流值時,觸發限流策略。下一個週期開始時,進行清零,重新計數。
此算法在單機還是分佈式環境下實現都非常簡單,使用redis的incr原子自增性和線程安全即可輕鬆實現。
這個算法通常用於QPS限流和統計總訪問量,對於秒級以上的時間週期來說,會存在一個非常嚴重的問題,那就是臨界問題,如下圖:
假設1min內服務器的負載能力爲100,因此一個週期的訪問量限制在100,然而在第一個週期的最後5秒和下一個週期的開始5秒時間段內,分別湧入100的訪問量,雖然沒有超過每個週期的限制量,但是整體上10秒內已達到200的訪問量,已遠遠超過服務器的負載能力,由此可見,計數器算法方式限流對於週期比較長的限流,存在很大的弊端。
2、滑動窗口算法
滑動窗口算法是將時間週期分爲N個小週期,分別記錄每個小週期內訪問次數,並且根據時間滑動刪除過期的小週期。
如下圖,假設時間週期爲1min,將1min再分爲2個小週期,統計每個小週期的訪問數量,則可以看到,第一個時間週期內,訪問數量爲75,第二個時間週期內,訪問數量爲100,超過100的訪問則被限流掉了
由此可見,當滑動窗口的格子劃分的越多,那麼滑動窗口的滾動就越平滑,限流的統計就會越精確。
此算法可以很好的解決固定窗口算法的臨界問題。
3、漏桶算法
漏桶算法是訪問請求到達時直接放入漏桶,如當前容量已達到上限(限流值),則進行丟棄(觸發限流策略)。漏桶以固定的速率進行釋放訪問請求(即請求通過),直到漏桶爲空。
4、令牌桶算法
令牌桶算法是程序以r(r=時間週期/限流值)的速度向令牌桶中增加令牌,直到令牌桶滿,請求到達時向令牌桶請求令牌,如獲取到令牌則通過請求,否則觸發限流策略
各個算法比較
算法 |
確定參數 |
空間複雜度 |
時間複雜度 |
限制突發流量 |
平滑限流 |
分佈式環境下實現難度 |
固定窗口 |
計數週期T、 週期內最大訪問數N |
低O(1) (記錄週期內訪問次數及週期開始時間) |
低O(1) |
否 |
否 |
低 |
滑動窗口 |
計數週期T、 週期內最大訪問數N |
高O(N) (記錄每個小週期中的訪問數量) |
中O(N) |
是 |
相對實現。滑動窗口的格子劃分的越多,那麼滑動窗口的滾動就越平滑 |
中 |
漏桶 |
漏桶流出速度r、漏桶容量N |
低O(1) (記錄當前漏桶中容量) |
高O(N) |
是 |
是 |
高 |
令牌桶 |
令牌產生速度r、令牌桶容量N |
低O(1) (記錄當前令牌桶中令牌數) |
高O(N) |
是 |
是 |
高 |