該文主要介紹了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/,,-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/
這個臨時edit檔案用來儲存該region在wal檔案中的所有edit記錄。一旦拆分結束後,這個臨時檔案將被重新命名為如下的形式:
/hbase/
上面的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啟動乙個執行緒來讀取並拆分這個日誌檔案。
自動裝箱 自動拆箱 裝裝裝 拆拆拆
public class testautobox 快取 128,127 實際就是系統初始的時候,建立了 128,127 之間的乙個快取陣列 當我們呼叫valueof 時候,首先檢查是否在 128,127 之間,如果在這個範圍則直接從快取陣列中拿出已經建好的物件 如果不在這個範圍,則建立新的integ...
swift 可選型別,強制拆包,隱性拆包
當我們不知道變數的值時,可以將改變量設定為可選型別 表明str是可選型別 string型別或者nil型別 var str string?表明str是可選型別 是string型別或者nil型別 var str string?hello world str str?uppercasestring 拆包 ...
裝箱和拆箱,自動裝箱和自動拆箱
以integer的建立為例。裝箱 把基本資料型別轉換成包裝類物件 int integer integer num1 new integer 17 拆箱 把乙個包裝類的物件,轉換成基本型別的變數 integer int int num2 num1.intvalue 自動裝箱 integer num3 ...