題干與適用場景
系統希望在同一個 Redis hash 中保存多個欄位,但每個欄位的有效期不同。請說明如何使用 HEXPIRE、如何處理續期條件、讀取過期狀態、記憶體回收、舊版本相容和恢復。不要只寫命令語法。
面試官考察點
- 是否理解 Redis 7.4 的過期粒度從 key 擴展到 hash field。
- 是否能正確使用 NX、XX、GT、LT 條件並解釋回傳值。
- 是否考慮過期刪除時機、讀寫競態、通知、持久化和記憶體預算。
- 是否能設計版本探測、降級、監控和資料恢復方案。
回答前需要釐清的問題
- 欄位是否允許獨立過期,還是必須整體原子地更新多個欄位?
- TTL 是依業務事件計算,還是固定到期時間?重複寫入能否延長有效期?
- 過期後業務要回傳缺失、預設值,還是觸發重新計算?是否需要過期事件?
- Redis 版本、叢集模式、持久化方式和舊客戶端是否支援欄位級 TTL?
30 秒回答框架
我會先確認欄位獨立生命週期是否值得保留在同一個 hash 中,再為每個欄位定義 TTL、續期條件和缺失語義。HEXPIRE 可按欄位設定相對秒數,並用 NX、XX、GT、LT 防止無意縮短或延長期限;命令回傳值要納入監控。上線前驗證讀取、重寫、過期通知、故障恢復和舊版本降級,不能把欄位過期誤解為定時精確刪除。
分步驟深入解答
1. 建模欄位生命週期
為每個欄位定義資料來源、最大新鮮度、續期事件和過期後的替代值。需要整體原子更新的欄位仍可放在同一 hash,但 TTL 設定和業務寫入必須在一個可重試的協議中協調。
2. 選擇續期條件
首次設定可用 NX,只在已有過期時間時更新可用 XX;GT 只接受更長 TTL,LT 只接受更短 TTL。對每個欄位記錄設定命令的回傳碼,區分欄位不存在、條件不滿足、成功更新和立即刪除。
3. 處理過期與通知
欄位過期不等於應用執行緒在精確時刻收到事件。讀取時必須接受欄位缺失,寫入時避免把舊快照重新寫回;需要驅動重算時,結合 keyspace notification 或業務佇列,並設計重複事件與遺失事件的補償。
4. 相容、監控與恢復
啟動時探測 Redis 版本和客戶端能力;不支援欄位 TTL 時可降級為獨立 key,但要明確記憶體和原子性變化。監控剩餘 TTL、條件失敗、過期事件、命中率和記憶體;從 RDB/AOF 恢復後重新核對關鍵欄位的有效期與重算任務。
高品質示範回答
我會先把每個欄位的生命週期、續期來源和過期後行為寫成協議,再判斷是否需要 hash 的共享讀取與原子更新。使用 HEXPIRE 設定欄位 TTL,首次寫入用 NX,只在已有 TTL 時更新用 XX,防止縮短或延長則分別考慮 GT 與 LT,並記錄回傳值。讀取路徑把過期欄位視為缺失,不能依賴精確時刻的刪除通知;若要觸發重算,用通知加業務佇列和冪等補償。上線前探測版本、驗證故障恢復、監控 TTL/命中率/記憶體,並準備獨立 key 降級方案。
常見錯誤
- 把
HEXPIRE當成整個 hash 的EXPIRE別名。 - 不理解 NX、XX、GT、LT,重複寫入時無意修改 TTL。
- 假設欄位會在指定秒數精確時刻被刪除並收到唯一事件。
- 忽略舊版本、客戶端和叢集相容性。
- 沒有定義欄位缺失、重算、重複通知和恢復語義。
- 只看命中率,不監控 TTL、條件失敗和記憶體回收。
追問及應對
什麼時候仍應拆成多個 key?
當欄位必須跨服務獨立原子更新、客戶端不支援欄位 TTL,或過期與存取模式更適合整 key 時,拆 key 更簡單。要把額外 key 數量、記憶體開銷和一致性成本量化。
GT 為什麼適合推薦特徵?
推薦特徵通常只能在新鮮度更高時延長有效期;GT 可拒絕更短 TTL,避免晚到的舊事件把新資料提前過期。
如何處理過期通知遺失?
通知只做加速,不做唯一事實來源。讀取未命中、定期掃描剩餘 TTL、業務水位和冪等重算佇列應共同覆蓋遺失或重複事件。