當前位置:
首頁 > 最新 > Hadoop之HBase

Hadoop之HBase

1HBase概述

HBase是一個分散式的、面向列的開源資料庫,該技術來源於Fay Chang所撰寫的Google論文——「Bigtable:一個結構化數據的分散式存儲系統」。就像Bigtable利用了Google文件系統(File System)所提供的分散式數據存儲一樣,HBase在Hadoop之上提供了類似於Bigtable的能力。

HBase是Hadoop Database的簡稱,它是Apache的Hadoop項目中的一個子項目,HBase依託於Hadoop的HDFS作為其最基本的存儲單元,通過使用Hadoop的HDFS工具就可以看到這些數據存儲文件夾的結構,還可以通過MapReduce的框架對HBase進行操作。HBase不同於一般的關係型資料庫,它是一個適合於非結構化數據存儲的資料庫,另一個不同點是HBase採用基於列(更準確地說是基於列族)而不是基於行的模式。

HBase是一個數據模型,可以提供快速隨機訪問海量結構化數據的優勢,它還充分利用了Hadoop的文件系統提供的容錯能力。使用HBase在HDFS上讀取消費/隨機訪問數據,並提供讀寫訪問,如下圖所示:

2HBase的體系結構

在HBase中,表被分割成區域(Region,對應於列族),並由區域伺服器(RegionServer,對應於一個機器節點)提供服務,區域被列族垂直分為「Store_File」,Store_File又以HFile文件的形式被保存在HDFS文件系統中,下圖展示了HBase的體系結構。

Region內部解析:剛開始時數據都直接保存到mem_store內存中,待到mem_store滿時,便會flush成一個Store_File文件,直到增長到一定閾值,便會觸發Compact合併操作,將多個Store_File文件合併成一個大的Store_File文件(對應於HFile),同時進行版本合併和數據刪除;由於HDFS數據塊大小默認是128M,為了節省空間及提高效率,這個大的Store_File文件(也就是HFile),將以一個數據塊的大小128M保存到HDFS文件系統中。

HBase主要由三部分構成,即客戶端Client、主伺服器HMaster以及區域伺服器Region Server,區域伺服器可按照應用需求進行添加和刪除。

A、客戶端Client

包含訪問HBase的介面,並維護cache來加快對HBase的訪問,比如Region的位置信息等。

B、主伺服器HMaster

為Region Server分配Region;

負責Region Server的負載均衡;

發現失效的Region Server並重新分配其上的Region;

管理用戶對table的增刪改查操作。

C、區域伺服器RegionServer

Region Server維護Region,處理對這些Region的IO請求;

Region Server負責切分在運行過程中變得過大的Region。

DZookeeper

通過選舉,保證在任何時候,集群中只有一個主伺服器HMaster,HMaster與RegionServer啟動時會向Zookeeper註冊;

存儲所有Region的定址入口;

實時監控RegionServer的上線和下線信息,並實時通知給HMaster;

存儲HBase的schema和table元數據;

默認情況下,HBase管理Zookeeper實例,比如啟動或者停止Zookeeper;

Zookeeper的引入,解決了HMaster單點故障的問題。

3HBase的特點

AHBase的存儲機制

HBase是一個面向列的資料庫,在表中它由行排序,表模式定義為列族,也就是鍵值對,一個表有多個列族(需要在創建表時就指定)以及每一個列族可以有任意數量的列,後續列的值連續地存儲在磁碟上。表中的每個單元格值都具有時間戳(HBase默認添加)。總的來說,在一個HBase中:

表是行的集合;

行是列族的結合;

列族是列的集合;

列是鍵值對的集合。

舉一個HBase表的實例,其表結構如下圖所示,需要注意的是,rowkey(類似於關係型資料庫中的主鍵)是可以重複的,相同的rowkey記錄的是同一行數據;一個列族對應於一個Region。

BHBaseHDFS

兩者都具有良好的容錯性和擴展性,都可以擴展成百上千個節點。HBase適用於大數據量存儲,大數據量高並發操作,適用於需要對數據進行隨機讀寫的簡單操作;HDFS適用於批處理場景,不支持數據隨機查找,不適合增量數據處理,不支持數據更新。

下面的表格簡單地類比了HBase和HDFS。

C、面向行和面向列

面向列的資料庫是將數據表作為數據列的部分進行存儲,而不是作為數據行進行存儲;面向列的資料庫相對來說,對於大數據量的查詢操作具有較高的效率,而面向行的資料庫,對於增、刪、改這些操作具有較高的效率。下面的表格對列式資料庫和行式資料庫進行了簡單的類比。

DHBaseRDBMS

下面的表格簡單類比了基於列的資料庫HBase與通用的關係型資料庫RDBMS。

EHBase容錯性

HMaster容錯:Zookeeper重新選舉出一個新的HMaster,在沒有HMaster的過程中,數據讀取仍照常進行,但region切分、負載均衡等操作無法進行;

RegionServer容錯:定時向Zookeeper彙報心跳,如果一定時間內未出現心跳,HMaster將該RegionServer上的Region重新分配到其他RegionServer上,失效伺服器上「預寫」日誌由主伺服器進行分割並派送給新的RegionServer;

在分散式系統環境中,無法避免系統出錯或者宕機,一旦HRegionServer意外退出,mem_store中的內存數據就會丟失,引入HLog就是為了防止這種情況。其工作機制是:每個HRegionServer中都會有一個HLog對象,每次用戶操作寫入mem_store的同時,也會寫一份數據到HLog文件,HLog文件定期會滾動出新,並刪除舊的文件(對應已經持久化到Store_File中的數據)。當HRegionServer意外終止後,HMaster會通過Zookeeper感知,HMaster首先處理遺留的HLog文件,將不同Region的log數據拆分,分別放到相應Region目錄下,然後再將失效的Region(帶有剛剛拆分的log)重新分配,領取到這些Region的HRegionServer在Load Region的過程中,會發現有歷史HLog需要處理,因此會Replay HLog中的數據到mem_store中,然後flush到Store_File,完成數據恢復。

Zookeeper容錯:Zookeeper是一個可靠的服務,一般配置3到5個Zookeeper實例。

4HBase數據讀/寫流程

AHBase表數據的寫入流程

1)client先去訪問Zookeeper,從Zookeeper上獲取meta表的位置信息;

以前的版本hbase的系統表除了meta表還有root表;

在root表中存儲了meta表的位置信息;

新版本中將meta表的位置信息直接存入ZooKeeper中

2)client向meta表的region所在的regionserver發起訪問,讀取meta表的數據,獲取HBase集群上所有的表的元數據;

3)根據meta表的元數據信息(如某張表有幾個region及region如何分配及每個reigon的startkey和stopkey等),client找到當前要寫入的表對應的Region及所在RegionServer;

4)client向對應的RegionServer發起寫入請求;

5)RegionServer收到client請求並響應,client先把數據寫入到Hlog防止數據丟失;

6)再把數據寫入到mem_store內存緩存區(默認大小128M);

7)當數據寫入到Hlog及mem_store內存緩存區都成功時,寫入才算成功;

8)當mem_store達到128M或其他的因素觸發,會將mem_store中的數據flush成Store_File;

9)當Store_File越來越多,會觸發compact合併,將多個Store_File文件最終合併成一個文件;

合併分為minor compact和major compact;

在大合併期間打上『刪除』標籤的cell或者過期的cell會被統一清理

10)當某個store下的某個storeFile文件的最終合併後的大小達到10G時,會觸發整個region的split分割,一個region一分為二,由master進行分配;

BHBase表數據的讀取過程

1)client先去訪問Zookeeper,從Zookeeper上獲取meta表的位置信息;

2)client向meta表的Region所在的RegionServer發起訪問,讀取meta表的數據,獲取HBase集群上所有表的元數據;

3)根據meta表的元數據信息(如某張表有幾個Region及Region如何分配及每個Reigon的startkey和stopkey),client找到當前要寫入的表對應的Region及所在RegionServer;

4)client向對應的RegionServer發起讀請求;

5)RegionServer收到客戶端的讀請求,會先掃描mem_store,再掃描blockcache(讀緩存),沒有找到數據,再去讀取Store_File文件;

6)RegionServer將數據返回給client。

5Region分裂詳解

ARegion分裂的產生

在最初時,HBase中數據量會比較小,僅需要保存到一個Region上(如保存於下圖中的RegionServer1)。隨著數據量的增大,當HBase通過自檢查發現滿足相應的條件,觸發Region分裂(在HBase中不可避免會發生)使得Region數量變多並進行重新分布,如RegionServer1上先前的Region分裂成兩個,並將其中一個Region中的數據拷貝到其他RegionServer上的Region中,如下圖中的RegionServer2,該過程簡單描述如下圖。

因此,由於Region分裂的存在,需要採取其他必要的措施或進行合理規劃,將Region分裂產生的影響儘可能降到最低,防止對網路造成過大壓力,使整個環境崩潰。

B、尋找分裂點SplitPoint

Region分裂策略會觸發Region分裂,分裂開始之後的第一件事是尋找分裂點-SplitPoint。所有默認分裂策略,無論是ConstantSizeRegionSplit Policy、IncreasingToUpperBoundRegionSplitPolicy 抑或是SteppingSplit Policy,對於分裂點的定義都是一致的。當然,用戶手動執行分裂時是可以指定分裂點進行分裂的。

那分裂點是如何定位的呢? 整個Region中最大store中的最大文件中最中心的一個block的首個rowkey 。這是一句比較消耗腦力的語句,需要細細品味。另外,HBase還規定,如果定位到的rowkey是整個文件的首個rowkey或者最後一個rowkey的話,就認為沒有分裂點。

什麼情況下會出現沒有分裂點的場景呢?最常見的就是一個文件只有一個block,執行split的時候就會發現無法分裂。很多朋友在測試split的時候往往都是新建一張新表,然後往新表中插入幾條數據並執行一下flush,再執行split,奇蹟般地發現數據表並沒有真正執行分裂。

CRegion核心分裂流程

HBase將整個分裂過程包裝成了一個事務,意圖能夠保證分裂事務的原子性。整個分裂事務過程分為如下三個階段:prepare– execute – rollback,操作模板如下圖所示:

prepare階段:在內存中初始化兩個子Region,具體是生成兩個HRegionInfo對象,包含tableName、regionName、startkey、endkey等。同時會生成一個transactionjournal,這個對象用來記錄分裂的進展,具體見rollback階段。

execute階段:分裂的核心操作。如下圖所示:

具體過程如下:

1)、RegionServer更改ZK節點/region-in-transition中該Region的狀態為SPLITING;

2)、Master通過watch節點/region-in-transition檢測到Region狀態改變,並修改內存中Region的狀態,在Master頁面RIT模塊就可以看到Region執行split的狀態信息;

3)、在父存儲目錄下新建臨時文件夾.split保存split後的daughter region信息;

4)、關閉parent region:parent region關閉數據寫入並觸發flush操作,將寫入Region的數據全部持久化到磁碟。此後,短時間內客戶端落在父Region上的請求都會拋出異常NotServingRegionException;

5)、核心分裂步驟:在.split文件夾下新建兩個子文件夾,稱之為daughter A、daughter B,並在文件夾中生成reference文件,分別指向父Region中對應文件。這個步驟是所有操作步驟中最核心的一個環節;

6)、父Region分裂為兩個子Region後,將daughter A、daughter B拷貝到HBase根目錄下,形成兩個新的Region;

7)、parent region通知修改hbase.meta表後下線,不再提供服務。下線後parent region在meta表中的信息並不會馬上刪除,而是標註split列、offline列為true,並記錄兩個子Region;

8)、開啟daughter A、daughter B兩個子Region。通知修改hbase.meta表,正式對外提供服務。

rollback階段:如果execute階段出現異常,則執行rollback操作。為了實現回滾,整個分裂過程被分為很多子階段,回滾程序會根據當前進展到哪個子階段清理對應的垃圾數據。代碼中使用JournalEntryType來表徵各個子階段。

DRegion切分事務性保證

整個Region分裂是一個比較複雜的過程,涉及到父Region中HFile文件的切分、兩個子Region的生成、系統meta元數據的更改等很多子步驟,因此必須保證整個分裂過程的事務性,即要麼分裂完全成功,要麼分裂完全未開始,在任何情況下也不能出現分裂只完成一半的情況。

為了實現分裂的事務性,hbase設計了使用狀態機的方式保存分裂過程中的每個子步驟狀態,這樣一旦出現異常,系統可以根據當前所處的狀態決定是否回滾,以及如何回滾。遺憾的是,目前實現中這些中間狀態都只存儲在內存中,因此一旦在分裂過程中出現RegionServer宕機的情況,有可能會出現分裂處於中間狀態的情況,也就是RIT狀態。這種情況下需要使用hbck工具進行具體查看並分析解決方案。在2.0版本之後,HBase實現了新的分散式事務框架Procedure V2(HBASE-12439),新框架將會使用HLog存儲這種單機事務(DDL操作、Split操作、Move操作等)的中間狀態,因此可以保證即使在事務執行過程中參與者發生了宕機,依然可以使用HLog作為協調者對事務進行回滾操作或者重試提交,大大減少甚至杜絕RIT現象。

ERegion分裂對其他模塊的影響

通過Region分裂流程的了解,我們知道整個Region分裂過程並沒有涉及數據的移動,所以分裂本身的成本並不是很高,可以很快完成。分裂後子Region的文件實際沒有任何用戶數據,文件中存儲的僅是一些元數據信息,如分裂點rowkey等,那通過引用文件如何查找數據呢?子Region的數據實際在什麼時候完成真正遷移?數據遷移完成之後父Region什麼時候會被刪掉?

1)通過reference文件如何查找數據?

這裡就能看到reference文件名、文件內容的實際意義,整個操作流程如下所示:

i.根據reference文件名(Region名+真實文件名)定位到真實數據所在文件路徑;

ii.定位到真實數據文件就可以在整個文件中掃描待查KV了么?非也。因為reference文件通常都只引用了數據文件的一半數據,以分裂點為界,要麼上半部分文件數據,要麼下半部分數據。那到底是哪部分數據?分裂點又是哪個點?還記得上文提到的reference文件的文件內容吧,沒錯,就記錄在該文件中。

2)父Region的數據什麼時候會遷移到子Region目錄?

答案是子Region發生major_compaction時。我們知道compaction的執行實際上是將store中所有小文件一個KV一個KV從小到大讀出來之後再順序寫入一個大文件,完成之後再將小文件刪掉,因此compaction本身就需要讀取並寫入大量數據。子Region執行major_compaction後會將父目錄中屬於該子Region的所有數據讀出來並寫入子Region目錄數據文件中。可見將數據遷移放到compaction這個階段來做,是一件順其自然的事情。

3Region什麼時候會被刪除?

實際上HMaster會啟動一個線程定期遍歷檢查所有處於splitting狀態的父Region,以確定父Region是否可以被清理。檢測線程首先會在meta表中揪出所有split列為true的Region,並載入出其分裂後生成的兩個子Region(meta表中splitA列和splitB列),只需要檢查這兩個子Region是否還存在引用文件,如果都不存在引用文件就可以認為該父Region對應的文件可以被刪除。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序猿的修身養性 的精彩文章:

TAG:程序猿的修身養性 |