Hbase的數據模型和讀寫原理:
HBase是一個開源可伸縮的分布式數據庫,他根據Google Bigtable數據模型構建在hadoop的hdfs存儲系統之上。
HBase是一個稀疏、多維度、排序的映射表。表的索引是行鍵、列族、列限定符和時間戳,一個列族中可以包含任意多個列,同一個列族里面數據存儲在一起。同一張表的每行數據的列的值都可以為空,所以說HBase是稀疏的。
數據模型
HBase是一個稀疏、多維度、排序的映射表,這張表的索引是行鍵、列族、列限定符和時間戳每個值是一個未經解釋的字符串。
表(Table):一個HBase表由行和列組成,列划分為若干個 列族。
行(Row):在表里面,每一行代表着一個數據對象,每一行都是以一個行鍵(Row Key)來進行唯一標識,行鍵可以是任意字符串,在HBase內部,行鍵保存為字符數組,數據存儲時,按照行鍵的字典序排列。
列族(Column Family):列族支持動態擴展,可以很輕松地添加一個列族或列,無需預先定義列的數量以及類型,所有列均以字符串形式存儲,用戶需要自行進行數據類型地轉換。一個HBase表被分組成為許多“列族”的集合,它是基本的訪問控制單元。
列標識(Column Qualifier):列族中的數據通過列標識符來進行定位,列標識也沒有特定的數據類型,以二進制字節來存儲。
單元格(Cell):每一個行鍵,列族和列標識符共同確定一個單元,存儲在單元里的數據稱為單元數據,單元和單元數據也沒有的挺的數據類型,以二進制字節來存儲。
時間戳(Timestap):默認每一個單元中的數據插入時都會用時間戳來進行版本標識。讀取單元數據時,如果時間戳沒有被指定,則默認返回最新你的數據,寫入新的單元格數據時,如果沒有設置時間戳,默認用當前時間,每一個列族的單元數據的版本數量都被HBase單獨維護默認情況下HBase保留3個版本數據。
邏輯模型
時候,你也可以把HBase看成一個多維度的Map模型去理解它的數據模型。正如下圖,一個行鍵映射一個列族數組,列族數組中的每個列族又映射一個列標識數組,列標識數組中的每一個列標識(Column Qualifier)又映射到一個時間戳數組,里面是不同時間戳映射下不同版本的值,但是默認取最近時間的值,所以可以看成是列標識(Column Qualifier)和它所對應的值的映射。用戶也可以通過HBase的API去同時獲取到多個版本的單元數據的值。Row Key在HBase中也就相當於關系型數據庫的主鍵,並且Row Key在創建表的時候就已經設置好,用戶無法指定某個列作為Row Key。
又有的時候,你也可以把HBase看成是一個類似Redis那樣的Key-Value數據庫。如下圖,當你要查詢某一行的所有數據時,Row Key就相當於Key,而Value就是單元中的數據(列族,列族里的列和列中時間戳所對應的不同版本的值);當深入到HBase底層的存儲機制時,用戶要查詢指定行里某一條單元數據時,HBase會去讀取一個數據塊,里面除了有要查詢的單元數據,可能同時也會獲取到其它單元數據,因為這個數據塊還包含着這個Row Key所對應的其它列族或其它的列信息,這些信息實際也代表着另一個單元數據,這也是HBase的API內部實際的工作原理。
物理模型
邏輯數據模型中空白cell在物理上是不存儲的,因此若一個請求為要獲取t8時間的contents:html,他的結果就是空。相似的,若請求為獲取t9時間的anchor:my.look.ca,結果也是空。但是,如果不指明時間,將會返回最新時間的行,每個最新的都會返回。
在一個HBase中,存儲了很多HBase表,當表中包含的行數量非常龐大,無法在一台機器上存儲時,需要分布存儲到多台機器上,需要根據行鍵的值對表中進行分區,每個行分區被稱為“Region”。
Master主服務器把不同的Region分配到不同的Region服務器上,同一個Region不會拆分到多個Region服務器上,每個Region服務器負責管理一個Region集合,通常每個Region服務器上會放置10~1000個Region。
復合鍵設計
Hbase由兩種基本的鍵結構:行鍵和列鍵,行鍵存儲本身的內容,行鍵存儲鍵的排序順序,列鍵包含了列族和特定的列限定符,磁盤上一個列族下的所有單元格的內容都存儲在文件中,不同同列族的單元格不會出現在同一個存儲文件中。不同列族的單元格不會出現在同一個存儲文件中。實際上,每個單元格在存儲時,同時保存了列鍵、行鍵和時間戳,羈絆存了在表中的位置信息。
在設計HBase表時,行鍵是最重要的,行鍵決定了訪問HBase表可以得到的性能,這個結論根植於兩個實時:region基於行鍵為一個區間的行提供忘,並負責區間的每一行;HFile在硬盤上存儲有序的行,當Region刷寫到內存里的行生成HFile。這些行已經排過序,也會有序地刷寫到硬盤上。
優秀地行鍵設計可以保證良好地HBase性能:
1.行鍵存儲在HBase中地每個單元格中,如果行鍵越長,用於存儲單元格地I/O開銷會越大。
2.對於組合行每個組件地排序順序取決於訪問模式。
主機名 事件類型 時間戳:適合訪問模式使用主機名和事件類型地查詢日志方式。
事件類型 時間戳 主機名:適合訪問模式用於時間類型和時間戳查詢日志地方式。
事件類型 反轉時間戳 主機名 :反轉時間戳的值是Long.MAX_VALUE減去時間戳;這樣可以確保最近發生的事件排在前面,適用於按照事件發生順序及逆行處理的場合。
倒敘時間戳作為鍵的一部分可以快速的找到數據庫中數據的最近版本。由於HBase的鍵是排序的,該鍵排在任何比它老的行鍵的前面,所以最近的版本必然是第一個。
注意: 行鍵不能發改變,唯一可以“改變”的方式是刪除然后再插入。這是一個網上常問的問題,所以需要開始就要讓行鍵正確。
數據結構
RowKey
與nosql數據庫們一樣,RowKey是用來檢索記錄的主鍵。訪問HBASE table中的行,只有三種方式:
1.通過單個RowKey訪問
2.通過RowKey的range(正則)
3.全表掃描
RowKey行鍵 (RowKey)可以是任意字符串(最大長度是64KB,實際應用中長度一般為 10-100bytes),在HBASE內部,RowKey保存為字節數組。存儲時,數據按照RowKey的字典序(byte order)排序存儲。設計RowKey時,要充分排序存儲這個特性,將經常一起讀取的行存儲放到一起。(位置相關性)
Column Family
列族:HBASE表中的每個列,都歸屬於某個列族。列族是表的schema的一部分(而列不是),必須在使用表之前定義。列名都以列族作為前綴。例如 courses:history,courses:math都屬於courses這個列族。
Cell
由{rowkey, column Family:columu, version} 唯一確定的單元。cell中的數據是沒有類型的,全部是字節碼形式存貯。
關鍵字:無類型、字節碼
Time Stamp
HBASE 中通過rowkey和columns確定的為一個存貯單元稱為cell。每個 cell都保存 着同一份數據的多個版本。版本通過時間戳來索引。時間戳的類型是 64位整型。時間戳可以由HBASE(在數據寫入時自動 )賦值,此時時間戳是精確到毫秒 的當前系統時間。時間戳也可以由客戶顯式賦值。如果應用程序要避免數據版 本沖突,就必須自己生成具有唯一性的時間戳。每個 cell中,不同版本的數據按照時間倒序排序,即最新的數據排在最前面。
為了避免數據存在過多版本造成的的管理 (包括存貯和索引)負擔,HBASE提供了兩種數據版本回收方式。一是保存數據的最后n個版本,二是保存最近一段時間內的版本(比如最近七天)。用戶可以針對每個列族進行設置。
命名空間
Table:表,所有的表都是命名空間的成員,即表必屬於某個命名空間,如果沒有指定,則在default默認的命名空間中。
RegionServer group:一個命名空間包含了默認的RegionServer Group。
Permission:權限,命名空間能夠讓我們來定義訪問控制列表ACL(Access Control List)。例如,創建表,讀取表,刪除,更新等等操作。
Quota:限額,可以強制一個命名空間可包含的region的數量。
Hbase原理
HBase讀流程
-
Client先訪問zookeeper,從meta表讀取region的位置,然后讀取meta表中的數據。meta中又存儲了用戶表的region信息;
-
根據namespace、表名和rowkey在meta表中找到對應的region信息;
- 找到這個region對應的regionserver;
- 查找對應的region;
- 先從MemStore找數據,如果沒有,再到BlockCache里面讀;
- BlockCache還沒有,再到StoreFile上讀(為了讀取的效率);
- 如果是從StoreFile里面讀取的數據,不是直接返回給客戶端,而是先寫入BlockCache,再返回給客戶端。
HBase寫流程
- Client向HregionServer發送寫請求;
- HregionServer將數據寫到HLog(write ahead log)。為了數據的持久化和恢復;
- HregionServer將數據寫到內存(MemStore);
- 反饋Client寫成功。
數據flush過程
- 當MemStore數據達到閾值(默認是128M,老版本是64M),將數據刷到硬盤,將內存中的數據刪除,同時刪除HLog中的歷史數據;
- 並將數據存儲到HDFS中;
數據合並過程
- 當數據塊達到4塊,Hmaster將數據塊加載到本地,進行合並;
- 當合並的數據超過256M,進行拆分,將拆分后的Region分配給不同的HregionServer管理;
- 當HregionServer宕機后,將HregionServer上的hlog拆分,然后分配給不同的HregionServer加載,修改.META.;
- 注意:HLog會同步到HDFS。