深入HBase架構原理

一塵在心發表於2018-08-23

深入學習HBase架構原理

HBase定義

HBase 是一個高可靠、高效能、面向列、可伸縮的分散式儲存系統,利用Hbase技術可在廉價PC Server上搭建大規模結構化儲存叢集。

HBase 是Google Bigtable 的開源實現,與Google Bigtable 利用GFS作為其檔案儲存系統類似, HBase 利用Hadoop HDFS 作為其檔案儲存系統;Google 執行MapReduce 來處理Bigtable中的海量資料, HBase 同樣利用Hadoop MapReduce來處理HBase中的海量資料;Google Bigtable 利用Chubby作為協同服務, HBase 利用Zookeeper作為對應。

HBase 的特點

HBase 中的表一般有以下特點。

1) 大:一個表可以有上億行,上百萬列。

2) 面向列:面向列表(簇)的儲存和許可權控制,列(簇)獨立檢索。

3) 列式儲存,其資料在表中是按照某列儲存的,這樣在查詢只需要少數幾個欄位時,能大大減少讀取的資料量。

4) 稀疏:對於為空(NULL)的列,並不佔用儲存空間,因此,表可以設計的非常稀疏。

5) 無模式:每一行都有一個可以排序的主鍵和任意多的列,列可以根據需要動態增加,同一張表中不同的行可以有截然不同的列

6) 資料多版本:Hbase每一個列的儲存有多個Version。

7) 資料型別單一,Hbase中的資料都是字串,沒有型別。

8) 擴充套件性:底層依賴HDFS。

9) 高可靠性:WAL機制保證了資料寫入時不會因叢集異常而導致寫入資料丟失,Replication機制保證了在叢集出現嚴重的問題時,資料不會發生丟失或損壞。而且Hbase底層使用HDFS,HDFS本身也有備份。

10) 高效能:底層的LSM資料結構和Rowkey有序排列等架構上的獨特設計,使得Hbase具有非常高的寫入效能。region切分,主鍵索引和快取機制使得Hbase在海量資料下具備一定的隨機讀取效能,該效能真對Rowkey的查詢能到達到毫秒級別。

MapReduce on HBase

在HBase系統上執行批處理運算,最方便和實用的模型依然是MapReduce,如下圖:

HBase Table和Region的關係,比較類似HDFS File和Block的關係,HBase提供了配套的TableInputFormat和TableOutputFormat API,可以方便的將HBase Table作為Hadoop MapReduce的Source和Sink,對於MapReduce Job應用開發人員來說,基本不需要關注HBase系統自身的細節。

Table & Region

當Table隨著記錄數不斷增加而變大後,會逐漸分裂成多份splits,成為regions,一個region由[startkey,endkey)表示,不同region會被Master分配給相應的RegionServer進行管理。 

HBase中有兩張特殊的Table, -ROOT- 和 .META. 
- .META. :記錄了使用者表的Region資訊,.META.可以有多個region 

表包含所有的使用者空間region列表,以及Region Server的伺服器地址

- -ROOT-:記錄了.META.表的Region資訊,-ROOT-只有一個region 

表包含.META.表所在的region列表,該表只有一個Region;Zookeeper中記錄了-ROOT-表的location

- Zookeeper中記錄了-ROOT-表的location 
Client訪問使用者資料之前需要先訪問zookeeper,然後訪問-ROOT-表,接著訪問.META.表,最後才能找到使用者資料的位置去訪問,中間需要多次網路操作,不過client端會做cache快取。

HBase 訪問介面

HBase 支援很多種訪問,訪問HBase的常見介面如下。

1、Native Java API,最常規和高效的訪問方式,適合Hadoop MapReduce Job並行

批處理HBase表資料。

2、HBase Shell,HBase的命令列工具,最簡單的介面,適合HBase管理使用。

3、Thrift Gateway,利用Thrift序列化技術,支援C++,PHP,Python等多種語言,

適合其他異構系統線上訪問HBase表資料。

4、REST Gateway,支援REST 風格的Http API訪問HBase, 解除了語言限制。

5、Pig,可以使用Pig Latin流式程式語言來操作HBase中的資料,和Hive類似,本質最終也是編譯成MapReduce Job來處理HBase表資料,適合做資料統計。

6、Hive,當前Hive的Release版本尚沒有加入對HBase的支援,但在下一個版本Hive 0.7.0中將會支援HBase,可以使用類似SQL語言來訪問HBase。

HBase 儲存結構(系統結構)

HBase的架構圖上可以看出,HBase中的儲存包括Client、HMaster、HRegionServer、HRegion、Store、MemStore、StoreFile、HFile、HLog等,接下來紹他們的作用

HBase中的每張表都通過行鍵按照一定的範圍被分割成多個子表(HRegion),預設一個HRegion超過256M就要被分割成兩個,這個過程由HRegionServer管理,而HRegion的分配由HMaster管理。

Client

包含訪問HBase的介面,並維護cache來加快對HBase的訪問,比如region的位置資訊

Zookeeper

1. 存放整個 HBase叢集的後設資料以及叢集的狀態資訊。

2. 實現HMaster主從節點的failover。

3. 保證任何時候,叢集中只有一個master

4. 儲存所有Region的定址入口

5. 實時監控Region server的上線和下線資訊。並實時通知給master

6. 儲存HBase的schema和table後設資料

HMaster

1、為Region server分配region。

2、負責Region server的負載均衡。

3、發現失效的Region server並重新分配其上的region。

4、 HDFS上的垃圾檔案回收。

5、 處理schema更新請求,ü管理使用者對table的增刪改查操作

HRegionServer

1、維護master分配給他的region,處理對這些region的io請求。

2、負責切分正在執行過程中變的過大的region。

可以看到,client訪問hbase上的資料並不需要master參與(定址訪問zookeeper和 region server,資料讀寫訪問region server),master僅僅維護table和region的後設資料資訊(table的後設資料資訊儲存在zookeeper上),負載很低。 HRegionServer存取一個子表

時,會建立一個HRegion物件,然後對錶的每個列族建立一個Store例項,每個Store都會有一個MemStore和0個或多個StoreFile與之對應,每個StoreFile都會對應一個HFile,

HFile就是實際的儲存檔案。因此,一個HRegion有多少個列族就有多少個Store。一個

HRegionServer會有多個HRegion和一個HLog。

HRegion

table在行的方向上分隔為多個Region。Region是HBase中分散式儲存和負載均衡的最小單元,即不同的region可以分別在不同的Region Server上,但同一個Region是不會拆分

到多個server上。

Region按大小分隔,每個表一般是隻有一個region。隨著資料不斷插入表,region不斷增大,當region的某個列族達到一個閾值(預設256M)時就會分成兩個新的region。

每個region由以下資訊標識:

1、< 表名,startRowkey,建立時間>

2、由目錄表(-ROOT-和.META.)記錄該region的endRowkey

HRegion定位:Region被分配給哪個Region Server是完全動態的,所以需要機制來定位Region具體在哪個region server。

HBase使用三層結構來定位region:

 

1、通過zk裡的檔案/hbase/rs得到-ROOT-表的位置。-ROOT-表只有一個region。

2、通過-ROOT-表查詢.META.表的第一個表中相應的region的位置。其實-ROOT-表是.META.表的第一個region;.META.表中的每一個region在-ROOT-表中都是一行記錄。

3、通過.META.表找到所要的使用者表region的位置。使用者表中的每個region在.META.表中都是一行記錄。

-ROOT-表永遠不會被分隔為多個region,保證了最多需要三次跳轉,就能定位到任意的region。client會將查詢的位置資訊儲存快取起來,快取不會主動失效,因此如果client上的快取全部失效,則需要進行6次網路來回,才能定位到正確的region,其中三次用來發現快取失效,另外三次用來獲取位置資訊。

Store每一個region由一個或多個store組成,至少是一個store,hbase會把一起訪問的資料

放在一個store裡面,即為每個ColumnFamily建一個store,如果有幾個ColumnFamily,也就有幾個Store。一個Store由一個memStore和0或者多個StoreFile組成。 HBase以store的大小來判斷是否需要切分region。

MemStore

memStore 是放在記憶體裡的。儲存修改的資料即keyValues。當memStore的大小達到

一個閥值(預設64MB)時,memStore會被flush到檔案,即生成一個快照。目前hbase 會

有一個執行緒來負責memStore的flush操作。 StoreFile

memStore記憶體中的資料寫到檔案後就是StoreFile,StoreFile底層是以HFile的格式儲存。

HFile

HBase中KeyValue資料的儲存格式,是hadoop的二進位制格式檔案。首先HFile檔案是不定長的,長度固定的只有其中的兩塊:Trailer和FileInfo。Trailer中有指標指向其他資料塊

的起始點,FileInfo記錄了檔案的一些meta資訊。 Data Block是hbase io的基本單元,為了提高效率,HRegionServer中有基於LRU的block cache機制。每個Data塊的大小可以在創

建一個Table的時候通過引數指定(預設塊大小64KB),大號的Block有利於順序Scan,小號的Block利於隨機查詢。每個Data塊除了開頭的Magic以外就是一個個KeyValue對拼接而成,Magic內容就是一些隨機數字,目的是防止資料損壞,結構如下。

 

HFile結構圖如下:

Data Block段用來儲存表中的資料,這部分可以被壓縮。 Meta Block段(可選的)用來儲存使用者自定義的kv段,可以被壓縮。 FileInfo段用來儲存HFile的元資訊,不能被壓縮,使用者也可以在這一部分新增自己的元資訊。 Data Block Index段(可選的)用來儲存Meta Blcok的索引。 Trailer這一段是定長的。儲存了每一段的偏移量,讀取一個HFile時,會首先

讀取Trailer,Trailer儲存了每個段的起始位置(段的Magic Number用來做安全check),然

後,DataBlock Index會被讀取到記憶體中,這樣,當檢索某個key時,不需要掃描整個HFile,而只需從記憶體中找到key所在的block,通過一次磁碟io將整個 block讀取到記憶體中,

再找到需要的key。DataBlock Index採用LRU機制淘汰。 HFile的Data Block,Meta Block

通常採用壓縮方式儲存,壓縮之後可以大大減少網路IO和磁碟IO,隨之而來的開銷當然是需要花費cpu進行壓縮和解壓縮。目標HFile的壓縮支援兩種方式:gzip、lzo。

 

另外,針對目前針對現有HFile的兩個主要缺陷:

a) 佔用過多記憶體

b) 啟動載入時間緩慢

基於此缺陷,提出了HFile Version2設計。 HLog

其實HLog檔案就是一個普通的Hadoop Sequence File, Sequence File的value是key

時HLogKey物件,其中記錄了寫入資料的歸屬資訊,除了table和region名字外,還同時包

括sequence number和timestamp,timestamp是寫入時間,sequence number的起始值為0,或者是最近一次存入檔案系統中的sequence number。 Sequence File的value是HBase的KeyValue物件,即對應HFile中的KeyValue。

HLog(WAL log):WAL意為write ahead log,用來做災難恢復使用,HLog記錄資料的所有變更,一旦region server 當機,就可以從log中進行恢復。

LogFlusher

前面提到,資料以KeyValue形式到達HRegionServer,將寫入WAL之後,寫入一個

SequenceFile。看過去沒問題,但是因為資料流在寫入檔案系統時,經常會快取以提高效能。這樣,有些本以為在日誌檔案中的資料實際在記憶體中。這裡,我們提供了一個

LogFlusher的類。它呼叫HLog.optionalSync(),後者根據 hbase.regionserver.optionallogflushinterval (預設是10秒),定期呼叫Hlog.sync()。另外,HLog.doWrite()也會根據 hbase.regionserver.flushlogentries (預設100秒)定期呼叫Hlog.sync()。Sync() 本身呼叫HLog.Writer.sync(),它由SequenceFileLogWriter實現。 LogRoller

Log的大小通過$HBASE_HOME/conf/hbase-site.xml 的

hbase.regionserver.logroll.period 限制,預設是一個小時。所以每60分鐘,會開啟一個新的log檔案。久而久之,會有一大堆的檔案需要維護。首先,LogRoller呼叫

HLog.rollWriter(),定時滾動日誌,之後,利用HLog.cleanOldLogs()可以清除舊的日誌。

它首先取得儲存檔案中的最大的sequence number,之後檢查是否存在一個log所有的條目

的“sequence number”均低於這個值,如果存在,將刪除這個log。每個region server維

護一個HLog,而不是每一個region一個,這樣不同region(來自不同的table)的日誌會混在一起,這樣做的目的是不斷追加單個檔案相對於同時寫多個檔案而言,可以減少磁碟定址次數,因此可以提高table的寫效能。帶來麻煩的時,如果一個region server下線,為了恢復其上的region,需要將region server上的log進行拆分,然後分發到其他region server上進

行恢復。

HBase與Zookeeper的關係 

 

 1. HBase依賴Zookeeper

       首先HMaster和RegionServer都需要和Zookeeper互動,因為RegionServer上線了還需要互動,之後Zookeeper知道了告訴HMaster,而下線或斷開了Zookeeper知道了也告訴HMaster;同時HMaster還管理RegionServer,HMaster還會在HDFS上寫Region資料。

       2. 預設情況下,HBase依賴、管理Zookeeper例項,比如,啟動或者停止Zookeeper;

       3. HMaster與HRegionServer啟動時會向Zookeeper註冊;

       4. Zookeeper的引入使得HMaster不再是單點故障。

HBase 設計

HBase 中的每一張表就是所謂的 BigTable。BigTable 會儲存一系列的行記錄,行記錄

有三個基本型別的定義:Row Key、Time Stamp、Column。

1、Row Key 是行在 BigTable 中的唯一標識。

2、Time Stamp 是每次資料操作對應關聯的時間戳,可以看做 SVN 的版本。

3、Column 定義為< family>:< label>,通過這兩部分可以指定唯一的資料的儲存列,family 的定義和修改需要對 HBase 進行類似於 DB 的 DDL 操作,而 label ,不需要定義直接可以使用,這也為動態定製列提供了一種手段。family 另一個作用體現在物理儲存優化讀寫操作上,同 family 的資料物理上儲存的會比較臨近,因此在業務設計的過程中可以利用這個特性。

HBase邏輯模型

HBase 以表的形式儲存資料。表由行和列組成。列劃分為若干個列族(row family),如下圖所示。

HBase邏輯資料模型圖

 

1、 Row Key

與 NoSQL 資料庫一樣,Row Key 是用來檢索記錄的主鍵。訪問 HBase table 中的行,只有三種方式:

1)通過單個 Row Key 訪問。

2)通過 Row Key 的 range 全表掃描。

3)Row Key 可以使任意字串(最大長度是64KB,實際應用中長度一般為 10 ~

100bytes),在HBase 內部,Row Key 儲存為位元組陣列。

在儲存時,資料按照 Row Key 的字典序(byte order)排序儲存。設計 Key 時,要充分排序儲存這個特性,將經常一起讀取的行儲存到一起(位置相關性)。

注意字典序對 int 排序的結果是 1,10,100,11,12,13,14,15,16,17,18,19,20,21,..., 9,91,92,93,94,95,96,97,98,99。要儲存整形的自然序,Row Key 必須用 0 進行左填充。

行的一次讀寫是原子操作(不論一次讀寫多少列)。這個設計決策能夠使使用者很容易理解程式在對同一個行進行併發更新操作時的行為。

2、列族

HBase 表中的每個列都歸屬於某個列族。列族是表的 Schema 的一部分(而列不是),必須在使用表之前定義。列名都以列族作為字首,例如 courses:history、

courses:math 都屬於 courses 這個列族。

訪問控制、磁碟和記憶體的使用統計都是在列族層面進行的。在實際應用中,列族上的控制許可權能幫助我們管理不同型別的應用,例如,允許一些應用可以新增新的基本資料、一些應用可以讀取基本資料並建立繼承的列族、一些應用則只允許瀏覽資料(甚至可能因為隱私的原因不能瀏覽所有資料)。

3、時間戳

HBase 中通過 Row 和 Columns 確定的一個儲存單元稱為 Cell。每個 Cell 都儲存著同

一份資料的多個版本。版本通過時間戳來索引,時間戳的型別是 64 位整型。時間戳可以由HBase(在資料寫入時自動)賦值,此時時間戳是精確到毫秒的當前系統時間。時間戳也可以由客戶顯示賦值。如果應用程式要避免資料版本衝突,就必須自己生成具有唯一性的時間戳。每個 Cell 中,不同版本的資料按照時間倒序排序,即最新的資料排在最前面。

為了避免資料存在過多版本造成的管理(包括儲存和索引)負擔,HBase 提供了兩種資料版本回收方式。一是儲存資料的最後 n 個版本,二是儲存最近一段時間內的版本(比如最近七天)。使用者可以針對每個列族進行設定。

4、 Cell

Cell 是由 {row key,column(=< family> + < label>),version} 唯一確定的單元。

Cell 中的資料是沒有型別的,全部是位元組碼形式儲存。

HBase物理儲存

Table 在行的方向上分割為多個HRegion,每個HRegion分散在不同的RegionServer中。

每個HRegion由多個Store構成,每個Store由一個memStore和0或多個StoreFile組成,每個Store儲存一個Columns Family

HRegion與Store關係圖

StoreFile以HFile格式儲存在HDFS中。

小小總結

1、有關Hbase表的特點

 A、大:一個表可以有上億行,上百萬列

 B、面向列:面向列表(簇)的儲存和許可權控制,列(簇)獨立檢索

 C、稀疏:對於為空(NULL)的列,並不佔用儲存空間,因此,表可以設計的非常稀疏

2、有關HMaster的作用

 A、為Region server分配region

 B、負責Region server的負載均衡

 C、發現失效的Region server並重新分配其上的region

 D、HDFS上的垃圾檔案回收

3、HBase定位region

 A、通過zk裡的檔案/hbase/rs得到-ROOT-表的位置。-ROOT-表只有一個region

 B、通過-ROOT-表查詢.META.表的第一個表中相應的region的位置。其實-ROOT-表是.META.表的第一個region;.META.表中的每一個region在-ROOT-表中都是一行記錄

 C、通過.META.表找到所要的使用者表region的位置。使用者表中的每個region在.META.表中都是一行記錄

相關文章