1. 程式人生 > >請問你知道分散式系統設計模式的最低水位線思想麼?

請問你知道分散式系統設計模式的最低水位線思想麼?

# 最低水位線(Low-Water Mark) 最低水位線是指在 WAL(Write Ahead Log)預寫日誌這種設計模式中,標記在這個位置之前的日誌可以被丟棄。 ## 問題背景 WAL(Write Ahead Log)預寫日誌維護了對於儲存的每次更新,隨著時間不斷增長,這個日誌檔案會變得無限大。[Segmented Log 分割日誌](https://juejin.im/post/6874916427195908109)這種設計模式可以讓我們每次只處理一個更小的檔案,但是日誌如果不清理,會無休止增長以至於硬碟被佔滿。 ## 解決方案 最低水位線這種設計模式會告訴系統哪一部分的日誌可以被刪除了,即在最低水位線之前的所有日誌可以被清理掉。一般的方式是,程式內有一個執行緒執行一個定時任務,不斷地檢查哪一部分的日誌可以被清理並且刪除這些日誌檔案。 ``` this.logCleaner = newLogCleaner(config); this.logCleaner.startup(); ``` 這裡的 LogCleaner 可以用定時任務實現: ``` public void startup() { scheduleLogCleaning(); } private void scheduleLogCleaning() { singleThreadedExecutor.schedule(() -> { cleanLogs(); }, config.getCleanTaskIntervalMs(), TimeUnit.MILLISECONDS); } ``` ## 基於快照的最低水位線實現以及示例 大部分的分散式一致性系統(例如 Zookeeper(ZAB 簡化 paxos協議),etcd(raft協議)),都實現了快照機制。在這種機制下,他們的儲存引擎會定時的進行全量快照,並且記錄下快照對應的日誌位置,將這個位置作為最低水位線。 ``` //進行快照 public SnapShot takeSnapshot() { //獲取最近的日誌id Long snapShotTakenAtLogIndex = wal.getLastLogEntryId(); //利用這個日誌 id 作為標識,生成快照 return new SnapShot(serializeState(kv), snapShotTakenAtLogIndex); } ``` 當生成了快照併成功儲存到了磁碟上,對應的最低水位線將用來清理老的日誌: ``` //根據位置獲取這個位置之前的所有日誌文