文件

持久化

了解 ToriiDB 如何結合記憶體狀態、append-only log、逐鍵檔案、重播、壓縮與過期清理。

儲存配置

儲存根目錄會為每個邏輯資料庫建立一個目錄:

<root>/
└── db_0/
    ├── record.aof
    └── xx/yy/zz/<md5>.json

預設根目錄為 ./tempstore.New(path) 可指定其他根目錄。啟動時會建立 16 個資料庫 descriptor,但個別資料庫目錄與 AOF handle 採延遲初始化。

記憶體狀態

每個資料庫都有一份由 sync.RWMutex 保護的 map[string]*Entry,它是執行期的主要真實來源。Entry 包含 value、偵測型別、timestamp、選用 expiration、選用 vector 與 parsed JSON cache。

資料庫彼此獨立;切換資料庫會改變 session 使用的 map 與 persistence directory。

逐鍵 JSON 檔案

每次寫入都會把完整 entry 儲存成 JSON file。路徑由 key 的 MD5 hash 推導,再拆成三層、每層兩個字元的目錄:

<root>/db_N/ab/cd/ef/abcdef....json

utils.WriteFile 會建立 parent directory、寫入同層 temporary file,再 rename 覆蓋 target。Entry writer 使用 Entry.JSON(),不直接 marshal Entry,以確保包含未匯出的 raw value。

刪除 key 時會移除 entry file;週期性過期清理也會移除對應檔案。

Append-Only Log

record.aof 每行包含一個 JSON object。每筆 AOFRecord 可含:

欄位 意義
ts 操作的 Unix timestamp
cmd SETDELEXPIREEXPIREATPERSIST
key 受影響 key
value SET 記錄的 value
expire_at 選用的絕對過期 timestamp
vector 選用的 base64 little-endian float32 vector

每次追加後都會執行 File.Sync。寫入 handler 通常在持有資料庫寫鎖時,依序更新記憶體、逐鍵檔案與 AOF。

重播

首次存取資料庫時只會呼叫一次 replayAOF。重播流程:

  1. 讀取逐行記錄。
  2. 忽略空白或格式錯誤的行。
  3. 重建 SET value 與 vector。
  4. 套用 deletion 與 expiration operation。
  5. 為 JSON value 預熱 parsed cache。
  6. 將有效 log size 記為 compaction baseline。

若 AOF 不存在,資料庫會從空狀態開始。逐鍵 JSON file 是 cache artifact;啟動重建以 AOF 為準。

壓縮

目前 AOF size 達到以下兩者較大值的兩倍時,自動觸發壓縮:

壓縮會為每個未過期 entry 寫出一筆目前的 SET 記錄,包含 expiration 與 vector,並捨棄已被取代的歷史。若沒有 entry,則移除 AOF。

Store.Close() 會等待背景向量工作、停止清理,再並行壓縮所有已載入資料庫。Graceful shutdown 時應呼叫它。

過期清理

過期會在多個層級強制套用:

路徑 行為
點讀取 將過期 entry 視為 missing,並可能從記憶體移除
掃描操作 略過過期 entry
清理計時器 每分鐘從已載入資料庫移除過期 entry 與 file
壓縮 重寫 AOF 時排除過期 entry

因此 key 在 expiration timestamp 到達時即為邏輯不存在,不必等待實體檔案刪除。

備份與還原

相關頁面

EN