文章目錄
- 什么時候用令牌桶,什么時候用漏桶算法??
- 先放結論
- 兩個算法一眼看懂
- 什么時候選令牌桶?
- 什么時候選漏桶?
- 組合用法(90% 的真實系統都會這么干)
- 小結記憶
- 對令牌桶和漏桶組合用法再次詳細敘述一下,以小紅書生活社區系統為例子
- 為什么要 **“令牌桶 → 漏桶”** 組合?
- 1. 小紅書請求鏈路示例
- 2. 組合在小紅書的 **四個高頻場景**
- 3. 配置與調優步驟(落地到小紅書)
- 4. 代碼/配置片段示意
- 5 · 常見誤區 & 小紅書踩坑實錄
什么時候用令牌桶,什么時候用漏桶算法??
先放結論
場景特征 | 令牌桶(Token Bucket) | 漏桶(Leaky Bucket) |
---|---|---|
是否允許突發流量 | ? 允許,可在桶里先攢“額度”,瞬時放量 | ? 不允許,出流量永遠是勻速 |
對下游的壓力 | 瞬時可能出現高并發,需要下游有一定緩沖或彈性 | 始終平滑,幾乎不會壓垮下游 |
對實時性/時延要求 | 突發時延小,整體時延可控 | 峰值被“削平”,高峰請求會排隊、時延增大 |
典型用例 | API 網關限流、微服務之間“削峰”但保留突發、手機套餐計費 | 交換機/路由器排隊、日志寫入磁盤、打印任務、銀行轉賬出賬口 |
兩個算法一眼看懂
關鍵詞 | 令牌桶 | 漏桶 |
---|---|---|
本質 | “拿令牌才可通過” | “進水隨意,出水勻速” |
控制維度 | 入流(允許多久發多少) | 出流(確保永遠固定速率) |
可配置項 | 生成速率 r、桶容量 b | 漏出速率 r、桶容量 b |
能否積攢額度 | 可以:桶里最多存 b 個令牌 | 可以:桶里最多排隊 b 個請求 |
流量視角 | 突發→滑動平均 ≤ r | 任何時刻 ≤ r |
什么時候選令牌桶?
- 業務本身就是“偶有高峰”
例:電商秒殺開始前 5 秒,令牌桶能攢夠令牌,瞬間放行指定量請求;后續再勻速補充。 - 下游能短暫擴容或有緩沖區
比如使用異步隊列、K8s 自動擴縮容,可吃掉短時突發。 - 需要按“總量 + 峰值”計費/統計
運營商對流量計費:保證平均速率,但允許你瞬時用掉“未用額度”。 - API 限流希望“好人優先”
正常流量積攢令牌,機器人/爬蟲持續刷會很快耗盡令牌,被限速。
一句話:令牌桶在乎“總量控制 + 瞬時彈性”。
什么時候選漏桶?
- 下游“吃不了”任何峰值,只能勻速消費
打印機、磁帶機、磁盤順寫、第三方支付接口 QPS 固定。 - 希望徹底削峰平谷,保證穩定輸出
視頻流推送、實時音頻、網絡芯片隊列,抖動越小越好。 - 時延可被犧牲換取穩定
排隊時間增加也沒關系,例如批量日志落盤。 - 實現簡單、資源可預估
只要求一個固定速率,不需要動態計算剩余令牌。
一句話:漏桶在乎“絕對平滑 + 下游安全”。
組合用法(90% 的真實系統都會這么干)
- 入口令牌桶 —— 允許合規突發,把“洪峰”削到可控范圍。
- 出口漏桶 —— 對真正嬌貴的依賴再做一次勻速下沉。
這樣既不失靈活性,又能保護最脆弱的環節。很多 API 網關、CDN、大型分布式系統限流都是“先令牌桶,后漏桶”。
小結記憶
- 令牌桶:能攢錢、能一次性花;平均不能超標。
- 漏桶:只能領死工資;永遠 1、1、1… 勻速走。
選哪個?看你要不要“突發權”。如果答案是“要”—→令牌桶;如果答案是“絕不能”—→漏桶。
對令牌桶和漏桶組合用法再次詳細敘述一下,以小紅書生活社區系統為例子
為什么要 “令牌桶 → 漏桶” 組合?
在真實的大型社區里——小紅書就是典型——沒有一種單獨的限流算法能同時滿足「用戶體驗」和「核心依賴安全」 兩個目標:
目標 | 令牌桶能做到 | 漏桶能做到 |
---|---|---|
秒級突發場景(雙 11、明星發筆記秒贊)依然“秒開” | ? | ? |
保護下游(數據庫、推薦 RPC、支付)絕不被瞬時打爆 | ? | ? |
所以工業界普遍做法是:入口先令牌桶,出口再漏桶。下面用小紅書的典型流量路徑來拆一遍。
1. 小紅書請求鏈路示例
App/Web ? CDN ? API Gateway ? Notes Service ?│ │(令牌桶限流) (漏桶勻速入庫 + MQ)
-
API Gateway / 邊緣網關(令牌桶)
- 粒度:用戶 ID + 接口(
/notes/publish
、/notes/like
等) - 配置示例:
- 桶容量 B = 120(允許 2 分鐘的剩余額度)
- 令牌速率 R = 60 req/min(每人每分鐘 60 次發帖接口)
- 效果:
- 正常人偶爾連點「發布」也能秒過。
- 連續腳本刷請求會瞬間耗空令牌,得到 429。
- 粒度:用戶 ID + 接口(
-
業務微服務(漏桶)
- 場景:
Notes Service
里寫數據庫、調用內容審核、下發特點 feed 打分。 - 實現:
入隊:任意速率 出隊:固定 5 k/s → MySQL & Redis & AI 審核
- 參數:
- 漏速 L = 5 000 req/s(后端表的寫入 QPS 壓測上限)
- 桶深度 Q = 20 000(≈4 秒峰值緩沖)
- 效果:
- 當明星空降帶來 10 k/s 發布洪峰時,隊列頂多攢 4 秒即被消化。
- 如果洪峰持續更久,隊列溢出觸發降級(寫失敗重試 / 回退到異步草稿)。
- 場景:
2. 組合在小紅書的 四個高頻場景
場景 | 入口令牌桶 | 出口漏桶 | 額外策略 |
---|---|---|---|
筆記發布 | 用戶維度限流,允許一鍵連發 | 圖片轉碼、AI 審核勻速寫入 | 超隊列 10 s 回退草稿,告知稍后發布 |
點贊/收藏 | 用戶-接口維度令牌,防止機器腳本 | 點贊寫 Redis,不需要漏桶;但寫 MySQL 日志走漏桶 | 后端異步批量合并落庫 |
搜索熱詞 | IP + 用戶令牌桶,擋住爬蟲高頻搜索 | ES 查詢也做漏桶,勻速 2 k/s | 熱詞命中緩存直接返回 |
直播間打賞 | 用戶余額操作需閃電響應→入口令牌桶 + 內存預扣 | 金額入賬、流水寫賬務庫用漏桶 | 賬務庫用 XA 事務,漏速按 TPS 上限 |
3. 配置與調優步驟(落地到小紅書)
- 抓歷史峰值
- 查詢「雙 11」「618」「明星生日」當天 每 10 秒 的 QPS 波峰。
- 先配令牌桶
B ≈ R × 可接受峰值持續秒數
(可逆算為「用戶能連點多少次不被限」)。
- 測后端極限
- 對 MySQL / ES / 推薦 RPC 壓測,得出
L_max
。
- 對 MySQL / ES / 推薦 RPC 壓測,得出
- 配漏桶
L = 0.8 × L_max
預留 20 % 余量。Q = L × 回滾/降級開銷秒數
(如 4 秒)。
- 雙閾值監控
- 隊列長度 > 0.6 Q:灰度告警,加實例。
- 隊列長度 > 0.9 Q:熔斷低優接口或觸發靜默降級。
4. 代碼/配置片段示意
# 網關級(Kong / Envoy)
rate_limiting:name: notes_publish_token_bucketcapacity: 120 # Btokens_per_interval: 60 # Rinterval: 60sredis_slot: user_id# Notes Service(Go 偽碼)
leaky := NewLeakyBucket(leakRate = 5000, // LqueueDepth = 20000, // Q
)
for req := range inboundChan {if !leaky.Allow(req) {metrics.Publish("overflow")return ErrBusy // 觸發降級}process(req) // 寫庫 + 審核 + MQ
}
5 · 常見誤區 & 小紅書踩坑實錄
# | 誤區(Anti-Pattern) | 真實后果 / 事故現場 | 根因分析 & 解決策略 |
---|---|---|---|
1 | 只做令牌桶,不做漏桶 | 2024 年某明星直播帶貨高峰,瞬時發帖 QPS 從 3 k 飆到 12 k;MySQL 主從延遲 30 s,導致點贊丟失、推薦時序錯亂 | 令牌桶放行突發,卻沒人“剎車”數據庫 → 下游被沖垮 |
2 | 漏桶漏速設太小 | 春節活動,漏速僅 2 k/s;排隊深度 20 k 很快塞滿,發布接口耗時 > 10 s,被大量用戶投訴卡頓 | 峰值持續時間被低估;隊列深度設計與峰值不匹配 |
3 | 把漏桶做在網關層“全局公用” | 統一隊列里既有搜索也有發帖;一次搜索風暴讓發帖延遲 5 s——出現“木桶效應” | 業務優先級不同,卻共用同一桶 |
4 | 令牌桶容量(B)設過大 | 群控腳本低頻養號,10 min 內攢滿 600 token,隨后一鍵爆發 → 機器流量混在真人里逃過風控 | 運維按“用戶體驗”放大 B,卻忽視惡意攢桶 |
5 | 令牌桶按 IP 而非用戶限流 | 學校/公司 NAT 出口下所有用戶共享同一 IP,晚高峰點贊被誤殺(429) | 多人共用 IP → token 爭搶 |
6 | 漏桶沒有溢出策略 | 活動推送 Bug 觸發 50 k/s 寫庫,隊列溢出后 JVM 直接 OOM | 隊列滿時仍強行入列 |
7 | 未監控桶內指標 | 一次 Gradual Release 沒人關注隊列水位,5 分鐘后才發現 MySQL 延遲;事故擴大 | 隊列長度、等待時長無可觀測 |
8 | 跨機房分布式令牌桶未同步 | A 機房峰值被擋住,B 機房因未同步令牌被打爆;兩邊用戶體驗不一致 | 本地緩存令牌導致“各自為政” |
9 | 漏桶排隊里混入長耗時任務 | AI 審核超時 2 s,阻塞后面的 1000 條快速寫入請求 | 漏桶只是勻速出隊,內部仍可能被慢請求“撐爆” |
10 | 冷熱啟停未預熱令牌桶 | 服務重啟后令牌桶空,導致 10 s 內 90 % 用戶請求 429 | 冷啟動沒有令牌 |
經驗總覽:先用數據推“峰值 × 持續時間”,再對照下游極限設 B, R, L, Q;并且 每個微服務自己兜底、監控可觀測、溢出有降級。