天天看點

HBase-存儲-檔案存儲結構、拆分、合并

HBase-存儲-檔案存儲結構、拆分、合并

HBase使用一個HDFS中可配置的根目錄,預設設為“/hbase”。可使用hadoop fs -lsr /hbase檢視目錄結構,檔案可以被分為兩類,一類位于HBase根目錄下,另一類位于根目錄中的表目錄下。

Flush指令可以将記憶體中的資料寫到存儲檔案中,否則就必須等插入的資料達到配置的刷寫大小。

1.根級檔案

第一組檔案是被HLog執行個體管理的WAL檔案,這些日志檔案被建立在HBase的根目錄下一個名為.logs的目錄中。對于每個HRegionServer,日志目錄中都包含一個對應的子目錄。在每個子目錄中有多個HLog檔案(因為日志滾動)。一個region伺服器的所有region共享同一組HLog檔案。

由于HDFS使用内置的append機制來追加寫入日志檔案,是以隻有等到檔案大小達到一個完整的塊時,檔案對使用者才是可見的—包括hadoop fs -lsr指令。雖然put操作的資料被安全持久化了,但目前寫入日志檔案的資料大小是稍微偏離的。

當所有包含的修改都被持久化到存儲檔案中,進而不再需要日志檔案時,它們會被放到HBase根目錄下的.oldlogs目錄中。當條件滿足配置上的門檻值會觸發日志的滾動。在十分鐘後,舊的日志檔案将被master删除,這是通過hbase.master.logcleaner.ttl屬性設定的。Master

2.表級檔案

在HBase中,每張表都有自己的目錄,其位于檔案系統中HBase根目錄下。每張表目錄包括一個名為.tabledesc的頂層檔案,該檔案存儲表對應序列化後的HTableDescriptor。其中包括表和列族的定義,同時其内容也可以被讀取。

3.region級檔案

在每張表的目錄裡面,表模式中每個列族都有一個單獨的目錄。目錄的名字是一部分region名字的MD5散列值。

Region檔案的總體結構是

/<hbase-root-dir>/<tablename>/<encoded-regionname>/<column-family>/<filename>

/apps/hbase/data/data/hbase/namespace/d25b2b8cb0d3d1c538437c1b89b8f8c8/info/7aef732982e04b77b7ee2a0ef9d7adc3      

可以在每個列族目錄中看到實際的資料檔案。

Region目錄中也有一個.regioninfo檔案,這個檔案包含了對應region的HRegionInfo執行個體序列化後的資訊。與.tabledesc檔案類似,它能被外部工具用來檢視region的相關資訊。例如,HBase的hbck工具就用它來檢查并生成中繼資料表中丢失的條目。

可選的.tmp目錄是按需求建立的,它被用來存放臨時檔案,例如,一次合并的重寫檔案。一旦這個過程完成,這些臨時生成的檔案通常會被移到region目錄中。

在WAL回放時,任何未送出的修改都會被寫入到每個region的一個單獨的檔案中。以上是第一步,然後如果日志拆分過程已經成功完成,這些檔案将被自動移動到臨時的recovered.edits目錄中。當region被打開時,region伺服器将會看到需要恢複的檔案,并且回放其中相應的條目。

一旦region超過了配置中region大小的最大值,region就需要拆分,其會建立一個對應的splits目錄,它被用來臨時存放兩個子region相關的資料。如果拆分過程成功,之後它們會被移動到表目錄中,并形成兩個新的region,每個region代表原始region的一半。

當看到一個region的目錄中沒有.tmp目錄,這就意味着還沒有進行過壓縮操作。如果沒有recovered.edits目錄,這就意味着WAL還沒有進行過回放操作。

4.region拆分

當一個region裡的存儲檔案增長到大于配置的hbase.hregion.max.filesize大小或者在列族層面配置的大小時,region會被一分為二。這個過程通常非常迅速,因為系統隻是為新region建立了兩個對應的檔案,每個region是原始region的一半。

Region伺服器通過在父region中建立splits目錄來完成這個過程。接下來關閉該region,此後這個region不再接受任何請求。

然後region伺服器通過在splits目錄中設立必須的檔案結構來準備新的子region(使用多線程),包括新region目錄和參考檔案。如果這個過程成功完成,它将把兩個新region目錄移到表目錄中。.META.表中父region的狀态會被更新,以表示其現在拆分的節點和子節點是什麼。以上過程可以避免父region被意外重新打開。

兩個子region都準備好後,将會被同一個伺服器并行打開。打開的過程包括更新.META.表,這樣可以把兩個region像其他region一樣作為可用region列出來。之後這兩個region會上線并開始服務請求。

同時也會初始化為兩個region并對region中的内容執行合并,合并過程在替換引用檔案之前會把父region的存儲檔案異步重寫到兩個子region中。以上過程會在子region的.tmp目錄中執行。一旦生成了重寫之後的檔案,它們将自動取代引用檔案。

最終父region會被清理掉,這意味着它在.META.表中的表項會被移除,并且它在磁盤上所有的檔案都會被删除。最後,master被告知關于拆分的情況,并且可以由于負載均衡而把新region移動到其它region伺服器上。

在拆分過程中,所有的步驟都在ZK中進行跟蹤。這使得在一個伺服器失效時,其它程序可以知道這個region狀态。

5.合并

存儲檔案會被背景的管理程序仔細地監控起來以確定它們處于控制之下。随着memstore的刷寫會生成很多磁盤檔案。如果檔案的數目達到門檻值,合并(compaction)過程将把它們合并成數量更少的體積更大的檔案。這個過程持續到這些檔案中最大的檔案超過配置的最大儲存檔案大小,此時會觸發一個region拆分。

壓縮合并有兩種,即minor和major。Minor合并負責重寫最後生成的幾個檔案到一個更大的檔案中。檔案數量是由hbase.hstore.compaction.min屬性設定的。它的預設值為3,并且最小值需要大于或等于2.過大的數字将會延遲minor合并的執行,同時也會增加執行時消耗的資源及執行的時間。

Minor合并可以處理的最大檔案數量預設為10,使用者可以通過hbase.hstore.compaction.max來配置。Hbase.hstore.compaction.min.size(預設設定為region的memstore刷寫大小)和hbase.hstore.compaction.max.size(預設設定為Long.MAX_VALUE)配置項屬性進一步減少了需要合并的檔案清單。任何比最大合并大小大的檔案都會被排除在外。最小合并大小的功能稍有不同:它是一個門檻值,而不是每個檔案的限制。它包括所有小于限制的檔案,直到到達每次壓縮允許的總檔案數量。

HBase-存儲-檔案存儲結構、拆分、合并

算法使用hbase.hstore.compaction.ratio(預設為1.2,或者120%)來確定在選擇過程中包括足夠的檔案。經過跟新檔案總的存儲檔案比較之後,這個比例仍将選擇達到那個值的檔案。評估總是按照從老檔案到新檔案的順序來進行的,這樣可以確定更老的檔案首先被合并。這些屬性的組合允許使用者微調一個minor合并包括檔案的數量。

HBase支援的另外一種合并是major合并:它們把所有檔案壓縮成一個單獨的檔案。在執行壓縮檢查時,系統自動決定運作哪種合并。在memstore被刷寫到磁盤後會觸發檢查,或在shell指令compact、major_compact之後觸發檢查,或是相應API在被調用後觸發檢查,抑或是被一個異步的背景程序觸發後。Region伺服器運作這個程序,而其功能由CompactChecker類實作,它以一個固定的周期觸發檢查,這個周期由hbase.server.thread.wakefrequency參數控制(乘以hbase.server.thread.wakefrequency.multiplier,設為1000,這樣它的執行頻率不會像其他基于線程的任務那麼頻繁)。

繼續閱讀