概述
HBase是基于Bigtable論文的面向列的分布式存儲(chǔ)系統(tǒng),其存儲(chǔ)設(shè)計(jì)是基于Memtable/SSTable的。 其它如 Cassandra 都是采用的該設(shè)計(jì)。
整個(gè)存儲(chǔ)分為兩部分,一部分為內(nèi)存中的 MemStore(Memtable) ,另外一部分為磁盤(pán) ( 這里是 HDFS) 上的 HFile(SSTable) 。下面分別講述兩種類型的存儲(chǔ)分別的實(shí)現(xiàn):
MemStore 中最重要的變量是:
volatile KeyValueSkipListSet kvset;
這里的 KeyValueSkipListSet 里面實(shí)際是這樣的:
private final ConcurrentNavigableMap<KeyValue, KeyValue> delegatee;
換句話說(shuō),其實(shí)就是一個(gè)放內(nèi)存的 Map 存放著 kv 。
?
HFile 是 HBase 實(shí)際的文件存儲(chǔ)格式,它是基于 TFile 的文件格式,替換了早期的 MapFile ,改進(jìn)了性能。
然后 HBase 會(huì)進(jìn)行控制,當(dāng) MemStore 寫(xiě)滿了以后進(jìn)行刷磁盤(pán)操作。
而HLog是HBase的日志格式實(shí)現(xiàn),主要是在寫(xiě)入的時(shí)候進(jìn)行write-ahead-log,主要為recovery而做。
HFile
HFile 是 HBase 中實(shí)際存數(shù)據(jù)的文件,為 HBase 提供高效快速的數(shù)據(jù)訪問(wèn)。它是基于 Hadoop 的 TFile ,模仿 Google Bigtable 架構(gòu)中的 SSTable 格式。之前的 Hadoop 的 MapFiles 已經(jīng)被證明性能不能到達(dá)我們的期望。文件格式如下:
?
?
文件是變長(zhǎng)的,唯一固定的塊是 File info 和 Trailer ,如圖所示, Trailer 有指向其它塊的指針,這些指針也寫(xiě)在了文件里, Index 塊記錄了 data 和 meta 塊的偏移量, data 和 meta 塊都是可選的。
塊的大小是由表創(chuàng)建時(shí)的 HColumnDescriptor 指定的,如下是 master web interface 上看到的一個(gè)例子:
{NAME => 'docs', FAMILIES => [{NAME => 'cache', COMPRESSION => 'NONE', VERSIONS => '3', TTL => '2147483647', BLOCKSIZE => '65536', IN_MEMORY => 'false', BLOCKCACHE => 'false'}, {NAME => 'contents', COMPRESSION => 'NONE', VERSIONS => '3', TTL => '2147483647', BLOCKSIZE => '65536', IN_MEMORY => 'false', BLOCKCACHE => 'false'}, ...
默認(rèn)的大小是 64KB ,下面是一段關(guān)于 HFile 的解釋:
“最小的塊大小。我們建議通常將其設(shè)置為 8KB 到 1MB 之間,如果經(jīng)常進(jìn)行基于 primary key 的順序訪問(wèn),可以設(shè)置更大的塊大小,但是這樣會(huì)帶來(lái)低效的隨機(jī)訪問(wèn)效率(更多的數(shù)據(jù)需要被解壓縮)。更小的塊大小將帶來(lái)更好的隨機(jī)訪問(wèn)效率,但是會(huì)耗費(fèi)更多的內(nèi)存去維持索引,并且在創(chuàng)建的時(shí)候會(huì)比較慢,因?yàn)樾枰? flush 壓縮流,這將導(dǎo)致一個(gè) FS I/O flush 。由于內(nèi)部的壓縮 codec 的緩存,最小的塊大小可以為 20-30KB ”
?
?
?
上圖是 HFile 中每個(gè) KeyValue 的格式,和普通的 key-value 沒(méi)有太大的區(qū)別。
?
HLog
源碼中的實(shí)現(xiàn)類是 HLog 。每個(gè) HRegionServer 會(huì)對(duì)應(yīng)一個(gè) HLog , HRegion 在初始化的時(shí)候 HRegionServer 會(huì)將該 HLog 的實(shí)例作為構(gòu)造函數(shù)傳入其中。 HLog 的核心函數(shù)是其 append() 函數(shù)。
在 HLog 中,會(huì)維持一個(gè) Sequence Number ,是一個(gè) AtomicLong 型,當(dāng)一個(gè) Region 啟動(dòng)的時(shí)候會(huì)從 HFile 的 Meta field 里面讀出當(dāng)前的 Sequence Number 。
如圖所示,由于 HLog 是 Region 之間共享的,因此, log 的順序是不定的,這一點(diǎn)后面會(huì)提到。當(dāng)一個(gè) HRegionServer 崩潰掉后, HMaster 會(huì)讓 HRegionServer 重啟的時(shí)候根據(jù)日志進(jìn)行恢復(fù)。
當(dāng)前的 WAL 使用的是 Hadoop 下的 SequenceFile 格式,其 key 是 HLogKey 實(shí)例,它包括以下內(nèi)容:
private byte [] encodedRegionName; private byte [] tablename; private long logSeqNum; // Time at which this edit was written. private long writeTime; private byte clusterId;
?
由于操作系統(tǒng)處理批量的數(shù)據(jù)要塊過(guò)單個(gè)單個(gè)的處理,因此,需要進(jìn)行 flush 日志。 LogFlusher 實(shí)現(xiàn)了該功能,它調(diào)用了 HLog.optionalSync() ,它將檢查是否到了 hbase.regionserver.optionallogflushinterval ,默認(rèn)是 10 秒。
???????? 日志的大小會(huì)有一個(gè)限制,這是用 hbase.regionserver.logroll.period 參數(shù)控制的,默認(rèn)是 1 個(gè)小時(shí)。到點(diǎn)以后 LogRoller 會(huì)觸發(fā)操作,檢查當(dāng)前的 Sequence Number ,看小于它的所有日志是否完整。
?
參考文獻(xiàn)
http://www.larsgeorge.com/
主要參考自larsgeorge的hbase系列文章
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
