詳解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中的每一張表就是所謂的BigTable。BigTable會儲存一系列的行記錄,行記錄有三個基本型別的定義:
1.RowKey
是行在BigTable中的唯一標識。
2.TimeStamp:
是每一次資料操作對應關聯的時間戳,可以看作SVN的版本。
3.Column:
定義為<family>:<label>,通過這兩部分可以指定唯一的資料的儲存列,family的定義和修改需要對HBase進行類似於DB的DDL操作,
而label,不需要定義直接可以使用,這也為動態定製列提供了一種手段。family另一個作用體現在物理儲存優化讀寫操作上,同family
的資料物理上儲存的會比較接近,因此在業務設計的過程中可以利用這個特性。
1. 邏輯儲存模型
HBase以表的形式儲存資料,表由行和列組成。列劃分為若干個列簇,如下圖所示:
下面是對錶中元素的詳細解析:
RowKey
與NoSQL資料庫一樣,rowkey是用來檢索記錄的主鍵。訪問HBase Table中的行,只有三種方式:
1.通過單個rowkey訪問
2.通過rowkey的range
3.全表掃描
rowkey行鍵可以任意字串(最大長度64KB,實際應用中長度一般為10-100bytes),在HBase內部RowKey儲存為位元組陣列。
儲存時,資料按照RowKey的字典序(byte order)排序儲存,設計key時,要充分了解這個特性,將經常一起讀取的行存放在一起。
需要注意的是:行的一次讀寫是原子操作(不論一次讀寫多少列)
列簇
HBase表中的每個列,都歸屬於某個列簇,列簇是表的schema的一部分(而列不是),必須在使用表之前定義。列名都以列簇作為字首。例如:
courses:history, courses:math 都屬於 courses 這個列簇。
訪問控制,磁碟和記憶體的使用統計都是在列簇層面進行的。
實際應用中,列簇上的控制權限能幫助我們管理不同型別的應用:我們允許一些應用可以新增新的基本資料、
一些應用可以讀取基本資料並建立繼承的列簇、一些應用則只允許瀏覽資料(設定可能因為隱私的原因不能瀏覽所有資料)。
時間戳
HBase中通過row和columns確定的為一個儲存單元稱為cell。每個cell都儲存著同一份資料的多個版本。版本通過時間戳來索引。
時間戳的型別是64位整型。時間戳可以由HBase在寫入時自動賦值,此時時間戳是精確到毫秒的當前系統時間。時間戳也可以由客戶顯示賦值。
如果應用程式要避免資料版本衝突,就必須自己生成具有唯一性的時間戳。每個cell中在不同版本的資料按照時間倒序排序,即最新的資料排在最前面。
為了避免資料存在過多的版本造成的管理負擔,HBase提供了兩種資料版本回收方式。一是儲存資料的最後n個版本,二是儲存最近一段時間內的版本
(比如最近七天)。使用者可以針對每個列簇進行設定。
Cell
由{row key, column(=+), version} 唯一確定的單元。cell中的資料是沒有型別的,全部是位元組碼形式儲存。
2. 物理儲存模型
Table在行的方向上分割為多個HRegion,每個HRegion分散在不同的RegionServer中。
每個HRegion由多個Store構成,每個Store由一個MemStore和0或多個StoreFile組成,每個Store儲存一個Columns Family
StoreFile以HFile格式儲存在HDFS中。
三、HBase儲存架構
從HBase的架構圖上可以看出,HBase中的儲存包括HMaster、HRegionSever、HRegion、HLog、Store、MemStore、StoreFile、HFile等,以下是HBase儲存架構圖:
HBase中的每張表都通過鍵按照一定的範圍被分割成多個子表(HRegion),預設一個HRegion超過256M就要被分割成兩個,這個過程由HRegionServer管理,
而HRegion的分配由HMaster管理。
HMaster的作用:
1.為HRegionServer分配HRegion
2.負責HRegionServer的負載均衡
3.發現失效的HRegionServer並重新分配
4.HDFS上的垃圾檔案回收
5.處理Schema更新請求
HRegionServer的作用:
1.維護HMaster分配給它的HRegion,處理對這些HRegion的IO請求
2.負責切分正在執行過程中變得過大的HRegion
可以看到,Client訪問HBase上的資料並不需要HMaster參與,定址訪問ZooKeeper和HRegionServer,資料讀寫訪問HRegionServer,
HMaster僅僅維護Table和Region的元資料資訊,Table的元資料資訊儲存在ZooKeeper上,負載很低。HRegionServer存取一個子表時,
會建立一個HRegion物件,然後對錶的每個列簇建立一個Store物件,每個Store都會有一個MemStore和0或多個StoreFile與之對應,
每個StoreFile都會對應一個HFile,HFile就是實際的儲存檔案。因此,一個HRegion有多少列簇就有多少個Store。
一個HRegionServer會有多個HRegion和一個HLog。
HRegion
Table在行的方向上分割為多個HRegion,HRegion是HBase中分散式儲存和負載均衡的最小單元,即不同的HRegion可以分別在不同的HRegionServer上,
但同一個HRegion是不會拆分到多個HRegionServer上的。HRegion按大小分割,每個表一般只有一個HRegion,隨著資料不斷插入表,HRegion不斷增大,
當HRegion的某個列簇達到一個閥值(預設256M)時就會分成兩個新的HRegion。
1、<表名,StartRowKey, 建立時間>
2、由目錄表(-ROOT-和.META.)記錄該Region的EndRowKey
HRegion定位:HRegion被分配給哪個HRegionServer是完全動態的,所以需要機制來定位HRegion具體在哪個HRegionServer,HBase使用三層結構來定位HRegion:
1、通過zk裡的檔案/hbase/rs得到-ROOT-表的位置。-ROOT-表只有一個region。
2、通過-ROOT-表查詢.META.表的第一個表中相應的HRegion位置。其實-ROOT-表是.META.表的第一個region;
.META.表中的每一個Region在-ROOT-表中都是一行記錄。
3、通過.META.表找到所要的使用者表HRegion的位置。使用者表的每個HRegion在.META.表中都是一行記錄。
-ROOT-表永遠不會被分隔為多個HRegion,保證了最多需要三次跳轉,就能定位到任意的region。Client會將查詢的位置資訊儲存快取起來,快取不會主動失效,
因此如果Client上的快取全部失效,則需要進行6次網路來回,才能定位到正確的HRegion,其中三次用來發現快取失效,另外三次用來獲取位置資訊。
Store
每一個HRegion由一個或多個Store組成,至少是一個Store,HBase會把一起訪問的資料放在一個Store裡面,即為每個ColumnFamily建一個Store,
如果有幾個ColumnFamily,也就有幾個Store。一個Store由一個MemStore和0或者多個StoreFile組成。 HBase以Store的大小來判斷是否需要切分HRegion。
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進行壓縮和解壓縮。(備註: DataBlock Index的缺陷。 a) 佔用過多記憶體b) 啟動載入時間緩慢)
HLog
HLog(WAL log):WAL意為write ahead log,用來做災難恢復使用,HLog記錄資料的所有變更,一旦region server 宕機,就可以從log中進行恢復。
LogFlusher
定期的將快取中資訊寫入到日誌檔案中
LogRoller
對日誌檔案進行管理維護