Disgn

加入購物車限流器

單位時間內,限制可以加入購物車的數量

兩層票匣(Token Bucket)+ 秒級時間窗

可以把每個方塊視為「某個時間窗內允許的票(tokens)」:

  • By SkuId 的票匣:每個 SKU 每秒最多 100 次加入(圖的 100 只是示意)。同一秒內,第 101 個想加的,因為他拿不到票,就被「請稍後再試」。

  • By ShopId 的票匣:同一商店合計每秒最多 1000 次加入。即使很多 SKU 分散加,也不能超過商店總上限,避免把該商店的後端資源用光。

  • 時間軸(1s、2s、3s、…、ns):代表「固定秒級視窗」或「每秒補票」。每過一秒,票匣重新裝滿(或按速率補票),下一秒再算。

🌳 「要通過,得同時有 Sku 的票 + Shop 的票」。任一票用完就被擋

〈每家店獨立設定〉—配額可調、資源隔離

Shop A、Shop B 各自一套配額

  • A 店的白/藍/黃(SKU)可以是每秒 100。
  • B 店的大小中 SKU 也各有每秒 100。

營運面可調。大店、熱門品給高一點;新店、長尾品給保守值。

把限流放在「加入購物車」前段,Fail-fast

  • 按下加入
  • 檢查庫存(若庫存 0,直接顯示缺貨)
  • 檢查商店總票匣(超額就彈「流量太熱」)
  • 檢查單 SKU 票匣(超額同樣彈窗)
  • 加入購物車檢查(各種商務/資料校驗)
  • 執行加入購物車(真的落 DB / 寫快取)
  • 成功進購物車 P1;若任一步失敗,回原失敗情境彈窗

🌳 限流檢查在昂貴操作之前,把「貴的那段」流量打薄。

只控「量」,不保證「公平」

問題 : 現設計針對 Shop/SKU 配額,不分人。腳本/機器人能搶先把票用完,真人一直被彈
改進:加入 per-user / per-IP / per-device 子限額 或 優先級(登入會員 > 未登入),甚至提供虛擬排隊(Queue with ticket + ETA),提高體感公平性

固定秒級視窗問題

規則:每個視窗(整秒)最多 100 次加入。
兩個視窗:[0.0000.999…] 與 [1.0001.999…],各自獨立計數、到整秒就歸零。

事件時間線(真實尖峰常發生在邊界)

0.980s ~ 0.999s:使用者/機器人猛戳,來了 100 次

視窗 [0,1):計數 = 100 → ✅ 合法(剛好到上限)

1.000s ~ 1.010s:一到下一秒,又再來 100 次

視窗 [1,2):計數 = 100 → ✅ 合法(新的秒又可用 100)

固定視窗只看「各秒內」有沒有超過 100。
結果:30 毫秒內(0.980~1.010)實際放行了 200 次。

把 200 次塞進 0.03 秒,等效瞬時吞吐量 = 200 / 0.03 ≈ 6,666 次/秒。
後端其實只有「平均 100/s 的胃口」,卻被「秒交界」放大成超高瞬時尖峰,DB/促銷/購物車那一刻就可能被壓壞;體感上也會變成有人秒通、有人被擋的隨機性。

滑動視窗(rolling window)

固定視窗只在固定邊界判斷;滑動視窗則「隨時」往回看過去一段時間,因此能精準限制「任意時刻的平均速率」,消除跨邊界爆衝問題

個人化資料限流器 / 機器人阻擋限流器

一種防禦性限流模式(defensive rate-limiting)

秒級固定視窗(或滑動視窗)

每 1 秒(CacheSeconds=1)允許 100 次。超過 100 次,就擋掉本秒多餘請求,但下一秒又可以重新計算。

  • 對象通常是「公共資源」或「整體流量」,如加入購物車、查庫存
  • 每秒重置,沒有懲罰期
  • 屬於「速率控制(rate limiting)

鎖定型限流(Lock-based)

若在 1 秒內(CacheSeconds=1)連續打 3 次,之後 30 秒內直接鎖帳號/IP/裝置,不讓再打

  • 用於「個人化/風控防禦」,例如防暴力登入、機器人點擊
  • 屬於「懲罰式限流(lockout)」,不是單純速率限制
  • 有暫時封鎖期(LockedSeconds)
面向 模式 A(滑動/固定視窗) 模式 B(鎖定型)
目的 控制系統總流量,防止尖峰打掛 阻擋異常或惡意重複請求
判斷對象 一般是全域 (By ShopId / SKU) 個人或裝置 (By MemberId / IP)
視窗設計 每 1 秒(可滑動),達上限就拒絕但下一秒恢復 若短時間內超標,進入封鎖期
行為反應 達上限 → 暫時拒絕或排隊 達上限 → 直接鎖 N 秒,不再判斷
效果 平滑流量、減少尖峰 防暴力攻擊、阻止刷請求
對使用者影響 一秒後可重試 被鎖後必須等整個封鎖期結束
範例場景 加入購物車、秒殺活動 登入驗證、發送簡訊驗證碼、防爬蟲

熔斷 Circuit Breaker

當某個外部服務或第三方 API 不穩定、連線變慢或頻繁出錯時,熔斷機制會「主動暫停呼叫那個服務」,避免整個系統被拖垮
電流太大 → 保險絲會燒掉 → 阻止更多電流流過 → 避免整棟房子跳電。系統裡的「熔斷」就是在保護主系統不要被拖垮

點數中心熔斷

→ 當點數中心(例如:積分計算、優惠折抵)出現異常時,
熔斷機制會讓主流程(購物→結帳)繼續運作,
暫時不去呼叫點數中心 API。
✅ 好處:用戶還能繼續結帳,不會卡在點數錯誤。

第三方會員中心熔斷

→ 當連接第三方會員(例如康是美、美會員中心)出錯時,
系統暫時停用該功能,
✅ 以免每次請求都 timeout 造成整個網站卡住。

熔斷過於敏感

30 秒內錯 5 次就熔斷,對流量高的 API(如積分查詢)來說太容易觸發。
改成「基於錯誤比例」的判斷(例如錯誤率 > 50% 才熔斷)。

恢復間隔時間過長

熔斷後要等 60~120 秒才恢復,可能導致暫時性錯誤被放大。建議採「指數回退(Exponential Backoff)」或「半開模式(Half-Open Test)」機制,
讓系統能更智慧地嘗試恢復。

Timeout 差異大導致體驗不一致

MWeb 30 秒、App 5 秒,造成「App 顯示錯誤但網頁成功」的情況。
建議統一用戶端 Timeout 邏輯,或在 API 層統一 Timeout 控制。

系統間依賴關係複雜時難以掌控

多個熔斷點(例如點數中心、會員中心)若同時啟動,整體流程會變得不可預期(例如結帳流程可能失去折扣、積分)。整體流程一致性下降,商業邏輯容易出錯

排隊機制