架構(gòu)組成
HBase采用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)如下:
?
在物理上,HBase由master/slave類型體系結(jié)構(gòu)中的三種服務(wù)器組成。RegionServer為讀取和寫入提供數(shù)據(jù)。訪問(wèn)數(shù)據(jù)時(shí),Client直接與Region Server通信。Region的分配,DDL(創(chuàng)建,刪除表)操作由HMaster處理。作為HDFS一部分的Zookeeper維護(hù)活動(dòng)集群狀態(tài)。 Hadoop DataNode存儲(chǔ)Region Server正在管理的數(shù)據(jù)。所有HBase數(shù)據(jù)都存儲(chǔ)在HDFS文件中。Region Server與HDFS數(shù)據(jù)節(jié)點(diǎn)并置,從而為Region Server提供的數(shù)據(jù)實(shí)現(xiàn)數(shù)據(jù)局部性。除了Region在Split的時(shí)候,Hbase寫入不是本地的,但是在Hbase在完成compaction之后 HBase數(shù)據(jù)是基于Local寫入的。NameNode維護(hù)構(gòu)成文件的所有物理數(shù)據(jù)塊的元數(shù)據(jù)信息。
山東掌趣網(wǎng)絡(luò)科技
?
Regions
HBase表按RowKey范圍水平劃分為“Region”。一個(gè)Region包含表中該Region的開(kāi)始鍵和結(jié)束鍵之間的所有行。將Region分配給群集中稱為“Region Server”的節(jié)點(diǎn),這些Region Server為讀取和寫入提供數(shù)據(jù)。Region Server可以服務(wù)大約1,000個(gè)區(qū)域。
山東掌趣網(wǎng)絡(luò)科技
?
HBase HMaster
區(qū)Region分配,DDL(創(chuàng)建,刪除表)操作由HBase Master處理。
HBase Master主要負(fù)責(zé):
Coordinating the region servers
- Assigning regions on startup , re-assigning regions for recovery or load balancing
- Monitoring all RegionServer instances in the cluster (listens for notifications from zookeeper)
Admin functions
- Interface for creating, deleting, updating tables
山東掌趣網(wǎng)絡(luò)科技
?
ZooKeeper
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)的一致性。
?山東掌趣網(wǎng)絡(luò)科技
?
總結(jié)
Zookeeper用于協(xié)調(diào)分布式系統(tǒng)成員的共享狀態(tài)信息。Region Server和Active的HMaster通過(guò)與ZooKeeper的會(huì)話連接。 ZooKeeper通過(guò)心跳維護(hù)臨時(shí)節(jié)點(diǎn)以進(jìn)行活動(dòng)會(huì)話。
山東掌趣網(wǎng)絡(luò)科技
每個(gè)RegionServer都會(huì)創(chuàng)建一個(gè)臨時(shí)節(jié)點(diǎn)。 HMaster監(jiān)視這些節(jié)點(diǎn)以發(fā)現(xiàn)可用的Region Server,并且還監(jiān)視這些節(jié)點(diǎn)的服務(wù)器故障。 HMasters試圖創(chuàng)建一個(gè)臨時(shí)節(jié)點(diǎn)。 Zookeeper確定第一個(gè)Master,并使用它來(lái)確保只有一個(gè)Master處于Active狀態(tài)?;顒?dòng)的HMaster將心跳發(fā)送到Zookeeper,非活動(dòng)的HMaster偵聽(tīng)活動(dòng)的HMaster故障的通知。 如果Region Server或Active的HMaster無(wú)法發(fā)送心跳,則會(huì)話過(guò)期,并刪除相應(yīng)的臨時(shí)節(jié)點(diǎn)。更新的偵聽(tīng)器將被通知已刪除的節(jié)點(diǎn)。Active的HMaster偵聽(tīng)Region Sever,并在發(fā)生故障時(shí)恢復(fù)Region Server。非活動(dòng)HMaster偵聽(tīng)活動(dòng)的HMaster故障,如果Active的HMaster發(fā)生故障,則非活動(dòng)的HMaster會(huì)變?yōu)榛顒?dòng)狀態(tài)。
HBase首先讀取或?qū)懭?/p>
有一個(gè)稱為META表的特殊HBase目錄表,該表保存集群中Region的位置。 ZooKeeper存儲(chǔ)META表的位置信息。
這是客戶端第一次讀取或?qū)懭際Base時(shí)發(fā)生的情況:
1、客戶端從ZooKeeper獲取托管META表的Region服務(wù)器。
2、客戶端將查詢.META。服務(wù)器以獲取與要訪問(wèn)的行鍵相對(duì)應(yīng)的區(qū)域服務(wù)器??蛻舳藢⒃撔畔⑴cMETA表位置一起緩存。
3、它將從相應(yīng)的區(qū)域服務(wù)器獲取行。
為了將來(lái)讀取,客戶端使用緩存來(lái)檢索META位置和先前讀取的行鍵。隨著時(shí)間的流逝,它不需要查詢META表,除非由于區(qū)域移動(dòng)導(dǎo)致遺漏;然后它將重新查詢并更新緩存。
?山東掌趣網(wǎng)絡(luò)科技
?
META表
hbase:meta表存儲(chǔ)了所有用戶HRegion的位置信息,它的RowKey是:tableName,regionStartKey,regionId,replicaId等,它只有info列族,這個(gè)列族包含三個(gè)列,他們分別是:
info:regioninfo:regionId,tableName,startKey,endKey,offline,split,replicaId;
info:server:HRegionServer對(duì)應(yīng)的server:port;
info:serverstartcode:HRegionServer的啟動(dòng)時(shí)間戳。
?山東掌趣網(wǎng)絡(luò)科技
?HRegion Server
Region Server在HDFS數(shù)據(jù)節(jié)點(diǎn)上運(yùn)行,并具有以下組件:
WAL: 預(yù)寫日志是分布式文件系統(tǒng)上的文件。 WAL用于存儲(chǔ)尚未持久存儲(chǔ)的新數(shù)據(jù)。發(fā)生故障時(shí)用于恢復(fù)。
BlockCache:是讀取緩存。它將經(jīng)常讀取的數(shù)據(jù)存儲(chǔ)在內(nèi)存中。滿時(shí)將逐出最近最少使用的數(shù)據(jù)。
MemStore:是寫緩存。它存儲(chǔ)尚未寫入磁盤的新數(shù)據(jù)。在寫入磁盤之前先對(duì)其進(jìn)行排序。每個(gè)區(qū)域的每個(gè)列族都有一個(gè)MemStore。
HRegion:一個(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(In Memory Sorted Buffer),所有數(shù)據(jù)的寫在完成WAL日志寫后,會(huì) 寫入MemStore中,由MemStore根據(jù)一定的算法將數(shù)據(jù)Flush到地層HDFS文件中(HFile),通常每個(gè)HRegion中的每個(gè) Column Family有一個(gè)自己的MemStore。
HFile在HFile中的數(shù)據(jù)是按RowKey、Column Family、Column排序,對(duì)相同的Cell(即這三個(gè)值都一樣),則按timestamp倒序排列。
?山東掌趣網(wǎng)絡(luò)科技
?
當(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到磁盤中)。
?山東掌趣網(wǎng)絡(luò)科技
?
寫完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的倒序,如下所示:
?山東掌趣網(wǎng)絡(luò)科技
?
每一次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。
當(dāng)一個(gè)HRegion中的所有MemStore的大小總和超過(guò)了
hbase.hregion.memstore.flush.size的大小,默認(rèn)128MB。此時(shí)當(dāng)前的HRegion中所有的MemStore會(huì)Flush到HDFS中。
當(dāng)全局MemStore的大小超過(guò)了
hbase.regionserver.global.memstore.upperLimit的大小,默認(rèn)40%的內(nèi)存使用量。此時(shí)當(dāng)前HRegionServer中所有HRegion中的MemStore都會(huì)Flush到HDFS中,F(xiàn)lush順序是MemStore大小的倒序,直到總體的MemStore使用量低于
hbase.regionserver.global.memstore.lowerLimit,默認(rèn)38%的內(nèi)存使用量。
當(dāng)前HRegionServer中WAL的大小超過(guò)了
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
在MemStore Flush過(guò)程中,還會(huì)在尾部追加一些meta數(shù)據(jù),其中就包括Flush時(shí)最大的WAL sequence值,以告訴HBase這個(gè)StoreFile寫入的最新數(shù)據(jù)的序列,那么在Recover時(shí)就直到從哪里開(kāi)始。在HRegion啟動(dòng)時(shí),這個(gè)sequence會(huì)被讀取,并取最大的作為下一次更新時(shí)的起始sequence。
?山東掌趣網(wǎng)絡(luò)科技
HFile里面的每個(gè)KeyValue對(duì)就是一個(gè)簡(jiǎn)單的byte數(shù)組。但是這個(gè)by
te數(shù)組里面包含了很多項(xiàng),并且有固定的結(jié)構(gòu)。我們來(lái)看看里面的具體結(jié)構(gòu):
山東掌趣網(wǎng)絡(luò)科技
?
開(kāi)始是兩個(gè)固定長(zhǎng)度的數(shù)值,分別表示Key的長(zhǎng)度和Value的長(zhǎng)度。緊接著是Key,開(kāi)始是固定長(zhǎng)度的數(shù)值,表示RowKey的長(zhǎng)度,緊接著是 RowKey,然后是固定長(zhǎng)度的數(shù)值,表示Family的長(zhǎng)度,然后是Family,接著是Qualifier,然后是兩個(gè)固定長(zhǎng)度的數(shù)值,表示Time Stamp和Key Type(Put/Delete)。Value部分沒(méi)有這么復(fù)雜的結(jié)構(gòu),就是純粹的二進(jìn)制數(shù)據(jù)了。
HBase讀實(shí)現(xiàn)
通過(guò)上文的描述,我們知道在HBase寫時(shí),相同Cell(
RowKey/ColumnFamily/Column相同)并不保證在一起,甚至刪除一個(gè)Cell也只是寫入一個(gè)新的Cell,它含有Delete標(biāo)記,而不一定將一個(gè)Cell真正刪除了,因而這就引起了一個(gè)問(wèn)題,如何實(shí)現(xiàn)讀的問(wèn)題?要解決這個(gè)問(wèn)題,我們先來(lái)分析一下相同的Cell可能存在的位置:首先對(duì)新寫入的Cell,它會(huì)存在于MemStore中;然后對(duì)之前已經(jīng)Flush到HDFS中的Cell,它會(huì)存在于某個(gè)或某些StoreFile(HFile)中;最后,對(duì)剛讀取過(guò)的Cell,它可能存在于BlockCache中。既然相同的Cell可能存儲(chǔ)在三個(gè)地方,在讀取的時(shí)候只需要掃瞄這三個(gè)地方,然后將結(jié)果合并即可(Merge Read),在HBase中掃瞄的順序依次是:BlockCache、MemStore、StoreFile(HFile)。其中StoreFile的掃瞄先會(huì)使用Bloom Filter過(guò)濾那些不可能符合條件的HFile,然后使用Block Index快速定位Cell,并將其加載到BlockCache中,然后從BlockCache中讀取。我們知道一個(gè)HStore可能存在多個(gè)StoreFile(HFile),此時(shí)需要掃瞄多個(gè)HFile,如果HFile過(guò)多又是會(huì)引起性能問(wèn)題。
?山東掌趣網(wǎng)絡(luò)科技
?
MemStore每次Flush會(huì)創(chuàng)建新的HFile,而過(guò)多的HFile會(huì)引起讀的性能問(wèn)題,那么如何解決這個(gè)問(wèn)題呢?HBase采用Compaction機(jī)制來(lái)解決這個(gè)問(wèn)題在HBase中Compaction分為兩種:Minor Compaction和Major Compaction。
Minor Compaction是指選取一些小的、相鄰的StoreFile將他們合并成一個(gè)更大的StoreFile,在這個(gè)過(guò)程中不會(huì)處理已經(jīng)Deleted或Expired的Cell。一次Minor Compaction的結(jié)果是更少并且更大的StoreFile。
Major Compaction是指將所有的StoreFile合并成一個(gè)StoreFile,在這個(gè)過(guò)程中,標(biāo)記為Deleted的Cell會(huì)被刪除,而那些已經(jīng)Expired的Cell會(huì)被丟棄,那些已經(jīng)超過(guò)最多版本數(shù)的Cell會(huì)被丟棄。一次Major Compaction的結(jié)果是一個(gè)HStore只有一個(gè)StoreFile存在。Major Compaction可以手動(dòng)或自動(dòng)觸發(fā),然而由于它會(huì)引起很多的IO操作而引起性能問(wèn)題,因而它一般會(huì)被安排在周末、凌晨等集群比較閑的時(shí)間。
山東掌趣網(wǎng)絡(luò)科技
?
HRegion Split
最初,一個(gè)Table只有一個(gè)HRegion,隨著數(shù)據(jù)寫入增加,如果一個(gè)HRegion到達(dá)一定的大小,就需要Split成兩個(gè)HRegion,這個(gè)大小由
hbase.hregion.max.filesize指定,默認(rèn)為10GB。當(dāng)split時(shí),兩個(gè)新的HRegion會(huì)在同一個(gè)HRegionServer中創(chuàng)建,它們各自包含父HRegion一半的數(shù)據(jù),當(dāng)Split完成后,父HRegion會(huì)下線,而新的兩個(gè)子HRegion會(huì)向HMaster注冊(cè)上線,處于負(fù)載均衡的考慮,這兩個(gè)新的HRegion可能會(huì)被HMaster分配到其他的HRegionServer中。
山東掌趣網(wǎng)絡(luò)科技
?
在HRegion Split后,兩個(gè)新的HRegion最初會(huì)和之前的父HRegion在相同的HRegionServer上,出于負(fù)載均衡的考慮,HMaster可能會(huì)將其中的一個(gè)甚至兩個(gè)重新分配的其他的HRegionServer中,此時(shí)會(huì)引起有些HRegionServer處理的數(shù)據(jù)在其他節(jié)點(diǎn)上,直到下一次Major Compaction將數(shù)據(jù)從遠(yuǎn)端的節(jié)點(diǎn)移動(dòng)到本地節(jié)點(diǎn)。
HRegionServer Recovery
當(dāng)一臺(tái)HRegionServer宕機(jī)時(shí),由于它不再發(fā)送Heartbeat給ZooKeeper而被監(jiān)測(cè)到,此時(shí)ZooKeeper會(huì)通知HMaster,HMaster會(huì)檢測(cè)到哪臺(tái)HRegionServer宕機(jī),它將宕機(jī)的HRegionServer中的HRegion重新分配給其他的HRegionServer,同時(shí)HMaster會(huì)把宕機(jī)的HRegionServer相關(guān)的WAL拆分分配給相應(yīng)的HRegionServer(將拆分出的WAL文件寫入對(duì)應(yīng)的目的HRegionServer的WAL目錄中,并并寫入對(duì)應(yīng)的DataNode中),從而這些HRegionServer可以Replay分到的WAL來(lái)重建MemStore。
山東掌趣網(wǎng)絡(luò)科技
?山東掌趣網(wǎng)絡(luò)科技






