v0.7.0

壓縮與垃圾回收

最後更新

本頁說明 ToriiDB 如何把資料庫重寫成新的 snapshot、移除被取代的檔案,以及 Store.Close() 關閉時做了什麼。

壓縮

compact() 只在持有資料庫寫鎖時執行(來自寫入路徑或 Store.Close()):

步驟 動作
1 重播失敗時以 loadErr 拒絕,避免不完整的 map 覆蓋良好的 snapshot
2 無資料且資料庫目錄不存在時略過
3 將未過期項目序列化到 N.snap.tmp,執行 write + fsync + close
4 os.Rename 為 N.snap,再對目錄 fsync
5 開啟 N+1.log 並換上,之後才關閉舊 log
6 於背景執行垃圾回收

N 是目前的 log 編號。直接使用 os.Rename,因為 go-pkg 的搬移函式在跨裝置時會退化為複製 + 刪除,不是原子操作。先開新 log 再關舊 log,資料庫就不會出現 log handle 為 nil 的空窗。

序列化以 CreatedAt 作為時間戳且不帶 UpdatedAt,因此從 snapshot 重啟後,項目不會有更新時間。

垃圾回收

壓縮成 snapshot N 後,會刪除 < N-1 的 snapshot 與 <= N-1 的 log。前一世代(N-1.snap + N.log)保留在磁碟上,作為重播的退回來源。

Store.Close() 以 sync.Once 保證冪等,並對每個已載入資料庫:

  1. 等待背景向量工作。
  2. 停止過期計時器。
  3. 在寫鎖下壓縮。
  4. 僅在壓縮成功時同步執行垃圾回收,因為背景 goroutine 在 process 結束前不會被排程。
  5. 關閉 log 檔。

回傳第一個壓縮錯誤。壓縮失敗時略過垃圾回收,可避免一個異常的高編號 snapshot 導致有效的舊檔案被刪除。

相關頁面

EN