Redis 防連點與短 TTL 去重

文件狀態:草稿 / 已對 new API 共同 helper
最後驗證:2026-05-07
來源:Lib/Common/RedisUtil.php, Lib/Validation/ApiValidation.php

目的

這份文件記錄程式中使用 Redis 做短時間去重、防連點或降低重複 side effect 的共同模式。

完整 API 行為仍放在各流程文件;這裡只回答 Redis key 怎麼判讀、測試與正式環境可能有什麼差異。

主要 helper

來源:

Lib/Common/RedisUtil.php

常見模式:

incrementKey(<key>, <ttl>)
isDoubleClick(<func_name>, <user_id>, <ttl = 5>)

判讀重點:

  • Redis TTL 類限制通常是短時間去重,不一定是產品層級的「每日上限」。
  • 要看呼叫端怎麼使用回傳值,不能只看到 Redis key 就判斷 API 被擋。
  • 測試環境如果 Redis 關閉或 namespace 不同,行為可能和 production 不同。

search_add 相關案例

來源:

Lib/Validation/ApiValidation.php::updateUserAccessActivity()

行為:

Redis key: access_act_<user_id>
TTL: 10 秒

用途:

  • 避免短時間內重複寫每日 access activity。
  • 成功時可能寫入 daily_access 與 UserAccess activity。
  • 這不是 search_add 提出需求次數上限。

容易誤判的地方:

  • 測試 cleanup 會處理 daily_access,但 daily_access 不是發案上限來源。
  • search_add 同分類 24 小時上限看的是 quote_requests count,不是 Redis key。

排查方式

遇到疑似 Redis 防連點時:

  1. 先找呼叫端 code,確認 key 格式、TTL 與回傳值如何使用。
  2. 確認目前環境是否啟用 Redis。
  3. 如果是 PHPUnit,確認測試是否有清 key 或隔離 namespace。
  4. 不要把短 TTL 去重誤解成長期次數上限。

文件補充規則

新增 Redis 類限制時,至少寫:

欄位說明
key 格式例如 access_act_<user_id>
TTL秒數
呼叫端哪個 API / helper 使用
超過限制行為直接回 error、return early、或只是不寫 side effect
環境差異Redis 開關、namespace、測試 cleanup