深入理解HBASE(3.3)RegionServer-Region

作用

– HBase自動(dòng)把表水平劃分成多個(gè)區(qū)域(region),每個(gè)region會(huì)保存一個(gè)表 里面某段連續(xù)的數(shù)據(jù);每個(gè)表一開始只有一個(gè)region,隨著數(shù)據(jù)不斷插 入表,

  • region不斷增大,當(dāng)增大到一個(gè)閥值的時(shí)候,region就會(huì)等分會(huì) 兩個(gè)新的region(裂變);

– 當(dāng)table中的行不斷增多,就會(huì)有越來越多的region。這樣一張完整的表 被保存在多個(gè)Regionserver上。

層級(jí)結(jié)構(gòu)

  • Table (HBase 表)

  • Region(表的Regions)

    • Store(Region中以列族為單位的單元)

      • MemStore (用于寫緩存)

      • StoreFile (StoreFiles for each Store for each Region for the table) 存儲(chǔ)在磁盤上的文件(HFile)

        • Block (讀寫的最小單元)

Region分裂

1、根據(jù)rowkey來分裂定位切分點(diǎn)

那切分點(diǎn)是如何定位的呢? 整個(gè)region中最大store中的最大文件中最中心的一個(gè)block的首個(gè)rowkey 。這是一句比較消耗腦力的語句,需要細(xì)細(xì)品味。另外,HBase還規(guī)定,如果定位到的rowkey是整個(gè)文件的首個(gè)rowkey或者最后一個(gè)rowkey的話,就認(rèn)為沒有切分點(diǎn)。

什么情況下會(huì)出現(xiàn)沒有切分點(diǎn)的場(chǎng)景呢?最常見的就是一個(gè)文件只有一個(gè)block,執(zhí)行split的時(shí)候就會(huì)發(fā)現(xiàn)無法切分。很多新同學(xué)在測(cè)試split的時(shí)候往往都是新建一張新表,然后往新表中插入幾條數(shù)據(jù)并執(zhí)行一下flush,再執(zhí)行split,奇跡般地發(fā)現(xiàn)數(shù)據(jù)表并沒有真正執(zhí)行切分。原因就在這里,這個(gè)時(shí)候仔細(xì)的話你翻看debug日志是可以看到這樣的日志滴:

分割日志

2、事務(wù)性執(zhí)行分裂

HBase將整個(gè)切分過程包裝成了一個(gè)事務(wù),意圖能夠保證切分事務(wù)的原子性。整個(gè)分裂事務(wù)過程分為三個(gè)階段:prepare – execute – (rollback) ,操作模版如下:

執(zhí)行分裂的代碼

prepare階段:

在內(nèi)存中初始化兩個(gè)子region,具體是生成兩個(gè)HRegionInfo對(duì)象,包含tableName、regionName、startkey、endkey等。同時(shí)會(huì)生成一個(gè)transaction journal,這個(gè)對(duì)象用來記錄切分的進(jìn)展,具體見rollback階段。

執(zhí)行階段

  1. regionserver 更改ZK節(jié)點(diǎn) /region-in-transition 中該region的狀態(tài)為SPLITING。

  2. master通過watch節(jié)點(diǎn)/region-in-transition檢測(cè)到region狀態(tài)改變,并修改內(nèi)存中region的狀態(tài),在master頁面RIT模塊就可以看到region執(zhí)行split的狀態(tài)信息。

  3. 在父存儲(chǔ)目錄下新建臨時(shí)文件夾.split保存split后的daughter region信息。

  4. 關(guān)閉parent region:parent region關(guān)閉數(shù)據(jù)寫入并觸發(fā)flush操作,將寫入region的數(shù)據(jù)全部持久化到磁盤。此后短時(shí)間內(nèi)客戶端落在父region上的請(qǐng)求都會(huì)拋出異常NotServingRegionException。

  5. 核心分裂步驟:在.split文件夾下新建兩個(gè)子文件夾,稱之為daughter A、daughter B,并在文件夾中生成reference文件,分別指向父region中對(duì)應(yīng)文件。這個(gè)步驟是所有步驟中最核心的一個(gè)環(huán)節(jié),生成reference文件日志如下所示:

2017-08-12 11:53:38,158 DEBUG [StoreOpener-0155388346c3c919d3f05d7188e885e0-1] regionserver.StoreFileInfo: reference 'hdfs://hdfscluster/hbase-rsgroup/data/default/music/0155388346c3c919d3f05d7188e885e0/cf/d24415c4fb44427b8f698143e5c4d9dc.00bb6239169411e4d0ecb6ddfdbacf66' to region=00bb6239169411e4d0ecb6ddfdbacf66 hfile=d24415c4fb44427b8f698143e5c4d9dc。

reference文件是一個(gè)引用文件(并非linux鏈接文件),文件內(nèi)容很顯然不是用戶數(shù)據(jù)。

文件內(nèi)容其實(shí)非常簡(jiǎn)單,主要有兩部分構(gòu)成:

其一是切分點(diǎn) splitkey

其二是一個(gè)boolean類型的變量(true或者false),true表示該reference文件引用的是父文件的上半部分(top),而false表示引用的是下半部分 (bottom)。

原理
  1. 父region分裂為兩個(gè)子region后, 將daughter A、daughter B拷貝到HBase根目錄下,形成兩個(gè)新的region

  2. parent region通知修改 hbase.meta 表后下線,不再提供服務(wù)。下線后parent region在meta表中的信息并不會(huì)馬上刪除,而是標(biāo)注split列、offline列為true,并記錄兩個(gè)子region。

  3. 開啟daughter A、daughter B兩個(gè)子region。通知修改 hbase.meta 表,正式對(duì)外提供服務(wù)。

rollback階段:

如果execute階段出現(xiàn)異常,則執(zhí)行rollback操作。為了實(shí)現(xiàn)回滾,整個(gè)切分過程被分為很多子階段,回滾程序會(huì)根據(jù)當(dāng)前進(jìn)展到哪個(gè)子階段清理對(duì)應(yīng)的垃圾數(shù)據(jù)。代碼中使用 JournalEntryType 來表征各個(gè)子階段,

分裂問題

1、通過reference文件如何查找數(shù)據(jù)?

(1)根據(jù)reference文件名(region名+真實(shí)文件名)定位到真實(shí)數(shù)據(jù)所在文件路徑

(2)定位到真實(shí)數(shù)據(jù)文件就可以在整個(gè)文件中掃描待查KV了么?非也。因?yàn)閞eference文件通常都只引用了數(shù)據(jù)文件的一半數(shù)據(jù),以切分點(diǎn)為界,要么上半部分文件數(shù)據(jù),要么下半部分?jǐn)?shù)據(jù)。那到底哪部分?jǐn)?shù)據(jù)?切分點(diǎn)又是哪個(gè)點(diǎn)?還記得上文又提到reference文件的文件內(nèi)容吧,沒錯(cuò),就記錄在文件中。

文件內(nèi)容其實(shí)非常簡(jiǎn)單,主要有兩部分構(gòu)成:其一是切分點(diǎn) splitkey,其二是一個(gè)boolean類型的變量(true或者false),true表示該reference文件引用的是父文件的上半部分(top),而false表示引用的是下半部分 (bottom)。

2、父region的數(shù)據(jù)什么時(shí)候會(huì)遷移到子region目錄?

答案是子region發(fā)生major_compaction時(shí)。我們知道compaction的執(zhí)行實(shí)際上是將store中所有小文件一個(gè)KV一個(gè)KV從小到大讀出來之后再順序?qū)懭胍粋€(gè)大文件,完成之后再將小文件刪掉,因此compaction本身就需要讀取并寫入大量數(shù)據(jù)。子region執(zhí)行major_compaction后會(huì)將父目錄中屬于該子region的所有數(shù)據(jù)讀出來并寫入子region目錄數(shù)據(jù)文件中??梢妼?shù)據(jù)遷移放到compaction這個(gè)階段來做,是一件順便的事。

3、父region什么時(shí)候會(huì)被刪除?

實(shí)際上HMaster會(huì)啟動(dòng)一個(gè)線程定期遍歷檢查所有處于splitting狀態(tài)的父region,確定檢查父region是否可以被清理。檢測(cè)線程首先會(huì)在meta表中揪出所有split列為true的region,并加載出其分裂后生成的兩個(gè)子region(meta表中splitA列和splitB列), 只需要檢查此兩個(gè)子region是否還存在引用文件,如果都不存在引用文件就可以認(rèn)為該父region對(duì)應(yīng)的文件可以被刪除?,F(xiàn)在再來看看上文中父目錄在meta表中的信息,就大概可以理解為什么會(huì)存儲(chǔ)這些信息了:

META存儲(chǔ)的分裂信息

生產(chǎn)環(huán)境

【禁用自動(dòng)切分region,改用手動(dòng)切分】

上面說的都是自動(dòng)切分來實(shí)現(xiàn)的負(fù)載均衡。建議在生產(chǎn)環(huán)境中禁用自動(dòng)的split(或者將Region設(shè)置的大一點(diǎn)),然后手動(dòng)切割region,可以在晚上或者業(yè)務(wù)不忙(例如沒有大量寫操作)的時(shí)候手動(dòng)執(zhí)行split。

執(zhí)行split操作后,Hbase內(nèi)部的邏輯是:

第一輪split,遍歷所有region的信息,如果region size大于某值(比如4G)則split該region;

如果一輪后沒有大于該值的region則結(jié)束,如果還有大于該值的region則繼續(xù)新一輪split,直到?jīng)]有region大于該閾值為止。

如何判斷split已完成:檢查hdfs上老的region目錄是否已被清除來判斷split是否已完成。

Region 合并

意義

  • 當(dāng)存在大量沒有數(shù)據(jù)的region時(shí),執(zhí)行region的合并來避免region過多
  • 之所以會(huì)存在大量沒有數(shù)據(jù)的region是因?yàn)闉榱吮苊鈘egion到達(dá)閥值引起分裂的開銷,創(chuàng)建表格時(shí)先進(jìn)行預(yù)分區(qū)。

步驟

  1. 客戶端發(fā)送指令給Master
  2. Master收到指令后將要合并的region移動(dòng)到指定的RegionServer
  3. Master發(fā)送Merge請(qǐng)求給指定的RegionServer執(zhí)行合并操作
  4. 最后將被合并的regions從hbase:meta中刪除并添加合并后的region
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容