您好,登錄后才能下訂單哦!
HFile(HBaseFile)是HBase使用的一種文件存儲格式的抽象,
目前存在兩種版本的HFile:HFileV1和HFileV2
HBase0.92之前的版本僅支持HFileV1,
HBase0.92/0.94同時支持HFileV1和HFileV2。
以下分別是HFileV1/V2的結構圖:
HFileV1
HFileV2
圖中的數據塊(Datablock)正是實際存放應用數據的地方,
每個數據塊又由一系列的KeyValue組成,并且這些KeyValue之間是按Key升序排列的,
本文將說明KeyValue到底是什么以及當KeyValue越來越多時出現大量類似的數據有哪些算法能減少重復?
首先來看一個例子:
假設需要將用戶的基本信息以及正在參與的開源項目的有關信息存入HBase:
用戶基本信息參與的開源項目
————————————————-
用戶Id職業性別tomcathbase
————————————————-
zhh3009碼農男提patch打醬油提patch打醬油
用戶Id職業性別tomcatant
————————————————-
jdd1999碼神男創始人創始人
———————————————————
表1.1
用戶基本信息 參與的開源項目 --------------------- ---------------------------- 用戶Id 職業 性別 tomcat hbase --------------------- ---------------------------- zhh3009 碼農 男 提patch打醬油 提patch打醬油 用戶Id 職業 性別 tomcat ant --------------------- ---------------------------- jdd1999 碼神 男 創始人 創始人 --------------------------------------------------------- 表1.1
從這個例子來看,用戶的基本信息比較好確定,但是參與的開源項目不確定且在開源項目中扮演的角色也不確定,
所以用關系數據庫不太好建表,因為不知道具體有多少列,也無法把相關的列歸成一個組。
HBase是一種基于列的數據庫,相關的列可以歸到一個列族(ColumnFamily),
每個列族中具體有哪些列不必事先知道,可以在需要的時候添加,比如在用戶基本信息中為zhh3009加入email這樣的列,
上例中”用戶基本信息”和”參與的開源項目”可以作為兩個列族,
不同的列族在HBase內部通常對應一個目錄,這樣不同的列值只會放到它所屬的列族目錄下。
我們希望通過查詢某個列就能把同一個列族或多個列族中的信息取出來,用戶Id就是這樣的列,
比如當我們要查詢zhh3009的郵箱和參與的開源項目時,根據用戶Id來查就不會查到jdd1999的信息,
在HBase中稱這樣的列為rowKey。
HBase是如何存放上例中的信息呢?
將用戶Id這一列抽出來作為rowKey,把上面的信息按如下格式扁平化:
<rowKey, 列族名稱, 列名 => 列值> —————————————————– <zhh3009, 用戶基本信息, 職業 => 碼農> <zhh3009, 用戶基本信息, 性別 => 男> <zhh3009, 參與的開源項目, tomcat => 提patch打醬油> <zhh3009, 參與的開源項目, hbase => 提patch打醬油> <jdd1999, 用戶基本信息, 職業 => 碼神> <jdd1999, 用戶基本信息, 性別 => 男> <jdd1999, 參與的開源項目, tomcat => 創始人> <jdd1999, 參與的開源項目, ant => 創始人> —————————————————– 表1.2
<rowKey, 列族名稱, 列名 => 列值> ----------------------------------------------------- <zhh3009, 用戶基本信息, 職業 => 碼農> <zhh3009, 用戶基本信息, 性別 => 男> <zhh3009, 參與的開源項目, tomcat => 提patch打醬油> <zhh3009, 參與的開源項目, hbase => 提patch打醬油> <jdd1999, 用戶基本信息, 職業 => 碼神> <jdd1999, 用戶基本信息, 性別 => 男> <jdd1999, 參與的開源項目, tomcat => 創始人> <jdd1999, 參與的開源項目, ant => 創始人> ----------------------------------------------------- 表1.2
表1.2中的每一行在HBase中對應一個KeyValue,
“=>”左邊的是KeyValue中的”Key”,”=>”右邊對應KeyValue中的”Value”。
當然這只是KeyValue的一個簡化格式,內部格式并非那么簡單,我們接下來看看真實的KeyValue是怎樣的?
KeyValue內部格式可以分成三部份:頭、Key、Value,如表2.1所示
名稱 字節數說明
——————————————————————–
keyLength 4表示Key所占的總字節數
valueLength4表示Value所占的總字節數
rowKeyLength2表示rowKey所占的字節數
rowKeyrowKeyLengthrowKey
columnFamilyLength1表示列族名稱所占的字節數
columnFamilycolumnFamilyLength列族名稱
columnNamecolumnNameLength列名
timestamp8時間戳
type1Key類型,比如是新增(Put),還是刪除(Delete)
valuevalueLength列值
——————————————————————–
表2.1
名稱 字節數 說明 -------------------------------------------------------------------- keyLength 4 表示Key所占的總字節數 valueLength 4 表示Value所占的總字節數 rowKeyLength 2 表示rowKey所占的字節數 rowKey rowKeyLength rowKey columnFamilyLength 1 表示列族名稱所占的字節數 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這一項,為了節省空間,這不是必需的,
當在解析KeyValue時,通過keyLength-8(timestamp)-1(type)就可以確定columnName在此KeyValue中的結束位置。
把表1.2中的前兩行按表2.1中的格式生成兩個KeyValue:
KeyValueA代表:<zhh3009,用戶基本信息,職業=>碼農>
KeyValueB代表:<zhh3009,用戶基本信息,性別=>男>
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。