文件 v1.0.0

恢復回灌

本頁說明 Redis 恢復後,fallback 期間的資料如何從本地檔案經記憶體寫回 Redis,以及哪些項目不會被寫回。

步驟

changeToNormalMode(sync.go:50-92)依序執行:

步驟 動作 失敗時
1 走訪 {DBPath}/{DB} 下所有 .json 檔 目錄不存在等錯誤 → 整個流程中止,isHealth 維持 false
2 逐檔讀取並解析為 Cache,以 Cache.Key 寫入記憶體快取 單檔讀取或解析失敗 → 記錄錯誤、略過該檔
3 syncMemoryToRedis:遍歷整個記憶體快取,以 Pipeline 寫回 Redis Pipeline 執行錯誤不檢查
4 cleanupLocalFile:刪除所有 .json 檔與空子目錄(保留 {DBPath}/{DB} 本身) 單檔刪除失敗 → 記錄錯誤、繼續
5 isHealth = true —

寫回規則

syncMemoryToRedis(sync.go:94-133):

項目 規則
範圍 記憶體快取中所有未過期項目,包含 fallback 前就在記憶體裡的項目
Redis TTL Timestamp + TTL − now 秒(剩餘時間)
剩餘 TTL ≤ 0 不寫入;未設 TTL(ttl = 0)的項目也落在這裡
批次 每 100 個未過期項目執行一次 Exec,最後不足 100 的再執行一次
寫入格式 Data 的 JSON(字串去掉引號),與 Set 相同
並行保護 isRecovering 以 CAS 確保同時只有一個回灌;已在執行時直接返回

實測結果

Redis 失聯期間寫入兩個鍵,再讓 Redis 恢復:

鍵 寫入 恢復後 Redis 恢復後本地檔
ttlkey Set("ttlkey", "t", time.Hour) 存在,TTL 59m59s 已刪除
forever Set("forever", "f", 0) 不存在 已刪除

forever 仍在記憶體快取中,正常模式下第一次被讀取時由 讀取修補 寫回 Redis。

資料只剩記憶體的情況

步驟 4 不論步驟 3 是否成功都會刪除本地檔案。下列情況發生後,資料只存在於記憶體快取,程序結束即遺失:

情況 原因
Pipeline Exec 失敗(如恢復當下 Redis 又斷線) 錯誤未檢查,檔案照刪
回灌已在執行中 第二次呼叫 syncMemoryToRedis 直接返回,但後續清檔照常執行
ttl = 0 的項目 不在批次中,靠讀取修補才會寫回

恢復後的記憶體快取

恢復完成後記憶體快取不會被清空。所有載入的項目留在記憶體,直到過期被背景掃除;正常模式的 Get 對這些鍵一律記憶體命中,不查 Redis。

EN