作者: Unmesh Joshi
譯者: java達(dá)人
預(yù)寫日志中的索引,表示可以丟棄日志的哪一部分。
問題
預(yù)寫日志維護(hù)對持久性存儲的每一次更新。隨著時間的進(jìn)展,它會無限制地增長。Segmented Log允許一次處理較小的文件,但是如果不檢查,總磁盤存儲量將無限制增長。
解決方案
有一種機制可以告訴日志記錄機器可以安全地丟棄日志的哪一部分。該機制提供了最低的偏移量或low water mark,在此之前的日志可以丟棄。讓任務(wù)在后臺的單獨線程中運行,該任務(wù)連續(xù)檢查可以丟棄日志的哪一部分并刪除磁盤上的文件。
this.logCleaner = newLogCleaner(config);this.logCleaner.startup();
日志清理器可以實現(xiàn)為定時任務(wù)
public void startup() { scheduleLogCleaning();}
private void scheduleLogCleaning() { singleThreadedExecutor.schedule(() -> { cleanLogs(); }, config.getCleanTaskIntervalMs(), TimeUnit.MILLISECONDS);}基于快照的Low-Water Mark
大多數(shù)共識實現(xiàn)(例如Zookeeper或etcd(在RAFT中定義))都實現(xiàn)了快照機制。在此實現(xiàn),存儲引擎需要定期快照。除快照外,它還存儲成功應(yīng)用的日志索引。參考“Write-Ahead Log”模式中的簡單鍵值存儲實現(xiàn),可以采取以下快照:
public SnapShot takeSnapshot() { Long snapShotTakenAtLogIndex = wal.getLastLogEntryId(); return new SnapShot(serializeState(kv), snapShotTakenAtLogIndex);}
一旦快照成功保存在磁盤上,日志管理器將獲得Low-Water Mark,以丟棄較舊的日志。
List<WALSegment> getSegmentsBefore(Long snapshotIndex) { List<WALSegment> markedForDeletion = new ArrayList<>(); List<WALSegment> sortedSavedSegments = wal.sortedSavedSegments; for (WALSegment sortedSavedSegment : sortedSavedSegments) { if (sortedSavedSegment.getLastLogEntryId() < snapshotIndex) { markedForDeletion.a(chǎn)dd(sortedSavedSegment); } } return markedForDeletion;}基于時間的Low-Water Mark
在某些系統(tǒng)中,不一定要使用日志來更新系統(tǒng)狀態(tài),可以在給定的時間窗口后丟棄日志,而不必等待任何其他子系統(tǒng)共享可以刪除的最低日志索引。例如,在像Kafka這樣的系統(tǒng)中,日志將保留7周;消息時間超過7周的所有日志段都將被丟棄。對于此實現(xiàn),每個日志條目還包括創(chuàng)建時的時間戳。然后,日志清理器可以檢查每個日志段的最后一個條目,并丟棄早于配置的時間窗口的日志段。
private List<WALSegment> getSegmentsPast(Long logMaxDurationMs) { long now = System.currentTimeMillis(); List<WALSegment> markedForDeletion = new ArrayList<>(); List<WALSegment> sortedSavedSegments = wal.sortedSavedSegments; for (WALSegment sortedSavedSegment : sortedSavedSegments) { if (timeElaspedSince(now, sortedSavedSegment.getLastLogEntryTimestamp()) > logMaxDurationMs) { markedForDeletion.a(chǎn)dd(sortedSavedSegment); } } return markedForDeletion;}
private long timeElaspedSince(long now, long lastLogEntryTimestamp) { return now - lastLogEntryTimestamp;}
例子
?所有共識算法(例如Zookeeper和RAFT)中的日志實現(xiàn)均實現(xiàn)基于快照的日志清理
?Kafka中的存儲實現(xiàn)遵循基于時間的日志清理
-
分布式系統(tǒng)
+關(guān)注
關(guān)注
0文章
146瀏覽量
19280 -
Mark
+關(guān)注
關(guān)注
0文章
17瀏覽量
8406
發(fā)布評論請先 登錄
相關(guān)推薦
評論