RegionServer拆分實現(xiàn)
由于寫入請求由區(qū)域服務(wù)器處理,它們累積在一個名為memstore的內(nèi)存存儲系統(tǒng)中。一旦memstore填充,它的內(nèi)容就會作為附加的存儲文件寫入磁盤。這個事件被稱為memstore刷新。當存儲文件堆積時,RegionServer會將它們壓縮成更少、更大的文件。每次刷新或壓縮完成后,該區(qū)域中存儲的數(shù)據(jù)量將發(fā)生變化。RegionServer會咨詢區(qū)域拆分策略,以確定該地區(qū)是否因為其他策略特定的原因而變得太大或應(yīng)該拆分。如果策略建議,則區(qū)域拆分請求排隊。
從邏輯上講,分割區(qū)域的過程很簡單。我們在該區(qū)域的密鑰空間找到一個合適的點,我們應(yīng)該將該區(qū)域分成兩半,然后在該點將區(qū)域的數(shù)據(jù)分成兩個新的區(qū)域。然而,這個過程的細節(jié)并不簡單。當發(fā)生拆分時,新創(chuàng)建的子區(qū)域不會立即將所有數(shù)據(jù)重新寫入新文件。相反,他們創(chuàng)建類似于符號鏈接文件的小文件,稱為引用文件,根據(jù)拆分點指向父存儲文件的頂部或底部。引用文件與常規(guī)數(shù)據(jù)文件一樣使用,但只考慮一半的記錄。如果不再有對父區(qū)域的不可變數(shù)據(jù)文件的引用,則只能分割該區(qū)域。這些引用文件通過壓縮逐漸清理,以便該地區(qū)將停止引用其父文件,并且可以進一步拆分。
盡管拆分區(qū)域是由RegionServer做出的本地決定,但拆分過程本身必須與許多參與者協(xié)調(diào)。RegionServer在拆分之前和之后通知Master,更新.META.表以便客戶端可以發(fā)現(xiàn)新的子區(qū)域,并重新排列HDFS中的目錄結(jié)構(gòu)和數(shù)據(jù)文件。拆分是一個多任務(wù)過程。為了在發(fā)生錯誤時啟用回滾,RegionServer會保留關(guān)于執(zhí)行狀態(tài)的內(nèi)存日志。RegionServer拆分過程說明了RegionServer執(zhí)行拆分所采取的步驟。每個步驟都標有其步驟編號。來自RegionServers或Master的操作顯示為紅色,而來自客戶端的操作顯示為綠色。
下圖為RegionServer拆分過程:

- RegionServer決定在本地拆分區(qū)域,并準備拆分。拆分已開始。作為第一步,RegionServer獲取表上的共享讀鎖定,以防止在拆分過程中修改架構(gòu)。然后它在zookeeper下的/hbase/region-in-transition/region-name創(chuàng)建一個znode,并將znode的狀態(tài)設(shè)置為SPLITTING。
- Master開始了解znode,因為它有一個父region-in-transitionznode的觀察器。
- RegionServer在HDFS中的父級region目錄下創(chuàng)建一個子目錄.splits。
- RegionServer關(guān)閉父區(qū)域并在其本地數(shù)據(jù)結(jié)構(gòu)中將區(qū)域標記為離線。拆分區(qū)域現(xiàn)在處于離線狀態(tài)。在這一點上,來到父區(qū)域的客戶端請求將拋出NotServingRegionException??蛻舳藢⒅卦囈恍﹤浞?。關(guān)閉區(qū)域被刷新。
- RegionServer在.splits目錄下為子區(qū)域A和B創(chuàng)建地區(qū)目錄,并創(chuàng)建必要的數(shù)據(jù)結(jié)構(gòu)。然后,它會拆分存儲文件,因為它會在父區(qū)域中為每個存儲文件創(chuàng)建兩個引用文件。這些引用文件將指向父區(qū)域的文件。
- RegionServer在HDFS中創(chuàng)建實際的區(qū)域目錄,并為每個子區(qū)域移動引用文件。
- RegionServer向.META.表發(fā)送一個Put請求,并將.META.表中的父級設(shè)置為離線,添加有關(guān)子區(qū)域的信息。在這一點上,.META.中的子區(qū)域?qū)⒉粫袉为毜臈l目??蛻舳藢⒖吹礁竻^(qū)域在掃描.META.時被拆分。但直到他們出現(xiàn)在.META.其中才會知道這些子區(qū)域。此外,如果Put到.META.成功后,父區(qū)域?qū)行У夭鸱?。如果RegionServer在此RPC成功之前失敗,則Master和下一個Region Server打開該區(qū)域?qū)⑶宄嘘P(guān)區(qū)域拆分的不干凈狀態(tài)。更新.META.之后,區(qū)域分割將由Master進行前滾。
- RegionServer并行打開子區(qū)域A和B.
- RegionServer將子區(qū)域A和B添加到.META.,連同它承載區(qū)域的信息。拆分區(qū)域現(xiàn)在處于在線狀態(tài)。在此之后,客戶端可以發(fā)現(xiàn)新的區(qū)域并向他們發(fā)出請求??蛻舳嗽诒镜鼐彺?META.條目,但是當他們向RegionServer或者.META.發(fā)出請求時,他們的緩存將失效,他們將從.META.中了解新的區(qū)域。
- RegionServer更新ZooKeeper中的znode /hbase/region-in-transition/region-name以表示狀態(tài)SPLIT,以便主服務(wù)器可以了解它。必要時,平衡器可以自由地將子區(qū)域重新分配給其他區(qū)域服務(wù)器。拆分事務(wù)現(xiàn)在已完成。
- 拆分之后,.META.和HDFS仍將包含對父區(qū)域的引用。在子區(qū)域中進行壓縮重寫數(shù)據(jù)文件時,這些引用將被刪除。主服務(wù)器中的垃圾收集任務(wù)會定期檢查子區(qū)域是否仍然引用父區(qū)域的文件。否則,父區(qū)域?qū)⒈粍h除。
更多建議: