HBase Log Splitting(日誌拆分)

該文主要介紹了HBase在一個region server崩潰後,如何通過日誌拆分(Log Split)的方式來恢復丟失的修改,防止數據丟失的。

Log Split(日誌拆分)

HBase爲了提高寫的性能,將數據的修改先放到memstore內存中,這樣做的缺陷是當某個region server崩潰時,其memstore中的所有修改將會丟失,因爲它們還沒有被刷寫到磁盤上。爲了防止這情況造成的數據丟失,HBase的做法是在修改寫入memstore之前,先將其寫入一個稱爲"預寫日誌"(write-ahead-log,WAL)文件中。這樣在遇到一個region server崩潰後,可以通過回放(replay)WAL文件重新生成memstore中丟失的修改。

由於一個region server上會有多個region,並且這些region共享一個WAL文件。WAL文件中的每個修改(也叫做edit)都包含其屬於哪一個region的信息。當打開一個region時,將會replay這個region在WAL中的所有edits記錄,來重新生成數據。所以,在WAL文件中的所有edit都必須按region分組形成特定的集合,通過replay這些集合來對特定的region重新生成數據。像這樣在WAL文件中對edit 按region分組的過程就稱爲Log Split。

日誌拆分(Log Split)發生在集羣啓動時(由HMaster負責完成)或是在region server崩潰時(由ServerShutdownHandler負責完成),因爲HBase需要保持一致性。在日誌拆分時,受影響的region將不可用,直到拆分完成,數據完全重置。
下圖爲日誌拆分的過程:


在開始拆分日誌時,會重命名日誌目錄:/hbase/.logs/<host>,<port>,<startcode>-splitting,例如:/hbase/.logs/srv.example.com,60020,1254173957298-splitting

之所以重命名日誌目錄,主要是爲了防止region server誤寫入。因爲可能出現region server還在正常運行,但master已經認爲它已經關閉了的情況,比如region server 長時間沒有響應,造成ZooKeeper沒有收到其心跳,這種情況,HMaster會將該region server標識爲已失敗。通過重命名日誌目錄,任何可用的WAL文件仍然被使用,但不會發生誤寫入的情況。

每個日誌文件每次只能拆分一個edit記錄。日誌拆分器每次僅讀取日誌文件的中一個edit記錄,然後把每一個edit記錄放入相應region的緩衝區裏,同時日誌拆分器啓動若干個writer 線程,將緩衝區中的edit記錄寫到臨時的edit恢復文件中。臨時edit文件的路徑如下形式:
/hbase/<table_name>/<region_id>/recovered.edits/.temp

這個臨時edit文件用來保存該region在WAL文件中的所有edit記錄。一旦拆分結束後,這個臨時文件將被重命名爲如下的形式:

/hbase/<table_name>/<region_id>/recovered.edits/<sequenceid>

上面的sequenceid表示寫入文件的第一條日誌記錄的序列ID。HBase就是根據sequence ID來確定是否所有的edit都已經寫入。通過比較HFile中最後一條edit的sequence ID和該文件的sequenceid,如果前者大於或等於後者,則說明已經完全寫入。

當日志拆分結束,每一個受影響的region都會被分配到相應的region server上。當region是打開時,將會檢查recovered.edits目錄下是否有edit恢復文件,如果有,將會回放這些文件,讀取文件中的edit記錄並保存到memstore中。在所有的edit文件回放之後,將memstore中的內容刷寫到磁盤上(HFile),然後刪除這些edit文件。

在HBase 0.92版本之前,是在HMaster上通過一個線程按順序完成日誌拆分的整個過程的,但這比較耗時。從0.92版本引入了分佈式的日誌拆分,拆分的工作有master轉移到了額region服務器上,大大降低了拆分的時間。

最新的分佈式模式是通過ZooKeeper將每一個被丟棄的日誌文件分發給一個region server。這些region server 檢測ZooKeeper是否有可處理的日誌文件,它們將通過競爭,獲勝的region server啓動一個線程來讀取並拆分這個日誌文件。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章