HBase:分布式列式NoSQL数据库
傳統的ACID數據庫,可擴展性上受到了巨大的挑戰。而HBase這類系統,兼具可擴展性的同時,也提出了類SQL的接口。
HBase架構組成
HBase采用Master/Slave架構搭建集群,它隸屬于Hadoop生態系統,由一下類型節點組成:HMaster節點、HRegionServer節點、ZooKeeper集群,而在底層,它將數據存儲于HDFS中,因而涉及到HDFS的NameNode、DataNode等,總體結構如下:
HBase Client通過RPC方式和HMaster、HRegionServer通信
HMaster節點
HRegionServer節點
一個HRegionServer可以存放1000個HRegion(出自BigTable);HBase使用RowKey將表水平切割成多個HRegion,從HMaster的角度,每個HRegion都紀錄了它的StartKey和EndKey(第一個HRegion的StartKey為空,最后一個HRegion的EndKey為空),由于RowKey是排序的,因而Client可以通過HMaster快速的定位每個RowKey在哪個HRegion中。
底層Table數據存儲于HDFS中,而HRegion所處理的數據盡量和數據所在的DataNode在一起,實現數據的本地化;數據本地化并不是總能實現,比如在HRegion移動(如因Split)時,需要等下一次Compact才能繼續回到本地化。
ZooKeeper集群是協調系統
HBase的第一次讀寫
0.96以前的版本(參考BigTable)
HBase有兩個特殊的表,ROOT表(唯一)和META表。其中,ROOT表的位置保存在ZooKeeper中,它存儲了META表的RegionInfo信息。而META表 則存儲了用戶Table的RegionInfo信息,它可以被切分成多個HRegion。
- 所以需要3次讀取才能獲取目標HRegion的位置,然后第4次請求才能獲取真正的數據。所以,一般客戶端有ROOT表位置喝內容的緩存。
我們來看看為什么BigTable要選擇三級索引結構,BigTable論文里面提到,一般每個HRegion大小為128M,每行META數據1KB。所以,三級索引可以索引2^34個HRegion,可以索引很大很大的數據了。但是如果只有二級索引,我們就只能索引16TB,在大數據情況下這是完全不夠。
0.96后的版本
顯然只構建兩級索引可以大大加快查詢速度,為了兩級索引的情況下也能支持大數據量。我們可以加大每個HRegion的大小,如果每個HRegion大小為2GB,兩級索引就可以支持4PB。同樣,客戶端會緩存查詢后的HRegion位置信息。
hbase:meta表
meta表存儲了所有用戶HRegion的位置信息,它的RowKey是:tableName,regionStartKey,regionId,replicaId等,它只有info列族,這個列族包含三個列,他們分別是:
- regioninfo列是RegionInfo的proto格式:regionId,tableName,startKey,endKey,offline,split,replicaId;
- server格式:HRegionServer對應的server:port;
- serverstartcode格式是HRegionServer的啟動時間戳。
meta表(root表)結構
HRegionServer詳解
HRegionServer一般和DataNode在同一臺機器上運行,實現數據的本地性。HRegionServer包含多個HRegion,由WAL(HLog)、BlockCache、MemStore、HFile組成。
WAL(Write Ahead Log, HLog)
所有寫操作都會先保證將數據寫入這個Log文件(每個HRegionServer只有一個)后,才會真正更新MemStore,最后寫入HFile中。這樣即使HRegionServer宕機,我們依然可以從HLog中恢復數據。
由于HDFS只允許同一時刻對一個文件只能一個客戶端寫入,所以對HLog只能單線程寫入。這樣很明顯會影響性能,所以再HBase1.0以后的版本,多個WAL并行寫(MultiWAL),該實現采用HDFS的多個管道寫,以單個HRegion為單位。
BlockCache
讀緩存,Hbase中有兩種(BlockCache為HRegionServer內存大小的20%)
HRegion
HRegion是一個表的一部分,表的橫切的一部分
HStore
HRegion由多個Store(HStore)構成,每個HStore對應了一個Table在這個HRegion中的一個Column Family,即每個Column Family就是一個集中的存儲單元,因而最好將具有相近IO特性的Column存儲在一個Column Family,以實現高效讀取(數據局部性原理,可以提高緩存的命中率)。
HStore是HBase中存儲的核心,它實現了讀寫HDFS功能,一個HStore由一個MemStore 和0個或多個HFile組成。
- MemStore:所有數據的寫在完成WAL日志寫后,會 寫入MemStore中,由MemStore根據一定的算法將數據Flush到地層HDFS文件中(HFile),通常每個HRegion中的每個 Column Family有一個自己的MemStore。
- HFile:在HFile中的數據是按RowKey、Column Family、Column排序,對相同的Cell(即這三個值都一樣),則按timestamp倒序排列
MemStore
MemStore是一個In Memory Sorted Buffer,在每個HStore中都有一個MemStore,即它是一個HRegion的一個Column Family對應一個實例。它的排列順序以RowKey、Column Family、Column的順序以及Timestamp的倒序,如下所示:
每一次Put/Delete請求都是先寫入到MemStore中,當MemStore滿后會Flush成一個新的StoreFile(底層實現是HFile),即一個HStore(Column Family)可以有0個或多個StoreFile(HFile)。有以下三種情況可以觸發MemStore的Flush動作,需要注意的是MemStore的最小Flush單元是HRegion而不是單個MemStore。據說這是Column Family有個數限制的其中一個原因,估計是因為太多的Column Family一起Flush會引起性能問題
在MemStore Flush過程中,還會在尾部追加一些meta數據,其中就包括Flush時最大的WAL sequence值,以告訴HBase這個StoreFile寫入的最新數據的序列,那么在Recover時就直到從哪里開始。
HFile格式
HFile是MemStore在HDFS上的實體,所以寫一個HFile是順序寫,速度很快。HFile一共經歷了三個版本
v1
數據存放再Data塊中,Data塊的大小可以用戶指定,大的Data塊適合scan,小的Data塊適合隨機查找。
HFile里面的每個KeyValue對就是一個簡單的byte數組。但是這個byte數組里面包含了很多項,并且有固定的結構。
Block Index:使用記錄每個Data Block最大值的方案,需要將索引一次性讀入內存
v2
解決了V1版本內存占用,特別是Bloom File和Block Index過大。它的解決方案是把Bloom File和Block Index打散放入Data,每次查詢不用加載全部信息。對HFileV2格式具體分析,它是一個多層的類B+樹索引,采用這種設計,可以實現查找不需要讀取整個文件
Data Block中的Cell都是升序排列,每個block都有它自己的Leaf-Index,每個Block的最后一個Key被放入Intermediate-Index中,Root-Index指向Intermediate-Index。Bloom過濾器用于快速定位沒有在DataBlock中的數據
v3
v3和v2沒有太大變化,只是加了一個tag字段
理一理HRegionServer中的結構
- HRegionServer
- WAL(Hlog,一個,HDFS中)
- BlockCache
- HRegion(最多1000個,表的橫切,rowkey不會重疊)
- HStore(列族,HRegion的列切, 多個)
- MemStore(寫完Hlog后,剛生成的數據)
- HFile(多個,具體的數據,排序,HDFS中)
- HStore(列族,HRegion的列切, 多個)
HRegionServer寫流程
HBase讀流程
HBase寫時,相同Cell(RowKey/ColumnFamily/Column相同)并不保證在一起,甚至刪除一個Cell也只是寫入一個新的Cell,它含有Delete標記,而不一定將一個Cell真正刪除了,因而這就引起了一個問題,如何實現讀的問題?
相同的cell可能存在3個不同的位置,Block Cache,MemStore,HFile中。
Compaction
HFile過多,在數據讀取的時候,會產生性能問題。所以一段時間后,HFile會進行合并。HBase中Compaction分為兩種:Minor Compaction和Major Compaction。
- Minor Compaction:是指選取一些小的、相鄰的HFile將他們合并成一個更大的StoreFile,在這個過程中不會處理已經Deleted或Expired的Cell。(BigTable中將memtable的數據flush的一個HFile/SSTable稱為一次Minor Compaction)
- Major Compaction:是指將所有的HFile合并成一個HFile,可以手動觸發或者自動觸發,但是會引起性能問題,一般安排在周末。
HRegion Split
最初,一個Table只有一個HRegion,隨著數據寫入增加,如果一個HRegion到達一定的大小,就需要Split成兩個HRegion,這個大小由hbase.hregion.max.filesize指定,默認為10GB。
當split時(split時停止服務),兩個新的HRegion會在同一個HRegionServer中創建,它們各自包含父HRegion一半的數據,當Split完成后,父HRegion會下線,而新的兩個子HRegion會向HMaster注冊上線,處于負載均衡的考慮,這兩個新的HRegion可能會被HMaster分配到其他的HRegionServer中。
分裂流程
HRegion分裂后負載均衡
出于負載均衡的考慮,HMaster可能會將其中的一個甚至兩個重新分配的其他的HRegionServer中。可能會產生HFile在其他節點上,直到下一次Major Compaction將數據從遠端的節點移動到本地節點。
既然有拆分,但是HRegion也可以合并。HRegion調用closeAndMerge把兩個HRegion合并(需要兩個HRegion停止服務)
HBase中的負載均衡
負載均衡器會平衡系統中每個HRegionServer中HRegion個數。
負載均衡對系統性能影響很大,實際一般關閉,每周開啟一次。
容錯
HRegionServer Recovery
HMaster Recovery
依靠zookeeper進行主備切換
HBase一致性
HBase是強一致性,它表現在:
轉載于:https://www.cnblogs.com/biterror/p/6909923.html
總結
以上是生活随笔為你收集整理的HBase:分布式列式NoSQL数据库的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 静态方法和实例方法(mark)
- 下一篇: C Builder中如何利用消息