您好,登錄后才能下訂單哦!
這篇文章主要講解了“怎么實現Apache Bookkeeper中的Journal”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“怎么實現Apache Bookkeeper中的Journal”吧!
充當WAL
寫請求處理:
首先在Bookkeeper服務端收到了寫Entry的請求之后會交給Bookie
來處理
Bookie.addEntryInternal
這個方法會將請求攜帶的Entry信息寫入LedgerStorage
(實際數據存儲的位置 + 索引)
寫入成功之后還會同時將這個請求寫入Journal
。
其他重要信息:比如說Ledger
被fence的信息、LAC等。
啟動的時候將WAL進行replay,將記錄在journal里面的內容重新apply到LedgerStorage
里面,
避免之前寫入LedgerStorage
的內容因為沒有刷盤導致丟失。
checkpoint 邏輯
和其他WAL一樣,需要記錄一個位置,這個位置標識著LedgerStorage
里面的數據已經全都落盤了
這一個位置之前的WAL日志都可以被刪除。
維護JournalChannel
邏輯,寫入WAL日志,日志輪轉等。
整個寫入是異步的,寫入結果通過callback進行后續處理。
寫入的參數會封裝成為一個QueueEntry
放到寫請求隊列
class QueueEntry { // 內容 ByteBuf entry; long ledgerId; long entryId; // 寫結果的callback WriteCallback cb; // 進入隊列的時間,用來確定是否等待時間過長 long enqueueTime; // 是否需要等內容落盤 boolean ackBeforeSync; }
這個隊列會被一個線程定期處理,這里先叫做BookieJournalWriteThread
好了(實際沒有這個類)
取出之后會將攜帶的ByteBuffer
寫入到JournalChannel
里面。這個線程專門處理這個邏輯,
其他的活不干。
這里先說下JournalChannel
這個類,這個類可以認為是底層journal磁盤文件的映射,
內部實現是一個帶讀寫緩存的FileChannel
, 寫入的時候先到寫緩存,
有相應的邏輯主動觸發寫緩存寫到包裝的FileChannel
里面。
QueueEntry
的字節寫入之后,可能內容在寫緩存里面。
我們需要觸發flush邏輯,將寫緩存的內容寫到FileChannel
里面。
這里flush和 sync 到磁盤不是一個說法。
flush 是調用FileChannel.write
為了減少調用次數
sync 是調用FileChannel.force
為了fsync 到磁盤
這里觸發flush的條件有3種:
時間bound:這個請求入隊之后,一段時間之后必須被處理(寫入到channel或者落盤)
寫請求的個數 || 累積的寫請求的字節數
寫請求隊列為空(一般測試的時候出現這個,寫請求很少的情況下大部分都會被1這個條件兜底)
滿足flush 條件則會主動將寫緩存的內容刷到FileChannel
里面。
如果不需要等待內容落盤(ackBeforeSync=false),則直接將callback提交到線程池執行回調。
之后寫請求被放到一個等待flush的batch里面。
flush邏輯做完之后,會去判斷是否需要落盤。
按照配置有下面幾種條件需要落盤。
每次flush都需要落盤。
journal 文件輪轉,需要把之前的文件落盤。
按照配置的interval 落盤。
如果需要落盤則這個時候會將之前的batch 封裝成為一個ForceWriteRequest
放到落盤隊列里面。
這個隊列會被ForceWriteThread
清空。
這里可以配置一個groupCommit
的邏輯。避免多次fsync
。
如果配置了這個則會將隊列里面的請求合并到一起,觸發單次的FileChannel.force
同樣,落盤之后會將之前的callback 放到線程池去處理回調。
這個邏輯比較簡單,就是啟動的時候把這個文件的內容從上次成功checkpoint的位置開始讀取。
把讀到的內容再次寫入到LedgerStorage
里面就ok。
這個實際上和LedgerStorage
這個是聯動的,如果這一段WAL上面的內容,已經被LedgerStorage
成功寫到磁盤上了,那么這段WAL就可以被刪除了。
這里會有一個LastLogMark
文件,標記了(journal文件,offset)表示這個文件在這個offset之前的內容可以被干掉了。
Journal
這個類實現了CheckpointSource
這個接口。
實際動作由SyncThread
(實現了Checkpointer
接口)執行。
每種LedgerStorage
的checkpoint觸發條件不同。
entryLogPerLedgerEnabled || isDbLedgerStorage 會按照時間interval 定期觸發checkpoint
InterleavedLedgerStorage 會在日志輪轉的時候觸發
SortedLedgerStorage 會在memtable 需要flush的時候觸發
實際邏輯比較簡單
public void checkpoint(Checkpoint checkpoint) { // ... ledgerStorage.checkpoint(checkpoint); checkpointSource.checkpointComplete(checkpoint, true); // ... }
checkpointComplete 這個方法會刷新磁盤上的LastLogMarker
這個文件,同時落盤。
(主要邏輯在LedgerStorage.checkpoint
這里)
這里的磁盤是LedgerStorage的磁盤
寫入請求處理是異步的,提交之后就會被Journal線程處理。
Journal線程負責將內容寫入Journal channel,同時按照一定條件執行flush邏輯。
如果判斷需要進行刷盤則將刷盤batch包裝成ForceWriteRequest
ForceWriteThread
清理隊列進行group commit 處理。負責journal落盤。
對于寫請求的callback不會在這兩個執行,會被額外提交到callback線程池處理。
感謝各位的閱讀,以上就是“怎么實現Apache Bookkeeper中的Journal”的內容了,經過本文的學習后,相信大家對怎么實現Apache Bookkeeper中的Journal這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。