公司內(nèi)部使用的是MapR版本的Hadoop生態(tài)系統(tǒng),因而從MapR的官網(wǎng)看到了這篇文文章: An In-Depth Look at the HBase Architecture ,原本想翻譯全文,然而如果翻譯就需要各種咬文嚼字,太麻煩,因而本文大部分使用了自己的語言,并且加入了其他資源的參考理解以及本人自己讀源碼時(shí)對(duì)其的理解,屬于半翻譯、半原創(chuàng)吧。
創(chuàng)新互聯(lián)公司是一家專注于做網(wǎng)站、成都網(wǎng)站制作與策劃設(shè)計(jì),南城網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)公司做網(wǎng)站,專注于網(wǎng)站建設(shè)10多年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:南城等地區(qū)。南城做網(wǎng)站價(jià)格咨詢:028-86922220HBase采用Master/Slave架構(gòu)搭建集群,它隸屬于Hadoop生態(tài)系統(tǒng),由一下類型節(jié)點(diǎn)組成:HMaster節(jié)點(diǎn)、HRegionServer節(jié)點(diǎn)、ZooKeeper集群,而在底層,它將數(shù)據(jù)存儲(chǔ)于HDFS中,因而涉及到HDFS的NameNode、DataNode等,總體結(jié)構(gòu)如下:
其中
HMaster節(jié)點(diǎn)
用于:
管理HRegionServer,實(shí)現(xiàn)其負(fù)載均衡。
管理和分配HRegion,比如在HRegion split時(shí)分配新的HRegion;在HRegionServer退出時(shí)遷移其內(nèi)的HRegion到其他HRegionServer上。
實(shí)現(xiàn)DDL操作(Data Definition Language,namespace和table的增刪改,column familiy的增刪改等)。
管理namespace和table的元數(shù)據(jù)(實(shí)際存儲(chǔ)在HDFS上)。
權(quán)限控制(ACL)。
HRegionServer節(jié)點(diǎn) 用于:
存放和管理本地HRegion。
讀寫HDFS,管理Table中的數(shù)據(jù)。
Client直接通過HRegionServer讀寫數(shù)據(jù)(從HMaster中獲取元數(shù)據(jù),找到RowKey所在的HRegion/HRegionServer后)。
ZooKeeper集群是協(xié)調(diào)系統(tǒng) ,用于:
存放整個(gè) HBase集群的元數(shù)據(jù)以及集群的狀態(tài)信息。
實(shí)現(xiàn)HMaster主從節(jié)點(diǎn)的failover。
HBase Client通過RPC方式和HMaster、HRegionServer通信;一個(gè)HRegionServer可以存放1000個(gè)HRegion;底層Table數(shù)據(jù)存儲(chǔ)于HDFS中,而HRegion所處理的數(shù)據(jù)盡量和數(shù)據(jù)所在的DataNode在一起,實(shí)現(xiàn)數(shù)據(jù)的本地化;數(shù)據(jù)本地化并不是總能實(shí)現(xiàn),比如在HRegion移動(dòng)(如因Split)時(shí),需要等下一次Compact才能繼續(xù)回到本地化。
本著半翻譯的原則,再貼一個(gè)《An In-Depth Look At The HBase Architecture》的架構(gòu)圖:
這個(gè)架構(gòu)圖比較清晰的表達(dá)了HMaster和NameNode都支持多個(gè)熱備份,使用ZooKeeper來做協(xié)調(diào);ZooKeeper并不是云般神秘,它一般由三臺(tái)機(jī)器組成一個(gè)集群,內(nèi)部使用PAXOS算法支持三臺(tái)Server中的一臺(tái)宕機(jī),也有使用五臺(tái)機(jī)器的,此時(shí)則可以支持同時(shí)兩臺(tái)宕機(jī),既少于半數(shù)的宕機(jī),然而隨著機(jī)器的增加,它的性能也會(huì)下降;RegionServer和DataNode一般會(huì)放在相同的Server上實(shí)現(xiàn)數(shù)據(jù)的本地化。
HBase使用RowKey將表水平切割成多個(gè)HRegion,從HMaster的角度,每個(gè)HRegion都紀(jì)錄了它的StartKey和EndKey(第一個(gè)HRegion的StartKey為空,最后一個(gè)HRegion的EndKey為空),由于RowKey是排序的,因而Client可以通過HMaster快速的定位每個(gè)RowKey在哪個(gè)HRegion中。HRegion由HMaster分配到相應(yīng)的HRegionServer中,然后由HRegionServer負(fù)責(zé)HRegion的啟動(dòng)和管理,和Client的通信,負(fù)責(zé)數(shù)據(jù)的讀(使用HDFS)。每個(gè)HRegionServer可以同時(shí)管理1000個(gè)左右的HRegion(這個(gè)數(shù)字怎么來的?沒有從代碼中看到限制,難道是出于經(jīng)驗(yàn)?超過1000個(gè)會(huì)引起性能問題?
來回答這個(gè)問題
:感覺這個(gè)1000的數(shù)字是從BigTable的論文中來的(5 Implementation節(jié)):Each tablet server manages a set of tablets(typically we have somewhere between ten to a thousand tablets per tablet server))。
HMaster沒有單點(diǎn)故障問題,可以啟動(dòng)多個(gè)HMaster,通過ZooKeeper的Master Election機(jī)制保證同時(shí)只有一個(gè)HMaster出于Active狀態(tài),其他的HMaster則處于熱備份狀態(tài)。一般情況下會(huì)啟動(dòng)兩個(gè)HMaster,非Active的HMaster會(huì)定期的和Active HMaster通信以獲取其最新狀態(tài),從而保證它是實(shí)時(shí)更新的,因而如果啟動(dòng)了多個(gè)HMaster反而增加了Active HMaster的負(fù)擔(dān)。前文已經(jīng)介紹過了HMaster的主要用于HRegion的分配和管理,DDL(Data Definition Language,既Table的新建、刪除、修改等)的實(shí)現(xiàn)等,既它主要有兩方面的職責(zé):
協(xié)調(diào)HRegionServer
啟動(dòng)時(shí)HRegion的分配,以及負(fù)載均衡和修復(fù)時(shí)HRegion的重新分配。
監(jiān)控集群中所有HRegionServer的狀態(tài)(通過Heartbeat和監(jiān)聽ZooKeeper中的狀態(tài))。
Admin職能
創(chuàng)建、刪除、修改Table的定義。
ZooKeeper為HBase集群提供協(xié)調(diào)服務(wù),它管理著HMaster和HRegionServer的狀態(tài)(available/alive等),并且會(huì)在它們宕機(jī)時(shí)通知給HMaster,從而HMaster可以實(shí)現(xiàn)HMaster之間的failover,或?qū)﹀礄C(jī)的HRegionServer中的HRegion集合的修復(fù)(將它們分配給其他的HRegionServer)。ZooKeeper集群本身使用一致性協(xié)議(PAXOS協(xié)議)保證每個(gè)節(jié)點(diǎn)狀態(tài)的一致性。
ZooKeeper協(xié)調(diào)集群所有節(jié)點(diǎn)的共享信息,在HMaster和HRegionServer連接到ZooKeeper后創(chuàng)建Ephemeral節(jié)點(diǎn),并使用Heartbeat機(jī)制維持這個(gè)節(jié)點(diǎn)的存活狀態(tài),如果某個(gè)Ephemeral節(jié)點(diǎn)實(shí)效,則HMaster會(huì)收到通知,并做相應(yīng)的處理。
另外,HMaster通過監(jiān)聽ZooKeeper中的Ephemeral節(jié)點(diǎn)(默認(rèn):/hbase/rs/*)來監(jiān)控HRegionServer的加入和宕機(jī)。在第一個(gè)HMaster連接到ZooKeeper時(shí)會(huì)創(chuàng)建Ephemeral節(jié)點(diǎn)(默認(rèn):/hbasae/master)來表示Active的HMaster,其后加進(jìn)來的HMaster則監(jiān)聽該Ephemeral節(jié)點(diǎn),如果當(dāng)前Active的HMaster宕機(jī),則該節(jié)點(diǎn)消失,因而其他HMaster得到通知,而將自身轉(zhuǎn)換成Active的HMaster,在變?yōu)锳ctive的HMaster之前,它會(huì)創(chuàng)建在/hbase/back-masters/下創(chuàng)建自己的Ephemeral節(jié)點(diǎn)。
在HBase 0.96以前,HBase有兩個(gè)特殊的Table:-ROOT-和.META.(如
BigTable
中的設(shè)計(jì)),其中-ROOT- Table的位置存儲(chǔ)在ZooKeeper,它存儲(chǔ)了.META. Table的RegionInfo信息,并且它只能存在一個(gè)HRegion,而.META. Table則存儲(chǔ)了用戶Table的RegionInfo信息,它可以被切分成多個(gè)HRegion,因而對(duì)第一次訪問用戶Table時(shí),首先從ZooKeeper中讀取-ROOT- Table所在HRegionServer;然后從該HRegionServer中根據(jù)請(qǐng)求的TableName,RowKey讀取.META. Table所在HRegionServer;最后從該HRegionServer中讀取.META. Table的內(nèi)容而獲取此次請(qǐng)求需要訪問的HRegion所在的位置,然后訪問該HRegionSever獲取請(qǐng)求的數(shù)據(jù),這需要三次請(qǐng)求才能找到用戶Table所在的位置,然后第四次請(qǐng)求開始獲取真正的數(shù)據(jù)。當(dāng)然為了提升性能,客戶端會(huì)緩存-ROOT- Table位置以及-ROOT-/.META. Table的內(nèi)容。如下圖所示:
可是即使客戶端有緩存,在初始階段需要三次請(qǐng)求才能直到用戶Table真正所在的位置也是性能低下的,而且真的有必要支持那么多的HRegion嗎?或許對(duì)Google這樣的公司來說是需要的,但是對(duì)一般的集群來說好像并沒有這個(gè)必要。在BigTable的論文中說,每行METADATA存儲(chǔ)1KB左右數(shù)據(jù),中等大小的Tablet(HRegion)在128MB左右,3層位置的Schema設(shè)計(jì)可以支持2^34個(gè)Tablet(HRegion)。即使去掉-ROOT- Table,也還可以支持2^17(131072)個(gè)HRegion, 如果每個(gè)HRegion還是128MB,那就是16TB,這個(gè)貌似不夠大,但是現(xiàn)在的HRegion的大大小都會(huì)設(shè)置的比較大,比如我們?cè)O(shè)置了2GB,此時(shí)支持的大小則變成了4PB,對(duì)一般的集群來說已經(jīng)夠了,因而在HBase 0.96以后去掉了-ROOT- Table,只剩下這個(gè)特殊的目錄表叫做Meta Table(hbase:meta),它存儲(chǔ)了集群中所有用戶HRegion的位置信息,而ZooKeeper的節(jié)點(diǎn)中(/hbase/meta-region-server)存儲(chǔ)的則直接是這個(gè)Meta Table的位置,并且這個(gè)Meta Table如以前的-ROOT- Table一樣是不可split的。這樣,客戶端在第一次訪問用戶Table的流程就變成了:
從ZooKeeper(/hbase/meta-region-server)中獲取hbase:meta的位置(HRegionServer的位置),緩存該位置信息。
從HRegionServer中查詢用戶Table對(duì)應(yīng)請(qǐng)求的RowKey所在的HRegionServer,緩存該位置信息。
從查詢到HRegionServer中讀取Row。
從這個(gè)過程中,我們發(fā)現(xiàn)客戶會(huì)緩存這些位置信息,然而第二步它只是緩存當(dāng)前RowKey對(duì)應(yīng)的HRegion的位置,因而如果下一個(gè)要查的RowKey不在同一個(gè)HRegion中,則需要繼續(xù)查詢hbase:meta所在的HRegion,然而隨著時(shí)間的推移,客戶端緩存的位置信息越來越多,以至于不需要再次查找hbase:meta Table的信息,除非某個(gè)HRegion因?yàn)殄礄C(jī)或Split被移動(dòng),此時(shí)需要重新查詢并且更新緩存。
hbase:meta表存儲(chǔ)了所有用戶HRegion的位置信息,它的RowKey是:tableName,regionStartKey,regionId,replicaId等,它只有info列族,這個(gè)列族包含三個(gè)列,他們分別是:info:regioninfo列是RegionInfo的proto格式:regionId,tableName,startKey,endKey,offline,split,replicaId;info:server格式:HRegionServer對(duì)應(yīng)的server:port;info:serverstartcode格式是HRegionServer的啟動(dòng)時(shí)間戳。
HRegionServer一般和DataNode在同一臺(tái)機(jī)器上運(yùn)行,實(shí)現(xiàn)數(shù)據(jù)的本地性。HRegionServer包含多個(gè)HRegion,由WAL(HLog)、BlockCache、MemStore、HFile組成。
WAL即Write Ahead Log ,在早期版本中稱為HLog,它是HDFS上的一個(gè)文件,如其名字所表示的,所有寫操作都會(huì)先保證將數(shù)據(jù)寫入這個(gè)Log文件后,才會(huì)真正更新MemStore,最后寫入HFile中。采用這種模式,可以保證HRegionServer宕機(jī)后,我們依然可以從該Log文件中讀取數(shù)據(jù),Replay所有的操作,而不至于數(shù)據(jù)丟失。這個(gè)Log文件會(huì)定期Roll出新的文件而刪除舊的文件(那些已持久化到HFile中的Log可以刪除)。WAL文件存儲(chǔ)在/hbase/WALs/${HRegionServer_Name}的目錄中(在0.94之前,存儲(chǔ)在/hbase/.logs/目錄中),一般一個(gè)HRegionServer只有一個(gè)WAL實(shí)例,也就是說一個(gè)HRegionServer的所有WAL寫都是串行的(就像log4j的日志寫也是串行的),這當(dāng)然會(huì)引起性能問題,因而在HBase 1.0之后,通過 HBASE-5699 實(shí)現(xiàn)了多個(gè)WAL并行寫(MultiWAL),該實(shí)現(xiàn)采用HDFS的多個(gè)管道寫,以單個(gè)HRegion為單位。關(guān)于WAL可以參考Wikipedia的 Write-Ahead Logging 。順便吐槽一句,英文版的維基百科竟然能毫無壓力的正常訪問了,這是某個(gè)GFW的疏忽還是以后的常態(tài)?
BlockCache是一個(gè)讀緩存 ,即“引用局部性”原理(也應(yīng)用于CPU, 分空間局部性和時(shí)間局部性 ,空間局部性是指CPU在某一時(shí)刻需要某個(gè)數(shù)據(jù),那么有很大的概率在一下時(shí)刻它需要的數(shù)據(jù)在其附近;時(shí)間局部性是指某個(gè)數(shù)據(jù)在被訪問過一次后,它有很大的概率在不久的將來會(huì)被再次的訪問),將數(shù)據(jù)預(yù)讀取到內(nèi)存中,以提升讀的性能。HBase中提供兩種BlockCache的實(shí)現(xiàn):默認(rèn)on-heap LruBlockCache和BucketCache(通常是off-heap)。通常BucketCache的性能要差于LruBlockCache,然而由于GC的影響,LruBlockCache的延遲會(huì)變的不穩(wěn)定,而BucketCache由于是自己管理BlockCache,而不需要GC,因而它的延遲通常比較穩(wěn)定,這也是有些時(shí)候需要選用BucketCache的原因。這篇文章 BlockCache101 對(duì)on-heap和off-heap的BlockCache做了詳細(xì)的比較。
HRegion是一個(gè)Table中的一個(gè)Region在一個(gè)HRegionServer中的表達(dá) 。一個(gè)Table可以有一個(gè)或多個(gè)Region,他們可以在一個(gè)相同的HRegionServer上,也可以分布在不同的HRegionServer上,一個(gè)HRegionServer可以有多個(gè)HRegion,他們分別屬于不同的Table。HRegion由多個(gè)Store(HStore)構(gòu)成,每個(gè)HStore對(duì)應(yīng)了一個(gè)Table在這個(gè)HRegion中的一個(gè)Column Family,即每個(gè)Column Family就是一個(gè)集中的存儲(chǔ)單元,因而最好將具有相近IO特性的Column存儲(chǔ)在一個(gè)Column Family,以實(shí)現(xiàn)高效讀取(數(shù)據(jù)局部性原理,可以提高緩存的命中率)。HStore是HBase中存儲(chǔ)的核心,它實(shí)現(xiàn)了讀寫HDFS功能,一個(gè)HStore由一個(gè)MemStore 和0個(gè)或多個(gè)StoreFile組成。
MemStore是一個(gè)寫緩存 (In Memory Sorted Buffer),所有數(shù)據(jù)的寫在完成WAL日志寫后,會(huì) 寫入MemStore中,由MemStore根據(jù)一定的算法將數(shù)據(jù)Flush到地層HDFS文件中(HFile),通常每個(gè)HRegion中的每個(gè) Column Family有一個(gè)自己的MemStore。
HFile(StoreFile) 用于存儲(chǔ)HBase的數(shù)據(jù)(Cell/KeyValue) 。在HFile中的數(shù)據(jù)是按RowKey、Column Family、Column排序,對(duì)相同的Cell(即這三個(gè)值都一樣),則按timestamp倒序排列。
雖然上面這張圖展現(xiàn)的是最新的HRegionServer的架構(gòu)(但是并不是那么的精確),但是我一直比較喜歡看以下這張圖,即使它展現(xiàn)的應(yīng)該是0.94以前的架構(gòu)。
當(dāng)客戶端發(fā)起一個(gè)Put請(qǐng)求時(shí),首先它從hbase:meta表中查出該P(yáng)ut數(shù)據(jù)最終需要去的HRegionServer。然后客戶端將Put請(qǐng)求發(fā)送給相應(yīng)的HRegionServer,在HRegionServer中它首先會(huì)將該P(yáng)ut操作寫入WAL日志文件中(Flush到磁盤中)。
寫完WAL日志文件后,HRegionServer根據(jù)Put中的TableName和RowKey找到對(duì)應(yīng)的HRegion,并根據(jù)Column Family找到對(duì)應(yīng)的HStore,并將Put寫入到該HStore的MemStore中。此時(shí)寫成功,并返回通知客戶端。
MemStore是一個(gè)In Memory Sorted Buffer,在每個(gè)HStore中都有一個(gè)MemStore,即它是一個(gè)HRegion的一個(gè)Column Family對(duì)應(yīng)一個(gè)實(shí)例。它的排列順序以RowKey、Column Family、Column的順序以及Timestamp的倒序,如下所示:
每一次Put/Delete請(qǐng)求都是先寫入到MemStore中,當(dāng)MemStore滿后會(huì)Flush成一個(gè)新的StoreFile(底層實(shí)現(xiàn)是HFile),即一個(gè)HStore(Column Family)可以有0個(gè)或多個(gè)StoreFile(HFile)。有以下三種情況可以觸發(fā)MemStore的Flush動(dòng)作,
需要注意的是MemStore的最小Flush單元是HRegion而不是單個(gè)MemStore
。據(jù)說這是Column Family有個(gè)數(shù)限制的其中一個(gè)原因,估計(jì)是因?yàn)樘嗟腃olumn Family一起Flush會(huì)引起性能問題?具體原因有待考證。
當(dāng)一個(gè)HRegion中的所有MemStore的大小總和超過了hbase.hregion.memstore.flush.size的大小,默認(rèn)128MB。此時(shí)當(dāng)前的HRegion中所有的MemStore會(huì)Flush到HDFS中。
當(dāng)全局MemStore的大小超過了hbase.regionserver.global.memstore.upperLimit的大小,默認(rèn)40%的內(nèi)存使用量。此時(shí)當(dāng)前HRegionServer中所有HRegion中的MemStore都會(huì)Flush到HDFS中,F(xiàn)lush順序是MemStore大小的倒序(一個(gè)HRegion中所有MemStore總和作為該HRegion的MemStore的大小還是選取大的MemStore作為參考?有待考證),直到總體的MemStore使用量低于hbase.regionserver.global.memstore.lowerLimit,默認(rèn)38%的內(nèi)存使用量。
當(dāng)前HRegionServer中WAL的大小超過了hbase.regionserver.hlog.blocksize * hbase.regionserver.max.logs的數(shù)量,當(dāng)前HRegionServer中所有HRegion中的MemStore都會(huì)Flush到HDFS中,F(xiàn)lush使用時(shí)間順序,最早的MemStore先Flush直到WAL的數(shù)量少于hbase.regionserver.hlog.blocksize * hbase.regionserver.max.logs。 這里 說這兩個(gè)相乘的默認(rèn)大小是2GB,查代碼,hbase.regionserver.max.logs默認(rèn)值是32,而hbase.regionserver.hlog.blocksize是HDFS的默認(rèn)blocksize,32MB。但不管怎么樣,因?yàn)檫@個(gè)大小超過限制引起的Flush不是一件好事,可能引起長時(shí)間的延遲,因而這篇文章給的建議:“ Hint : keep hbase.regionserver.hlog.blocksize * hbase.regionserver.maxlogs just a bit above hbase.regionserver.global.memstore.lowerLimit * HBASE_HEAPSIZE. ”。并且需要注意, 這里 給的描述是有錯(cuò)的(雖然它是官方的文檔)。
在MemStore Flush過程中,還會(huì)在尾部追加一些meta數(shù)據(jù),其中就包括Flush時(shí)大的WAL sequence值,以告訴HBase這個(gè)StoreFile寫入的最新數(shù)據(jù)的序列,那么在Recover時(shí)就直到從哪里開始。在HRegion啟動(dòng)時(shí),這個(gè)sequence會(huì)被讀取,并取大的作為下一次更新時(shí)的起始sequence。
HBase的數(shù)據(jù)以KeyValue(Cell)的形式順序的存儲(chǔ)在HFile中,在MemStore的Flush過程中生成HFile,由于MemStore中存儲(chǔ)的Cell遵循相同的排列順序,因而Flush過程是順序?qū)?,我們直到磁盤的順序?qū)懶阅芎芨撸驗(yàn)椴恍枰煌5囊苿?dòng)磁盤指針。
HFile參考BigTable的SSTable和Hadoop的
TFile
實(shí)現(xiàn),從HBase開始到現(xiàn)在,HFile經(jīng)歷了三個(gè)版本,其中V2在0.92引入,V3在0.98引入。首先我們來看一下V1的格式:
V1的HFile由多個(gè)Data Block、Meta Block、FileInfo、Data Index、Meta Index、Trailer組成,其中Data Block是HBase的最小存儲(chǔ)單元,在前文中提到的BlockCache就是基于Data Block的緩存的。一個(gè)Data Block由一個(gè)魔數(shù)和一系列的KeyValue(Cell)組成,魔數(shù)是一個(gè)隨機(jī)的數(shù)字,用于表示這是一個(gè)Data Block類型,以快速監(jiān)測這個(gè)Data Block的格式,防止數(shù)據(jù)的破壞。Data Block的大小可以在創(chuàng)建Column Family時(shí)設(shè)置(HColumnDescriptor.setBlockSize()),默認(rèn)值是64KB,大號(hào)的Block有利于順序Scan,小號(hào)Block利于隨機(jī)查詢,因而需要權(quán)衡。Meta塊是可選的,F(xiàn)ileInfo是固定長度的塊,它紀(jì)錄了文件的一些Meta信息,例如:AVG_KEY_LEN, AVG_VALUE_LEN, LAST_KEY, COMPARATOR, MAX_SEQ_ID_KEY等。Data Index和Meta Index紀(jì)錄了每個(gè)Data塊和Meta塊的其實(shí)點(diǎn)、未壓縮時(shí)大小、Key(起始RowKey?)等。Trailer紀(jì)錄了FileInfo、Data Index、Meta Index塊的起始位置,Data Index和Meta Index索引的數(shù)量等。其中FileInfo和Trailer是固定長度的。
HFile里面的每個(gè)KeyValue對(duì)就是一個(gè)簡單的byte數(shù)組。但是這個(gè)byte數(shù)組里面包含了很多項(xiàng),并且有固定的結(jié)構(gòu)。我們來看看里面的具體結(jié)構(gòu):
開始是兩個(gè)固定長度的數(shù)值,分別表示Key的長度和Value的長度。緊接著是Key,開始是固定長度的數(shù)值,表示RowKey的長度,緊接著是 RowKey,然后是固定長度的數(shù)值,表示Family的長度,然后是Family,接著是Qualifier,然后是兩個(gè)固定長度的數(shù)值,表示Time Stamp和Key Type(Put/Delete)。Value部分沒有這么復(fù)雜的結(jié)構(gòu),就是純粹的二進(jìn)制數(shù)據(jù)了。
隨著HFile版本遷移,KeyValue(Cell)的格式并未發(fā)生太多變化,只是在V3版本,尾部添加了一個(gè)可選的Tag數(shù)組
。
HFileV1版本的在實(shí)際使用過程中發(fā)現(xiàn)它占用內(nèi)存多,并且Bloom File和Block Index會(huì)變的很大,而引起啟動(dòng)時(shí)間變長。其中每個(gè)HFile的Bloom Filter可以增長到100MB,這在查詢時(shí)會(huì)引起性能問題,因?yàn)槊看尾樵儠r(shí)需要加載并查詢Bloom Filter,100MB的Bloom Filer會(huì)引起很大的延遲;另一個(gè),Block Index在一個(gè)HRegionServer可能會(huì)增長到總共6GB,HRegionServer在啟動(dòng)時(shí)需要先加載所有這些Block Index,因而增加了啟動(dòng)時(shí)間。為了解決這些問題,在0.92版本中引入HFileV2版本:
在這個(gè)版本中,Block Index和Bloom Filter添加到了Data Block中間,而這種設(shè)計(jì)同時(shí)也減少了寫的內(nèi)存使用量;另外,為了提升啟動(dòng)速度,在這個(gè)版本中還引入了延遲讀的功能,即在HFile真正被使用時(shí)才對(duì)其進(jìn)行解析。
FileV3版本基本和V2版本相比,并沒有太大的改變,它在KeyValue(Cell)層面上添加了Tag數(shù)組的支持;并在FileInfo結(jié)構(gòu)中添加了和Tag相關(guān)的兩個(gè)字段。關(guān)于具體HFile格式演化介紹,可以參考
這里
。
對(duì)HFileV2格式具體分析,它是一個(gè)多層的類B+樹索引,采用這種設(shè)計(jì),可以實(shí)現(xiàn)查找不需要讀取整個(gè)文件:
Data Block中的Cell都是升序排列,每個(gè)block都有它自己的Leaf-Index,每個(gè)Block的最后一個(gè)Key被放入Intermediate-Index中,Root-Index指向Intermediate-Index。在HFile的末尾還有Bloom Filter用于快速定位那么沒有在某個(gè)Data Block中的Row;TimeRange信息用于給那些使用時(shí)間查詢的參考。在HFile打開時(shí),這些索引信息都被加載并保存在內(nèi)存中,以增加以后的讀取性能。
這篇就先寫到這里,未完待續(xù)。。。。
https://www.mapr.com/blog/in-depth-look-hbase-architecture#.VdNSN6Yp3qx
http://jimbojw.com/wiki/index.php?title=Understanding_Hbase_and_BigTable
http://hbase.apache.org/book.html
http://www.searchtb.com/2011/01/understanding-hbase.html
http://research.google.com/archive/bigtable-osdi06.pdf
原文轉(zhuǎn)自:http://www.blogjava.net/DLevin/archive/2015/08/22/426877.html