常見的限流方法:
- 固定窗口計數器:按照時間段劃分窗口,有一次請求就+1,最為簡單的算法,但這個算法有時會讓通過請求量允許為限制的兩倍。
- 滑動窗口計數器:通過將窗口再細分,并且按照時間“滑動”來解決突破限制的問題,但是時間區間的精度越高,算法所需的空間容量就越大。
- 漏桶:請求類似水滴,先放到桶里,服務的提供方則按照固定的速率從桶里面取出請求并執行。缺陷也很明顯,當短時間內有大量的突發請求時,即便此時服務器沒有任何負載,每個請求也都得在隊列中等待一段時間才能被響應。
- 令牌桶:往桶里面發放令牌,每個請求過來之后拿走一個令牌,然后只處理有令牌的請求。令牌桶滿了則多余的令牌會直接丟棄。令牌桶算法既能夠將所有的請求平均分布到時間區間內,又能接受服務器能夠承受范圍內的突發請求,因此是目前使用較為廣泛的一種限流算法。Google的開源項目guava提供了RateLimiter類,實現了單點的令牌桶限流。分布式環境下,可以考慮用Redis+Lua腳本實現令牌桶。 如果請求量太大了,Redis也撐不住怎么辦?我覺得可以類似于分布式ID的處理方式,Redis前面在增加預處理,比如每臺及其預先申請一部分令牌,只有令牌用完之后才去 Redis。如果還是太大,是否可以垂直切分?按照流量的來源,比如地理位置、IP 之類的再拆開。