1. 程式人生 > >HBase中Split的詳細過程

HBase中Split的詳細過程

分裂的細節並不簡單。當分裂發生時,新建立的“女兒regions”不會將所有的資料立即寫入到新檔案中。相反,它建立一些與象徵性引用檔案相似的小檔案,稱為Reference files,這些檔案根據根據切分點指向父store file的頭部或者尾部。reference file用起來和普通資料檔案沒什麼區別,但是其中只有一半的記錄。region只會在沒有引用指向父region不變的資料檔案時才會真正的分裂。reference files會在compaction的時候逐漸的被清理,這時split會發生。

雖然分裂region是RegionServer的本地行為,但分裂的過程會與很多角色相關。RegionServer在split前後通知Master,更新.META.表,這樣客戶可以發現新的“女兒regions”,並重新整理HDFS中的目錄結構與資料檔案。Splitting是一個多工的過程。為了能在發生錯誤時回滾,RegionServer維護了一個記憶體中的日誌去記錄執行狀態。

1.RegionServer在本地決定進行region分裂,準備分裂。分裂事務開始。第一步,RegionServer取得一把該表共享的讀行為鎖防止在split過程中發生模式變更。然後在zookeeper中建立一個znode放在/hbase/region-in-transition/region-name,並且將這個znode的狀態置為“SPLITTING”。

2.Master知道了這個znode,因為它有一個對父znode“region-in-transition”的觀察器。

3.在HDFS中,RegionServer在父“region”目錄下建立一個子目錄“.splits”。

4.RegionServer關閉了父region並且在本地資料結構中將該region標記為離線狀態。進行split的region現在處於離線狀態。這時候,客戶端對於父region的請求會丟擲“NotServingRegionException”錯誤。客戶端會進行重新嘗試。關閉的region會被清楚。

5.RegionServer為“女兒regions”A和B在“.splits”目錄下建立region目錄和必須的資料結構。然後分裂store files,為每個store file建立了兩個引用檔案(reference file),這兩個引用檔案會指向父region的檔案。

6.RegionServer在HDFS中建立“女兒region”真實的region目錄,並且將引用檔案(reference files)移入其中。

7.RegionServer傳送一個Put請求給.META.表,將.META.表中的父region置為離線狀態並且新增兩個“女兒region”的資訊。這時候,兩個“女兒region”不會有獨立的詞目(entry)在.META.中。客戶端如果對.META.表進行scan操作會發現父region被分裂,但是不知道關於“女兒region”的任何資訊知道她們出現在.META.表中。另外,如果Put操作成功,父region的split將會生效。如果在這個RPC操作之前RegionServer掛了,Master和接替的RegionServer會清理關於這個region分裂操作的髒狀態。直到.META.表被更新以後,region的分裂操作才會前滾。

8.RegionServer並行的開啟“女兒regionA”和“女兒regionB”

9.RegionServer將“女兒region”A和B的資訊新增進.META.表中。分裂的region(女兒region)這時候置為線上狀態。這之後,客戶端可以看到新的region並且可以向其提交請求。客戶端將.META.中的詞目(entry)快取在本地,但是當他們提交請求到RegionServer或者.META.表的時候,他們的快取將會失效,同時它們會從.META.表中看到新的region。

10.RegionServer更新ZooKeeper中znode“/hbase/region-in-transition/region-name”的狀態為“SPLIT”,這樣Master能獲取到這個資訊。如果必要的話,平衡器會把兩個“兒女region”分配到其他region server上去。split事務正式結束。

11.split過後,.META.和HDFS仍然維護一個指向父region的引用。當“女兒region”發生compact(合併)重寫資料檔案的時候這些引用會被刪除。垃圾收集器週期性的檢查“女兒region”是否有指向父region檔案的引用,如果沒有,則父region會被清除。