HBase——HFile存儲(chǔ)結(jié)構(gòu)解析

前言

HFile是HBase存儲(chǔ)數(shù)據(jù)的文件組織形式妻献,參考BigTable的SSTable和Hadoop的TFile實(shí)現(xiàn)捺僻。從HBase開始到現(xiàn)在,HFile經(jīng)歷了三個(gè)版本嫌术,其中V2在0.92引入烫扼,V3在0.98引入曙求。HFileV1版本的在實(shí)際使用過程中發(fā)現(xiàn)它占用內(nèi)存多,HFile V2版本針對(duì)此進(jìn)行了優(yōu)化材蛛,HFile V3版本基本和V2版本相同圆到,只是在cell層面添加了Tag數(shù)組的支持。鑒于此卑吭,本文主要針對(duì)V2版本進(jìn)行分析芽淡,對(duì)V1和V3版本感興趣的同學(xué)可以參考其他信息。

一豆赏、HFile V1

  • Data Block:保存表中的數(shù)據(jù)挣菲,這部分可以被壓縮

  • Meta Block:(可選)保存用戶自定義的kv對(duì),可以被壓縮掷邦。

  • File Info:Hfile的meta元信息白胀,不被壓縮,定長抚岗。

  • Data Block Index:Data Block的索引或杠。每個(gè)Data塊的起始點(diǎn)。

  • Meta Block Index:(可選的)Meta Block的索引宣蔚,Meta塊的起始點(diǎn)向抢。

  • Trailer: 定長认境。保存了每一段的偏移量,讀取一個(gè)HFile時(shí)挟鸠,會(huì)首先讀取Trailer叉信,Trailer有指針指向其他數(shù)據(jù)塊的起始點(diǎn),保存了每個(gè)段的起始位置(段的Magic Number用來做安全check)艘希,然后硼身,DataBlock Index會(huì)被讀取到內(nèi)存中,這樣覆享,當(dāng)檢索某個(gè)key時(shí)佳遂,不需要掃描整個(gè)HFile,而只需從內(nèi)存中找到key所在的block淹真,通過一次磁盤io將整個(gè)block讀取到內(nèi)存中讶迁,再找到需要的key连茧。DataBlock Index采用LRU機(jī)制淘汰核蘸。

HFile的Data Block,Meta Block通常采用壓縮方式存儲(chǔ)啸驯。Data Block是HBase I/O的基本單元客扎,為了提高效率,HRegionServer中有基于LRU的Block Cache機(jī)制罚斗。每個(gè)Data塊的大小可以在創(chuàng)建一個(gè)Table的時(shí)候通過參數(shù)指定徙鱼,大號(hào)的Block有利于順序Scan,小號(hào)Block利于隨機(jī)查詢针姿。每個(gè)Data塊除了開頭的Magic以外就是一個(gè)個(gè)KeyValue對(duì)拼接而成, Magic內(nèi)容就是一些隨機(jī)數(shù)字袱吆,目的是防止數(shù)據(jù)損壞。

注意距淫,block是hfile的最小壓縮和編碼數(shù)據(jù)塊绞绒,默認(rèn)128KB

第一版的block index是非常簡單的,注意只有兩個(gè)block index榕暇,一個(gè)是data block index蓬衡,一個(gè)是meta block index,block index包括了以下幾點(diǎn):

    1. offset
    1. Uncompressed size
    1. Key (a serialized byte array written using Bytes.writeByteArray)
    • 3.1 Key length as a variable-length integer (VInt)
    • 3.2 Key bytes

block index的數(shù)量會(huì)存放在trailer彤枢,這樣才能讀取到block index數(shù)據(jù)狰晚。

這個(gè)版本的block index有1個(gè)缺點(diǎn)

    1. 無法知道block壓縮后的數(shù)據(jù)大小,這在之后的解壓過程是必要的

所以在版本2缴啡,解決了這個(gè)問題壁晒,在block index中增加了實(shí)際存儲(chǔ)block大小的數(shù)據(jù)。

二业栅、HFile V2

在接口層面做了兼容秒咐,在讀hfile的時(shí)候换棚,支持v1和v2,在寫hfile的時(shí)候反镇,只會(huì)寫v2版本的hfile固蚤。

hfile升級(jí)的原因:

    1. v1 的設(shè)計(jì)導(dǎo)致了region server啟動(dòng)時(shí)間很長,需要加載很大的數(shù)據(jù)量歹茶,比如大量的bloom filter夕玩,大量的block index

為了解決這個(gè)問題,v2使得hfile增加了新特性惊豺,把bloom filter和block index打散燎孟,寫到多個(gè)block中去,這樣就減少了hfile 寫入時(shí)候的內(nèi)存offset尸昧。并且這些打散的block index會(huì)有預(yù)定的長度揩页。

另一方面,v2還用到了 load-on-open 這個(gè)概念烹俗,意思是說爆侣,在打開hfile的時(shí)候,加載那些必要的信息幢妄,包括trailer兔仰,trailer里記錄了hfile的必要信息。而其他數(shù)據(jù)就可以再用到的時(shí)候蕉鸳,通過trailer再解析出來乎赴。

2.1 HFile邏輯結(jié)構(gòu)

HFile V2的邏輯結(jié)構(gòu)如下圖所示:


文件主要分為四個(gè)部分:Scanned block section,Non-scanned block section潮尝,Opening-time data section和Trailer榕吼。

Scanned block section:顧名思義,表示順序掃描HFile時(shí)所有的數(shù)據(jù)塊將會(huì)被讀取勉失,包括Leaf Index Block和Bloom Block羹蚣。

Non-scanned block section:表示在HFile順序掃描的時(shí)候數(shù)據(jù)不會(huì)被讀取,主要包括Meta Block和Intermediate Level Data Index Blocks兩部分戴质。

Load-on-open-section:這部分?jǐn)?shù)據(jù)在HBase的region server啟動(dòng)時(shí)度宦,需要加載到內(nèi)存中。包括FileInfo告匠、Bloom filter block戈抄、data block index和meta block index。

Trailer:這部分主要記錄了HFile的基本信息后专、各個(gè)部分的偏移值和尋址信息划鸽。

2.2 HFile物理結(jié)構(gòu)

如上圖所示, HFile會(huì)被切分為多個(gè)大小相等的block塊,每個(gè)block的大小可以在創(chuàng)建表列簇的時(shí)候通過參數(shù)blocksize => ‘65535’進(jìn)行指定裸诽,默認(rèn)為64k嫂用,大號(hào)的Block有利于順序Scan,小號(hào)Block利于隨機(jī)查詢丈冬,因而需要權(quán)衡嘱函。而且所有block塊都擁有相同的數(shù)據(jù)結(jié)構(gòu),如圖左側(cè)所示埂蕊,HBase將block塊抽象為一個(gè)統(tǒng)一的HFileBlock往弓。HFileBlock支持兩種類型,一種類型不支持checksum蓄氧,一種不支持函似。為方便講解,下圖選用不支持checksum的HFileBlock內(nèi)部結(jié)構(gòu):


上圖所示HFileBlock主要包括兩部分:BlockHeader和BlockData喉童。其中BlockHeader主要存儲(chǔ)block元數(shù)據(jù)撇寞,BlockData用來存儲(chǔ)具體數(shù)據(jù)。block元數(shù)據(jù)中最核心的字段是BlockType字段堂氯,用來標(biāo)示該block塊的類型蔑担,HBase中定義了8種BlockType,每種BlockType對(duì)應(yīng)的block都存儲(chǔ)不同的數(shù)據(jù)內(nèi)容祖灰,有的存儲(chǔ)用戶數(shù)據(jù)钟沛,有的存儲(chǔ)索引數(shù)據(jù)畔规,有的存儲(chǔ)meta元數(shù)據(jù)局扶。對(duì)于任意一種類型的HFileBlock,都擁有相同結(jié)構(gòu)的BlockHeader叁扫,但是BlockData結(jié)構(gòu)卻不相同三妈。下面通過一張表簡單羅列最核心的幾種BlockType,下文會(huì)詳細(xì)針對(duì)每種BlockType進(jìn)行詳細(xì)的講解:

2.3 HFile中Block塊解析

上文從HFile的層面將文件切分成了多種類型的block莫绣,接下來針對(duì)幾種重要block進(jìn)行詳細(xì)的介紹畴蒲,因?yàn)槠脑颍饕嚓P(guān)的block不會(huì)在本文進(jìn)行介紹对室,接下來會(huì)寫一篇單獨(dú)的文章對(duì)其進(jìn)行分析和講解模燥。首先會(huì)介紹記錄HFile基本信息的TrailerBlock,再介紹用戶數(shù)據(jù)的實(shí)際存儲(chǔ)塊DataBlock掩宜,最后簡單介紹布隆過濾器相關(guān)的block蔫骂。

2.4 Trailer Block

主要記錄了HFile的基本信息、各個(gè)部分的偏移值和尋址信息牺汤,下圖為Trailer內(nèi)存和磁盤中的數(shù)據(jù)結(jié)構(gòu)辽旋,其中只顯示了部分核心字段:


HFile在讀取的時(shí)候首先會(huì)解析Trailer Block并加載到內(nèi)存,然后再進(jìn)一步加載LoadOnOpen區(qū)的數(shù)據(jù),具體步驟如下:

    1. 首先加載version版本信息补胚,HBase中version包含majorVersion和minorVersion兩部分码耐,前者決定了HFile的主版本: V1、V2 還是V3溶其;后者在主版本確定的基礎(chǔ)上決定是否支持一些微小修正骚腥,比如是否支持checksum等。不同的版本決定了使用不同的Reader對(duì)象對(duì)HFile進(jìn)行讀取解析
    1. 根據(jù)Version信息獲取trailer的長度(不同version的trailer長度不同)瓶逃,再根據(jù)trailer長度加載整個(gè)HFileTrailer Block
    1. 最后加載load-on-open部分到內(nèi)存中桦沉,起始偏移地址是trailer中的LoadOnOpenDataOffset字段,load-on-open部分的結(jié)束偏移量為HFile長度減去Trailer長度金闽,load-on-open部分主要包括索引樹的根節(jié)點(diǎn)以及FileInfo兩個(gè)重要模塊纯露,F(xiàn)ileInfo是固定長度的塊,它紀(jì)錄了文件的一些Meta信息代芜,例如:AVG_KEY_LEN, AVG_VALUE_LEN, LAST_KEY, COMPARATOR, MAX_SEQ_ID_KEY等埠褪;

2.5 Data Block

DataBlock是HBase中數(shù)據(jù)存儲(chǔ)的最小單元。DataBlock中主要存儲(chǔ)用戶的KeyValue數(shù)據(jù)(KeyValue后面一般會(huì)跟一個(gè)timestamp挤庇,圖中未標(biāo)出)钞速,而KeyValue結(jié)構(gòu)是HBase存儲(chǔ)的核心,每個(gè)數(shù)據(jù)都是以KeyValue結(jié)構(gòu)在HBase中進(jìn)行存儲(chǔ)嫡秕。KeyValue結(jié)構(gòu)在內(nèi)存和磁盤中可以表示為:


每個(gè)KeyValue都由4個(gè)部分構(gòu)成渴语,分別為key length,value length昆咽,key和value驾凶。其中key value和value length是兩個(gè)固定長度的數(shù)值,而key是一個(gè)復(fù)雜的結(jié)構(gòu)掷酗,首先是rowkey的長度调违,接著是rowkey,然后是ColumnFamily的長度泻轰,再是ColumnFamily技肩,之后是ColumnQualifier,最后是時(shí)間戳和KeyType(keytype有四種類型浮声,分別是Put虚婿、Delete、 DeleteColumn和DeleteFamily)泳挥,value就沒有那么復(fù)雜然痊,就是一串純粹的二進(jìn)制數(shù)據(jù)。

2.6 BloomFilter Meta Block & Bloom Block

BloomFilter對(duì)于HBase的隨機(jī)讀性能至關(guān)重要羡洁,對(duì)于get操作以及部分scan操作可以剔除掉不會(huì)用到的HFile文件玷过,減少實(shí)際IO次數(shù),提高隨機(jī)讀性能。在此簡單地介紹一下Bloom Filter的工作原理辛蚊,Bloom Filter使用位數(shù)組來實(shí)現(xiàn)過濾粤蝎,初始狀態(tài)下位數(shù)組每一位都為0,如下圖所示:


假如此時(shí)有一個(gè)集合S = {x1, x2, … xn}袋马,Bloom Filter使用k個(gè)獨(dú)立的hash函數(shù)初澎,分別將集合中的每一個(gè)元素映射到{1,…,m}的范圍。對(duì)于任何一個(gè)元素虑凛,被映射到的數(shù)字作為對(duì)應(yīng)的位數(shù)組的索引碑宴,該位會(huì)被置為1。比如元素x1被hash函數(shù)映射到數(shù)字8桑谍,那么位數(shù)組的第8位就會(huì)被置為1延柠。下圖中集合S只有兩個(gè)元素x和y,分別被3個(gè)hash函數(shù)進(jìn)行映射锣披,映射到的位置分別為(0贞间,3,6)和(4雹仿,7增热,10),對(duì)應(yīng)的位會(huì)被置為1:


現(xiàn)在假如要判斷另一個(gè)元素是否是在此集合中胧辽,只需要被這3個(gè)hash函數(shù)進(jìn)行映射峻仇,查看對(duì)應(yīng)的位置是否有0存在,如果有的話邑商,表示此元素肯定不存在于這個(gè)集合摄咆,否則有可能存在。下圖所示就表示z肯定不在集合{x奠骄,y}中:


HBase中每個(gè)HFile都有對(duì)應(yīng)的位數(shù)組豆同,KeyValue在寫入HFile時(shí)會(huì)先經(jīng)過幾個(gè)hash函數(shù)的映射,映射后將對(duì)應(yīng)的數(shù)組位改為1含鳞,get請(qǐng)求進(jìn)來之后再進(jìn)行hash映射,如果在對(duì)應(yīng)數(shù)組位上存在0芹务,說明該get請(qǐng)求查詢的數(shù)據(jù)不在該HFile中蝉绷。

HFile中的位數(shù)組就是上述Bloom Block中存儲(chǔ)的值,可以想象枣抱,一個(gè)HFile文件越大熔吗,里面存儲(chǔ)的KeyValue值越多,位數(shù)組就會(huì)相應(yīng)越大佳晶。一旦太大就不適合直接加載到內(nèi)存了桅狠,因此HFile V2在設(shè)計(jì)上將位數(shù)組進(jìn)行了拆分,拆成了多個(gè)獨(dú)立的位數(shù)組(根據(jù)Key進(jìn)行拆分,一部分連續(xù)的Key使用一個(gè)位數(shù)組)中跌。這樣一個(gè)HFile中就會(huì)包含多個(gè)位數(shù)組咨堤,根據(jù)Key進(jìn)行查詢,首先會(huì)定位到具體的某個(gè)位數(shù)組漩符,只需要加載此位數(shù)組到內(nèi)存進(jìn)行過濾即可一喘,減少了內(nèi)存開支。

在結(jié)構(gòu)上每個(gè)位數(shù)組對(duì)應(yīng)HFile中一個(gè)Bloom Block嗜暴,為了方便根據(jù)Key定位具體需要加載哪個(gè)位數(shù)組凸克,HFile V2又設(shè)計(jì)了對(duì)應(yīng)的索引Bloom Index Block,對(duì)應(yīng)的內(nèi)存和邏輯結(jié)構(gòu)圖如下:


Bloom Index Block結(jié)構(gòu)中totalByteSize表示位數(shù)組的bit數(shù)闷沥,numChunks表示Bloom Block的個(gè)數(shù)萎战,hashCount表示hash函數(shù)的個(gè)數(shù),hashType表示hash函數(shù)的類型舆逃,totalKeyCount表示bloom filter當(dāng)前已經(jīng)包含的key的數(shù)目撞鹉,totalMaxKeys表示bloom filter當(dāng)前最多包含的key的數(shù)目, Bloom Index Entry對(duì)應(yīng)每一個(gè)bloom filter block的索引條目,作為索引分別指向’scanned block section’部分的Bloom Block颖侄,Bloom Block中就存儲(chǔ)了對(duì)應(yīng)的位數(shù)組鸟雏。

Bloom Index Entry的結(jié)構(gòu)見上圖左邊所示,BlockOffset表示對(duì)應(yīng)Bloom Block在HFile中的偏移量览祖,F(xiàn)irstKey表示對(duì)應(yīng)BloomBlock的第一個(gè)Key孝鹊。根據(jù)上文所說,一次get請(qǐng)求進(jìn)來展蒂,首先會(huì)根據(jù)key在所有的索引條目中進(jìn)行二分查找又活,查找到對(duì)應(yīng)的Bloom Index Entry,就可以定位到該key對(duì)應(yīng)的位數(shù)組锰悼,加載到內(nèi)存進(jìn)行過濾判斷柳骄。

三、HFile V3

增加安全方面特性箕般,為cell級(jí)別增加ACL

HFile V3不和HFile V1和HFile V2兼容耐薯,因?yàn)樵诖鎯?chǔ)keyvalue的時(shí)候,會(huì)額外的存儲(chǔ)tags丝里,用于控制ACL曲初。

四、總結(jié)

hbase的三個(gè)版本的hfile在文件結(jié)構(gòu)層面逐漸完善杯聚,每個(gè)hfile文件都有自己獨(dú)立的索引臼婆。理解這些結(jié)構(gòu)對(duì)實(shí)際應(yīng)用業(yè)務(wù)優(yōu)化也是很有好處的。例如有很多場(chǎng)景需要多hbase的resion進(jìn)行遍歷而內(nèi)存資源又有限的情況幌绍,假設(shè)計(jì)算引擎用的是spark颁褂,那么每個(gè)分區(qū)遍歷一個(gè)region是不可能的故响,因?yàn)閿?shù)據(jù)量太多,資源吃不下颁独,而根據(jù)timestamp過濾分批遍歷的話彩届,性能有影響,相當(dāng)于每個(gè)region都要被重復(fù)遍歷奖唯。這種場(chǎng)景下惨缆,可以對(duì)region按照rowkey分割,每個(gè)spark分區(qū)只遍歷一個(gè)region的部分rowkey丰捷,這樣就可以無限拆分下去坯墨,再不也不用擔(dān)心資源的問題。不過這就又出現(xiàn)了一個(gè)問題病往,如果用rowkey切割region捣染,首先,rowkey如果設(shè)計(jì)的好的話停巷,不同rowkey段的數(shù)據(jù)很均勻耍攘,那么可以直接根據(jù)業(yè)務(wù)切分。而如果無法評(píng)估出不同rowkey段和數(shù)據(jù)的對(duì)應(yīng)關(guān)系畔勤,那么這個(gè)時(shí)候蕾各,可以利用到hfile。通過查看region下hfile文件中每個(gè)datablock的第一個(gè)rowkey庆揪,(由于datablock的index都是被保存在hfile的式曲,所以datablock可被直接定位),用該rowkey切割region缸榛,并且可以以最小block的粒度來控制每批遍歷region的數(shù)據(jù)量吝羞,這個(gè)粒度相信資源是完全夠用的。

參考:
https://hbase.apache.org/book.html#_hfile_format_2

http://wangneng-168.iteye.com/blog/2164299

http://hbasefly.com/2016/03/25/hbase-hfile/

https://blog.csdn.net/BlackArmand/article/details/119933879

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末内颗,一起剝皮案震驚了整個(gè)濱河市钧排,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌均澳,老刑警劉巖恨溜,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異负懦,居然都是意外死亡筒捺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門纸厉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人五嫂,你說我怎么就攤上這事颗品】铣撸” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我系馆,道長暖眼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任颜凯,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘敬扛。我一直安慰自己,他們只是感情好朝抖,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布啥箭。 她就那樣靜靜地躺著,像睡著了一般治宣。 火紅的嫁衣襯著肌膚如雪急侥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天侮邀,我揣著相機(jī)與錄音坏怪,去河邊找鬼。 笑死绊茧,一個(gè)胖子當(dāng)著我的面吹牛铝宵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播按傅,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼捉超,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了唯绍?” 一聲冷哼從身側(cè)響起拼岳,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎况芒,沒想到半個(gè)月后惜纸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡绝骚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年耐版,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片压汪。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡粪牲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出止剖,到底是詐尸還是另有隱情腺阳,我是刑警寧澤落君,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站亭引,受9級(jí)特大地震影響绎速,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜焙蚓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一纹冤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧购公,春花似錦萌京、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绘闷,卻和暖如春橡庞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背印蔗。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來泰國打工扒最, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人华嘹。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓吧趣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親耙厚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子强挫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容