HFile(HBaseFile)是HBase使用的一種文件存儲格式的抽象,
創(chuàng)新互聯(lián)建站堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都做網(wǎng)站、成都網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的泊頭網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
目前存在兩種版本的HFile:HFileV1和HFileV2
HBase0.92之前的版本僅支持HFileV1,
HBase0.92/0.94同時支持HFileV1和HFileV2。
以下分別是HFileV1/V2的結(jié)構(gòu)圖:
HFileV1
HFileV2
圖中的數(shù)據(jù)塊(Datablock)正是實際存放應(yīng)用數(shù)據(jù)的地方,
每個數(shù)據(jù)塊又由一系列的KeyValue組成,并且這些KeyValue之間是按Key升序排列的,
本文將說明KeyValue到底是什么以及當KeyValue越來越多時出現(xiàn)大量類似的數(shù)據(jù)有哪些算法能減少重復?
首先來看一個例子:
假設(shè)需要將用戶的基本信息以及正在參與的開源項目的有關(guān)信息存入HBase:
用戶基本信息參與的開源項目
————————————————-
用戶Id職業(yè)性別tomcathbase
————————————————-
zhh3009碼農(nóng)男提patch打醬油提patch打醬油
用戶Id職業(yè)性別tomcatant
————————————————-
jdd1999碼神男創(chuàng)始人創(chuàng)始人
———————————————————
表1.1
用戶基本信息 參與的開源項目 --------------------- ---------------------------- 用戶Id 職業(yè) 性別 tomcat hbase --------------------- ---------------------------- zhh3009 碼農(nóng) 男 提patch打醬油 提patch打醬油 用戶Id 職業(yè) 性別 tomcat ant --------------------- ---------------------------- jdd1999 碼神 男 創(chuàng)始人 創(chuàng)始人 --------------------------------------------------------- 表1.1
從這個例子來看,用戶的基本信息比較好確定,但是參與的開源項目不確定且在開源項目中扮演的角色也不確定,
所以用關(guān)系數(shù)據(jù)庫不太好建表,因為不知道具體有多少列,也無法把相關(guān)的列歸成一個組。
HBase是一種基于列的數(shù)據(jù)庫,相關(guān)的列可以歸到一個列族(ColumnFamily),
每個列族中具體有哪些列不必事先知道,可以在需要的時候添加,比如在用戶基本信息中為zhh3009加入email這樣的列,
上例中”用戶基本信息”和”參與的開源項目”可以作為兩個列族,
不同的列族在HBase內(nèi)部通常對應(yīng)一個目錄,這樣不同的列值只會放到它所屬的列族目錄下。
我們希望通過查詢某個列就能把同一個列族或多個列族中的信息取出來,用戶Id就是這樣的列,
比如當我們要查詢zhh3009的郵箱和參與的開源項目時,根據(jù)用戶Id來查就不會查到j(luò)dd1999的信息,
在HBase中稱這樣的列為rowKey。
HBase是如何存放上例中的信息呢?
將用戶Id這一列抽出來作為rowKey,把上面的信息按如下格式扁平化:
列值> —————————————————– 碼農(nóng)> 男> 提patch打醬油> 提patch打醬油> 碼神> 男> 創(chuàng)始人> 創(chuàng)始人> —————————————————– 表1.2
<rowKey, 列族名稱, 列名 => 列值> ----------------------------------------------------- <zhh3009, 用戶基本信息, 職業(yè) => 碼農(nóng)> <zhh3009, 用戶基本信息, 性別 => 男> <zhh3009, 參與的開源項目, tomcat => 提patch打醬油> <zhh3009, 參與的開源項目, hbase => 提patch打醬油> <jdd1999, 用戶基本信息, 職業(yè) => 碼神> <jdd1999, 用戶基本信息, 性別 => 男> <jdd1999, 參與的開源項目, tomcat => 創(chuàng)始人> <jdd1999, 參與的開源項目, ant => 創(chuàng)始人> ----------------------------------------------------- 表1.2
表1.2中的每一行在HBase中對應(yīng)一個KeyValue,
“=>”左邊的是KeyValue中的”Key”,”=>”右邊對應(yīng)KeyValue中的”Value”。
當然這只是KeyValue的一個簡化格式,內(nèi)部格式并非那么簡單,我們接下來看看真實的KeyValue是怎樣的?
KeyValue內(nèi)部格式可以分成三部份:頭、Key、Value,如表2.1所示
名稱 字節(jié)數(shù)說明
——————————————————————–
keyLength 4表示Key所占的總字節(jié)數(shù)
valueLength4表示Value所占的總字節(jié)數(shù)
rowKeyLength2表示rowKey所占的字節(jié)數(shù)
rowKeyrowKeyLengthrowKey
columnFamilyLength1表示列族名稱所占的字節(jié)數(shù)
columnFamilycolumnFamilyLength列族名稱
columnNamecolumnNameLength列名
timestamp8時間戳
type1Key類型,比如是新增(Put),還是刪除(Delete)
valuevalueLength列值
——————————————————————–
表2.1
名稱 字節(jié)數(shù) 說明 -------------------------------------------------------------------- keyLength 4 表示Key所占的總字節(jié)數(shù) valueLength 4 表示Value所占的總字節(jié)數(shù) rowKeyLength 2 表示rowKey所占的字節(jié)數(shù) rowKey rowKeyLength rowKey columnFamilyLength 1 表示列族名稱所占的字節(jié)數(shù) columnFamily columnFamilyLength 列族名稱 columnName columnNameLength 列名 timestamp 8 時間戳 type 1 Key類型,比如是新增(Put),還是刪除(Delete) value valueLength 列值 -------------------------------------------------------------------- 表2.1
keyLength和valueLength組成頭部,
rowKeyLength到type這7項組成Key,最后一項value代表第三部份:Value,
上面有個地方值得注意,在columnFamily前面有columnFamilyLength,
但是在columnName之前并沒有columnNameLength這一項,為了節(jié)省空間,這不是必需的,
當在解析KeyValue時,通過keyLength-8(timestamp)-1(type)就可以確定columnName在此KeyValue中的結(jié)束位置。
把表1.2中的前兩行按表2.1中的格式生成兩個KeyValue:
KeyValueA代表:
KeyValueB代表: