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