一阅虫、Hbase的架構(gòu)
架構(gòu)角色
-
Region Server
Region Server 為 Region 的管理者,其實現(xiàn)類為 HRegionServer募判,主要作用如下:- 對于數(shù)據(jù)的操作:get, put, delete;
- 對于 Region 的操作:splitRegion、compactRegion敢辩。
-
Master
Master 是所有 Region Server 的管理者,其實現(xiàn)類為 HMaster弟疆,主要作用如下:- 對于表的操作:create, delete, alter
- 對于 RegionServer的操作:分配 regions到每個RegionServer戚长,監(jiān)控每個 RegionServer的狀態(tài),負(fù)載均衡和故障轉(zhuǎn)移怠苔。
Zookeeper
HBase 通過 Zookeeper 來做 Master 的高可用同廉、RegionServer 的監(jiān)控、元數(shù)據(jù)的入口以及集群配置的維護(hù)等工作柑司。HDFS
HDFS 為 HBase 提供最終的底層數(shù)據(jù)存儲服務(wù)迫肖,同時為 HBase 提供高可用的支持。
數(shù)據(jù)存儲角色
- StoreFile:保存實際數(shù)據(jù)的物理文件攒驰,StoreFile以HFile的形式存儲在HDFS上蟆湖。每個Store會有一個或多個StoreFile(HFile),數(shù)據(jù)在每個StoreFile中都是有序的玻粪。
- MemStore:寫緩存隅津,由于HFile中的數(shù)據(jù)要求是有序的诬垂,所以數(shù)據(jù)是先存儲在MemStore中,排好序后伦仍,等到達(dá)刷寫時機(jī)才會刷寫到HFile结窘,每次刷寫都會形成一個新的HFile。
- WAL:預(yù)寫日志由于數(shù)據(jù)要經(jīng)過MemStore排序后才能刷寫到HFile充蓝,但把數(shù)據(jù)保存在內(nèi)存中會有很高的概率導(dǎo)致數(shù)據(jù)丟失隧枫,為了解決這個問題,數(shù)據(jù)會先寫在一個叫做Write-Ahead logfile的文件中谓苟,然后再寫入MemStore中官脓。所以在系統(tǒng)出現(xiàn)故障的時候,數(shù)據(jù)可以通過這個日志文件重建娜谊。
每個RegionServer 可以服務(wù)多個Region确买,每個RegionServer中有多個Store、1個WAL纱皆,和1個BlockCache湾趾,每個Store對應(yīng)一個列族,包含MemStore 和 StoreFile.
二派草、hbase 寫數(shù)據(jù)流程
- 1搀缠、Client先訪問zookeeper,獲取hbase:meta表位于哪個Region Server近迁。
- 2艺普、訪問對應(yīng)的Region Server,獲取hbase:meta表鉴竭,根據(jù)讀請求的namespace:table/rowkey歧譬,查詢出目標(biāo)數(shù)據(jù)位于哪個Region Server中的哪個Region中。并將該table的region信息以及meta表的位置信息緩存在客戶端的meta cache搏存,方便下次訪問瑰步。
- 3、與目標(biāo)Region Server進(jìn)行通訊璧眠;
- 4缩焦、將數(shù)據(jù)順序?qū)懭耄ㄗ芳樱┑絎AL;
- 5责静、將數(shù)據(jù)寫入對應(yīng)的MemStore袁滥,數(shù)據(jù)會在MemStore進(jìn)行排序;
- 6灾螃、向客戶端發(fā)送ack题翻;
- 7、等待達(dá)到MemStore的刷寫時機(jī)后腰鬼,將數(shù)據(jù)刷寫到HFile嵌赠。
- 8靴拱、在web頁面查看的時候會隨機(jī)的給每一個Region生成一個隨機(jī)編號。
說明:寫入數(shù)據(jù)時猾普,邏輯順序是先寫入到WAL(HLog),再寫入memStore本谜,但實際源碼流程如下:使用事務(wù)回滾機(jī)制來確保WAL和memStore同步寫入初家。
- 1)先獲取鎖(JUC),保證數(shù)據(jù)不會寫入成功前數(shù)據(jù)不會被查詢到
- 2)更新時間戳(數(shù)據(jù)中沒定義時間戳則使用系統(tǒng)時間)乌助,集群中個HRegionServer的系統(tǒng)時間誤差不能超過配置時間溜在,否則集群啟動不成功
- 3)內(nèi)存中構(gòu)建WAL
- 4)將構(gòu)建的WAL追加到最后寫入的WAL,此時不會將WAL同步到HDFS中的HLog中
- 5)將數(shù)據(jù)寫入到memStore
- 6)釋放鎖
- 7)同步WAL到HLog他托,如果同步失敗掖肋,會回滾memStore(通過doRollBackMemstore=false控制)
MemStore刷寫(flush)
自動觸發(fā)機(jī)制:HBase 2.0之前參數(shù)
第一種觸發(fā)條件:(Region級別Flush)
- 當(dāng)某個 memstroe 的大小達(dá)到了 hbase.hregion.memstore.flush.size(默認(rèn)值 128M),其所在 region 的所有 memstore 都會刷寫赏参。
- 如果寫入速度太快超過了刷寫速度志笼,當(dāng) memstore 的大小達(dá)到了 hbase.hregion.memstore.flush.size * hbase.hregion.memstore.block.multiplier(默認(rèn)值 4)大小時,會觸發(fā)所有memstore 刷寫并阻塞 Region 所有的寫請求把篓,此時寫數(shù)據(jù)會出現(xiàn) RegionTooBusyException 異常纫溃。
<!-- 單個region里memstore的緩存大小,超過那么整個HRegion就會flush,默認(rèn)128M -->
<property>
<name>hbase.hregion.memstore.flush.size</name>
<value>134217728</value>
<description>
Memstore will be flushed to disk if size of the memstore
exceeds this number of bytes. Value is checked by a thread that runs
every hbase.server.thread.wakefrequency.
</description>
</property>
<!-- 當(dāng)一個HRegion上的memstore的大小滿足hbase.hregion.memstore.block.multiplier *
hbase.hregion.memstore.flush.size, 這個HRegion會執(zhí)行flush操作并阻塞對該HRegion的寫入 -->
<property>
<name>hbase.hregion.memstore.block.multiplier</name>
<value>4</value>
<description>
Block updates if memstore has hbase.hregion.memstore.block.multiplier
times hbase.hregion.memstore.flush.size bytes. Useful preventing
runaway memstore during spikes in update traffic. Without an
upper-bound, memstore fills such that when it flushes the
resultant flush files take a long time to compact or split, or
worse, we OOME.
</description>
</property>
第二種觸發(fā)條件:(RegionServer級別Flush)
- 當(dāng) regionServer 中 memstore 的總大小達(dá)到 java_heapsize(堆內(nèi)存)* hbase.regionserver.global.memstore.size(默認(rèn)值 0.4)* hbase.regionserver.global.memstore.size.lower.limit(默認(rèn)值 0.95)韧掩,region 會按照其所有 memstore 的大小順序(由大到形珊啤)依次進(jìn)行刷寫。直到 regionServer 中所有 memstore 的總大小減小到上述值以下疗锐。
- 當(dāng) region server 中 memstore 的總大小達(dá)到 java_heapsize * hbase.regionserver.global.memstore.size(默認(rèn)值 0.4)時坊谁,會阻止繼續(xù)往所有的 memstore 寫數(shù)據(jù)。
<!-- regionServer的全局memstore的大小滑臊,超過該大小會觸發(fā)flush到磁盤的操作,默認(rèn)是堆大小的40%,而且regionserver級別的
flush會阻塞客戶端讀寫口芍。如果RegionServer的堆內(nèi)存設(shè)置為2G,則memstore總內(nèi)存大小為 2 * 0.4 = 0.8G-->
<property>
<name>hbase.regionserver.global.memstore.size</name>
<value></value>
<description>Maximum size of all memstores in a region server before
new
updates are blocked and flushes are forced. Defaults to 40% of heap (0.4).
Updates are blocked and flushes are forced until size of all
memstores
in a region server hits
hbase.regionserver.global.memstore.size.lower.limit.
The default value in this configuration has been intentionally left
emtpy in order to
honor the old hbase.regionserver.global.memstore.upperLimit property if
present.
</description>
</property>
<!--可以理解為一個安全的設(shè)置简珠,有時候集群的“寫負(fù)載”非常高阶界,寫入量一直超過flush的量,這時聋庵,我們就希望memstore不要超過一定的安全設(shè)置膘融。
在這種情況下,寫操作就要被阻塞一直到memstore恢復(fù)到一個“可管理”的大小, 這個大小就是默認(rèn)值是堆大小 * 0.4 * 0.95祭玉,也就是當(dāng)regionserver級別
的flush操作發(fā)送后,會阻塞客戶端寫,一直阻塞到整個regionserver級別的memstore的大小為 堆大小 * 0.4 *0.95為止 -->
<property>
<name>hbase.regionserver.global.memstore.size.lower.limit</name>
<value></value>
<description>Maximum size of all memstores in a region server before
flushes are forced.
Defaults to 95% of hbase.regionserver.global.memstore.size (0.95).
A 100% value for this value causes the minimum possible flushing to
occur when updates are
blocked due to memstore limiting.
The default value in this configuration has been intentionally left
emtpy in order to
honor the old hbase.regionserver.global.memstore.lowerLimit property if
present.
</description>
</property>
第三種觸發(fā)條件:(RegionServer級別Flush)
- 定期 hbase.regionserver.optionalcacheflushinterval(默認(rèn)3600000即一個小時)進(jìn)行 MemStore 的刷寫氧映,確保 MemStore 不會長時間沒有持久化。為避免所有的 MemStore 在同一時間進(jìn)行 flush 而導(dǎo)致問題脱货,定期的 flush 操作會有一定時間的隨機(jī)延時岛都。
第四種觸發(fā)條件:(Region級別Flush)
- 當(dāng)一個 Region 的更新次數(shù)達(dá)到 hbase.regionserver.flush.per.changes(默認(rèn)30000000即3千萬)時律姨,也會觸發(fā) MemStore 的刷寫。
第五種觸發(fā)條件 - 當(dāng)一個 RegionServer 的 HLog 即WAL文件數(shù)量達(dá)到上限(舊版本可通過參數(shù) hbase.regionserver.maxlogs臼疫,新版不再對外開放 择份,默認(rèn)32)時,也會觸發(fā) MemStore 的刷寫烫堤,HBase 會找到最舊的 HLog 文件對應(yīng)的 Region 進(jìn)行刷寫 荣赶。
#region的memstore的觸發(fā)
#判斷如果某個region中的某個memstore達(dá)到這個閾值,那么觸發(fā)flush鸽斟,flush這個region的所有memstore
hbase.hregion.memstore.flush.size=128M
#region的觸發(fā)級別:如果沒有memstore達(dá)到128拔创,但是所有memstore的大小加在一起大于等于128*4
#觸發(fā)整個region的flush
hbase.hregion.memstore.block.multiplier=4
#regionserver的觸發(fā)級別:所有region所占用的memstore達(dá)到閾值,就會觸發(fā)整個regionserver中memstore的溢寫
#從memstore占用最多的Regin開始flush
hbase.regionserver.global.memstore.size=0.4 --RegionServer中Memstore的總大小
#低于水位后停止
hbase.regionserver.global.memstore.size.upper.limit=0.99
hbase.regionserver.global.memstore.size.lower.limit = 0.4*0.95 =0.38
自動觸發(fā)機(jī)制:HBase 2.0之后
#設(shè)置了一個flush的最小閾值
#memstore的判斷發(fā)生了改變:max("hbase.hregion.memstore.flush.size / column_family_number",hbase.hregion.percolumnfamilyflush.size.lower.bound.min)
#如果memstore高于上面這個結(jié)果富蓄,就會被flush剩燥,如果低于這個值,就不flush立倍,如果整個region所有的memstore都低于灭红,全部flush
#水位線 = max(128 / 列族個數(shù),16),列族一般給3個 ~ 42M
#如果memstore的空間大于42,就flush,如果小于就不flush口注;如果都小于比伏,全部flush
舉例:3個列族,3個memstore, 90/30/30 90會被Flush
舉例:3個列族疆导,3個memstore, 30/30/30 全部flush
hbase.hregion.percolumnfamilyflush.size.lower.bound.min=16M
# 2.x中多了一種機(jī)制:In-Memory-compact,如果開啟了【不為none】赁项,會在內(nèi)存中對需要flush的數(shù)據(jù)進(jìn)行合并
#合并后再進(jìn)行flush,將多個小文件在內(nèi)存中合并后再flush
hbase.hregion.compacting.memstore.type=none|basic|eager|adaptive
關(guān)于相關(guān)參數(shù)的說明和調(diào)整建議:
hbase.hregion.memstore.flush.size
默認(rèn)值 128M澈段,單個 MemStore 大小超過該閾值就會觸發(fā) Flush悠菜。如果當(dāng)前集群 Flush 比較頻繁,并且內(nèi)存資源比較充裕败富,建議適當(dāng)調(diào)整為 256M悔醋。調(diào)大的副作用可能是造成宕機(jī)時需要分裂的 HLog 數(shù)量變多,從而延長故障恢復(fù)時間兽叮。hbase.hregion.memstore.block.multiplier
默認(rèn)值 4芬骄,Region 中所有 MemStore 超過單個 MemStore 大小的倍數(shù)達(dá)到該參數(shù)值時,就會阻塞寫請求并強(qiáng)制 Flush鹦聪。一般不建議調(diào)整账阻,但對于寫入過快且內(nèi)存充裕的場景,為避免寫阻塞泽本,可以適當(dāng)調(diào)整到5~8淘太。hbase.regionserver.global.memstore.size
默認(rèn)值 0.4,RegionServer 中所有 MemStore 大小總和最多占 RegionServer 堆內(nèi)存的 40%。這是寫緩存的總比例蒲牧,可以根據(jù)實際場景適當(dāng)調(diào)整撇贺,且要與 HBase 讀緩存參數(shù) hfile.block.cache.size(默認(rèn)也是0.4)配合調(diào)整。舊版本參數(shù)名稱為 hbase.regionserver.global.memstore.upperLimit冰抢。hbase.regionserver.global.memstore.size.lower.limit
默認(rèn)值 0.95松嘶,表示 RegionServer 中所有 MemStore 大小的低水位是 hbase.regionserver.global.memstore.size 的 95%,超過該比例就會強(qiáng)制 Flush挎扰。一般不建議調(diào)整喘蟆。舊版本參數(shù)名稱為 hbase.regionserver.global.memstore.lowerLimit。hbase.regionserver.optionalcacheflushinterval
默認(rèn)值 3600000(即 1 小時)鼓鲁,HBase 定期 Flush 所有 MemStore 的時間間隔。一般建議調(diào)大港谊,比如 10 小時骇吭,因為很多場景下 1 小時 Flush 一次會產(chǎn)生很多小文件,一方面導(dǎo)致 Flush 比較頻繁歧寺,另一方面導(dǎo)致小文件很多燥狰,影響隨機(jī)讀性能,因此建議設(shè)置較大值斜筐。此外還有一點(diǎn)值得說一下
官方建議使用一個列族龙致,因為一個列族就對應(yīng)磁盤中的一個文件,如果使用多個列族顷链,數(shù)據(jù)不均勻的情況下目代,在全局Flush時會產(chǎn)生較多的小文件。
如: 列族 CF1 CF2 CF3
100M 1K 5K
全局Flush時嗤练,對于CF2和CF3會生成2個小文件榛了。但是也可以使用多個列族,盡量保證數(shù)據(jù)均勻就好煞抬。
三霜大、hbase 讀數(shù)據(jù)流程
細(xì)節(jié)
- 1、Client先訪問zookeeper革答,獲取hbase:meta表位于哪個Region Server战坤。
- 2、訪問對應(yīng)的Region Server残拐,獲取hbase:meta表途茫,根據(jù)讀請求的namespace:table/rowkey,查詢出目標(biāo)數(shù)據(jù)位于哪個Region Server中的哪個Region中溪食。并將該table的region信息以及meta表的位置信息緩存在客戶端的meta cache慈省,方便下次訪問。
- 3、與目標(biāo)Region Server進(jìn)行通訊边败;
- 4袱衷、分別在Block Cache(讀緩存),MemStore和Store File(HFile)中查詢目標(biāo)數(shù)據(jù)笑窜,并將查到的所有數(shù)據(jù)進(jìn)行合并致燥。此處所有數(shù)據(jù)是指同一條數(shù)據(jù)的不同版本(time stamp)或者不同的類型(Put/Delete)。
- 5排截、將從文件中查詢到的數(shù)據(jù)塊(Block嫌蚤,HFile數(shù)據(jù)存儲單元,默認(rèn)大小為64KB)緩存到Block Cache断傲。
- 6脱吱、將合并后的最終結(jié)果返回給客戶端。
Block Cache
HBase 在實現(xiàn)中提供了兩種緩存結(jié)構(gòu) MemStore(寫緩存) 和 BlockCache(讀緩存)认罩。寫緩存前面說過不再重復(fù)箱蝠。
- 1、HBase 會將一次文件查找的 Block塊 緩存到 Cache中垦垂,以便后續(xù)同一請求或者鄰近數(shù)據(jù)查找請求宦搬,可以直接從內(nèi)存中獲取,避免昂貴的IO操作劫拗。
- 2间校、BlockCache是Region Server級別的,
- 3页慷、一個Region Server只有一個Block Cache憔足,在 Region Server 啟動的時候完成 Block Cache 的初始化工作。
- 4酒繁、HBase對Block Cache的管理分為如下三種四瘫。
- LRUBlockCache 是最初的實現(xiàn)方案,也是默認(rèn)的實現(xiàn)方案欲逃,將所有數(shù)據(jù)都放入JVM Heap中找蜜,交給JVM進(jìn)行管理。
- SlabCache 實現(xiàn)的是堆外內(nèi)存存儲稳析,不再由JVM管理數(shù)據(jù)內(nèi)存洗做。一般跟第一個組合使用,單它沒有改善 GC 弊端彰居,引入了堆外內(nèi)存利用率低诚纸。
- BucketCache 緩存淘汰不再由 JVM 管理 降低了Full GC 發(fā)生的頻率。
重點(diǎn)
讀數(shù)據(jù)時不要理解為先從 MemStore 中讀取陈惰,讀不到再讀 BlockCache 中畦徘,還讀不到再從HFile中讀取,然后將數(shù)據(jù)寫入到 BlockCache 中。因為如果人為設(shè)置導(dǎo)致磁盤數(shù)據(jù)new井辆,內(nèi)存數(shù)據(jù)old关筒。你讀取的時候會出錯的!
結(jié)論
HBase 把磁盤跟內(nèi)存數(shù)據(jù)一起讀杯缺,然后把磁盤數(shù)據(jù)放到 BlockCache中蒸播,BlockCache 是磁盤數(shù)據(jù)的緩存。HBase 是個讀比寫慢的工具萍肆。
四袍榆、StoreFile合并(Compaction)
由于memstore每次刷寫都會生成一個新的HFile,且同一個字段的不同版本(timestamp)和不同類型(Put/Delete)有可能會分布在不同的 HFile 中塘揣,因此查詢時需要遍歷所有的 HFile包雀。
為了減少 HFile 的個數(shù),以及清理掉過期和刪除的數(shù)據(jù)亲铡,會進(jìn)行 StoreFile Compaction才写。Compaction 分為兩種,分別是 Minor Compaction 和 Major Compaction奴愉。
# 2.0版本之前,只有StoreFile文件的合并
磁盤中合并:minor compaction铁孵、major compaction
# 2.0版本開始锭硼,內(nèi)存中的數(shù)據(jù)也可以先合并后Flush
內(nèi)存中合并:In-memory compaction
磁盤中合并:minor compaction、major compaction
Minor Compaction :輕量級
- Minor Compaction 是指選取一些小的蜕劝、相鄰的 HFile 將他們合并成一個更大的 HFile檀头。默認(rèn)情況下,Minor Compaction 會刪除所合并 HFile 中的 TTL 過期數(shù)據(jù)岖沛,但是不會刪除手動刪除(也就是 Delete 標(biāo)記作用的數(shù)據(jù))不會被刪除暑始。
- 屬性: hbase.hstore.compaction.min=3
minor compact文件選擇標(biāo)準(zhǔn)由以下幾個參數(shù)共同決定
<!--待合并文件數(shù)據(jù)必須大于等于下面這個值-->
<property>
<name>hbase.hstore.compaction.min</name>
<value>3</value>
</property>
<!--待合并文件數(shù)據(jù)必須小于等于下面這個值-->
<property>
<name>hbase.hstore.compaction.max</name>
<value>10</value>
</property>
<!--默認(rèn)值為128m,
表示文件大小小于該值的store file 一定會加入到minor compaction的store file中
-->
<property>
<name>hbase.hstore.compaction.min.size</name>
<value>134217728</value>
</property>
<!--默認(rèn)值為LONG.MAX_VALUE,
表示文件大小大于該值的store file 一定會被minor compaction排除-->
<property>
<name>hbase.hstore.compaction.max.size</name>
<value>9223372036854775807</value>
</property>
Major Compaction :重量級合并
- Major Compaction 是指將一個 Store 中所有的 HFile 合并成一個 HFile婴削,這個過程會清理三類沒有意義的數(shù)據(jù):被刪除的數(shù)據(jù)(打了 Delete 標(biāo)記的數(shù)據(jù))廊镜、TTL 過期數(shù)據(jù)、版本號超過設(shè)定版本號的數(shù)據(jù)唉俗。另外,一般情況下,Major Compaction 時間會持續(xù)比較長匿乃,整個過程會消耗大量系統(tǒng)資源牲迫,對上層業(yè)務(wù)有比較大的影響。因此衡楞,生產(chǎn)環(huán)境下通常關(guān)閉自動觸發(fā) Major Compaction 功能吱雏,改為手動在業(yè)務(wù)低峰期觸發(fā)。
- 參數(shù)配置: hbase.hregion.majorcompaction=7天
In-memory compaction
- 原理:將當(dāng)前寫入的數(shù)據(jù)劃分segment【數(shù)據(jù)段】
- 當(dāng)數(shù)據(jù)不斷寫入MemStore,劃分不同的segment歧杏,最終變成storefile文件
- 如果開啟內(nèi)存合并镰惦,先將第一個segment放入一個隊列中,與其他的segment進(jìn)行合并
- 合并以后的結(jié)果再進(jìn)行flush
- 內(nèi)存中合并的方式:hbase.hregion.compacting.memstore.type=None|basic|eager|adaptive
- Basic compaction策略不清理多余的數(shù)據(jù)版本得滤,無需對cell的內(nèi)存進(jìn)行考核
- eager compaction會過濾重復(fù)的數(shù)據(jù)陨献,清理多余的版本,這會帶來額外的開銷
- adaptive compaction根據(jù)數(shù)據(jù)的重復(fù)情況來決定是否使用eager策略
禁用自動合并懂更,使用手動處理:
Compact all regions in a table:
hbase> major_compact 't1'
hbase> major_compact 'ns1:t1'
Compact an entire region:
hbase> major_compact 'r1'
Compact a single column family within a region:
hbase> major_compact 'r1', 'c1'
Compaction 觸發(fā)時機(jī):
概括的說眨业,HBase 會在三種情況下檢查是否要觸發(fā) Compaction,分別是 MemStore Flush沮协、后臺線程周期性檢查龄捡、手動觸發(fā)。
- MemStore Flush:可以說 Compaction 的根源就在于Flush慷暂,MemStore 達(dá)到一定閾值或觸發(fā)條件就會執(zhí)行 Flush 操作聘殖,在磁盤上生成 HFile 文件,正是因為 HFile 文件越來越多才需要 Compact行瑞。HBase 每次Flush 之后奸腺,都會判斷是否要進(jìn)行 Compaction,一旦滿足 Minor Compaction 或 Major Compaction 的條件便會觸發(fā)執(zhí)行血久。
- 后臺線程周期性檢查:后臺線程 CompactionChecker 會定期檢查是否需要執(zhí)行 Compaction突照,檢查周期為 hbase.server.thread.wakefrequency * hbase.server.compactchecker.interval.multiplier,這里主要考慮的是一段時間內(nèi)沒有寫入仍然需要做 Compact 檢查氧吐。其中參數(shù) hbase.server.thread.wakefrequency 默認(rèn)值 10000 即 10s讹蘑,是 HBase 服務(wù)端線程喚醒時間間隔,用于 LogRoller筑舅、MemStoreFlusher 等的周期性檢查座慰;參數(shù) hbase.server.compactchecker.interval.multiplier 默認(rèn)值1000,是 Compaction 操作周期性檢查乘數(shù)因子翠拣,10 * 1000 s 時間上約等于2hrs, 46mins, 40sec版仔。
- 手動觸發(fā):通過 HBase Shell、Master UI 界面或 HBase API 等任一種方式執(zhí)行 compact误墓、major_compact等命令邦尊,會立即觸發(fā) Compaction。
Compaction 核心參數(shù):
hbase.hstore.compaction.min
- 默認(rèn)值 3优烧,一個 Store 中 HFile 文件數(shù)量超過該閾值就會觸發(fā)一次 Compaction(Minor Compaction)蝉揍,這里稱該參數(shù)為 minFilesToCompact。一般不建議調(diào)小畦娄,重寫場景下可以調(diào)大該參數(shù)又沾,比如 5~10 之間弊仪,
- 注意相應(yīng)調(diào)整下一個參數(shù)。老版本參數(shù)名稱為 hbase.hstore.compactionthreshold杖刷。
hbase.hstore.compaction.max
- 默認(rèn)值 10励饵,一次 Minor Compaction 最多合并的 HFile 文件數(shù)量,這里稱該參數(shù)為 maxFilesToCompact滑燃。這個參數(shù)也控制著一次壓縮的耗時役听。一般不建議調(diào)整,但如果上一個參數(shù)調(diào)整了表窘,該參數(shù)也應(yīng)該相應(yīng)調(diào)整典予,
- 一般設(shè)為 minFilesToCompact 的 2~3 倍。
hbase.regionserver.thread.compaction.throttle
- HBase RegionServer 內(nèi)部設(shè)計了兩個線程池 large compactions 與 small compactions乐严,用來分離處理 Compaction 操作瘤袖,該參數(shù)就是控制一個 Compaction 交由哪一個線程池處理,
- 默認(rèn)值是 2 * maxFilesToCompact * hbase.hregion.memstore.flush.size(默認(rèn)210128M=2560M即2.5G)昂验,建議不調(diào)整或稍微調(diào)大捂敌。
hbase.regionserver.thread.compaction.large/small
- 默認(rèn)值 1,表示 large compactions 與 small compactions 線程池的大小既琴。一般建議調(diào)整到 2~5占婉,不建議再調(diào)太大比如10,否則可能會消費(fèi)過多的服務(wù)端資源造成不良影響甫恩。
hbase.hstore.blockingStoreFiles
<!-- 每個store阻塞更新請求的閥值,表示如果當(dāng)前hstore中文件數(shù)大于該值逆济,系統(tǒng)將會強(qiáng)制執(zhí)行compaction操作進(jìn)行文件合并,
合并的過程會阻塞整個hstore的寫入,這樣有個好處是避免compaction操作趕不上Hfile文件的生成速率 -->
<property>
<name>hbase.hstore.blockingStoreFiles</name>
<value>10</value>
<description>
If more than this number of StoreFiles in any one Store
(one StoreFile is written per flush of MemStore) then updates are
blocked for this HRegion until a compaction is completed, or
until hbase.hstore.blockingWaitTime has been exceeded.
</description>
</property>
默認(rèn)值 10填物,表示一個 Store 中 HFile 文件數(shù)量達(dá)到該值就會阻塞寫入纹腌,等待 Compaction 的完成霎终。一般建議調(diào)大點(diǎn)滞磺,比如設(shè)置為 100,避免出現(xiàn)阻塞更新的情況莱褒,阻塞日志如下:
too many store files; delaying flush up to 90000ms
生產(chǎn)環(huán)境建議認(rèn)真根據(jù)實際業(yè)務(wù)量做好集群規(guī)模評估击困,如果小集群遇到了持續(xù)寫入過快的場景,合理擴(kuò)展集群也非常重要广凸。
五阅茶、數(shù)據(jù)切分(Split)
默認(rèn)情況下,每個 Table 起初只有一個 Region谅海,隨著數(shù)據(jù)的不斷寫入脸哀,Region 會自動進(jìn)行拆分。剛拆分時扭吁,兩個子 Region 都位于當(dāng)前的 Region Server撞蜂,但處于負(fù)載均衡的考慮盲镶,HMaster 有可能會將某個 Region 轉(zhuǎn)移給其他的 Region Server。
Region Split 時機(jī)
- 當(dāng)1個region中的某個Store下所有StoreFile的總大小超過hbase.hregion.max.filesize蝌诡,該 Region 就會進(jìn)行拆分(0.94 版本之前)溉贿。
- 當(dāng) 1 個 region 中 的 某 個 Store 下所有 StoreFile 的 總 大 小 超 過 Min(R^2 * "hbase.hregion.memstore.flush.size",hbase.hregion.max.filesize"),該 Region 就會進(jìn)行拆分浦旱,其中 R 為當(dāng)前 Region Server 中屬于該 Table 的個數(shù)(0.94 版本之后)宇色。
- 2.*之后:判斷region個數(shù)是否為1,如果為1颁湖,就按照256分宣蠕,如果不為1,就按照10GB來分
數(shù)據(jù)切分會造成數(shù)據(jù)傾斜(region 大小分布不均)爷狈,帶來熱點(diǎn)數(shù)據(jù)問題植影。所以建表時進(jìn)行預(yù)分區(qū)來盡量避免這種問題。
關(guān)閉自動分裂涎永,手動執(zhí)行
split 'tableName'
split 'namespace:tableName'
split 'regionName' # format: 'tableName,startKey,id'
split 'tableName', 'splitKey'
split 'regionName', 'splitKey'
六思币、被刪除數(shù)據(jù)(打了 Delete 標(biāo)記的數(shù)據(jù))的清除時機(jī)
被刪除數(shù)據(jù)會在兩種操作中被清除:
- Flush:內(nèi)存數(shù)據(jù)刷寫到磁盤(MemStore ——> StoreFile),這時候只會清除當(dāng)前內(nèi)存(memStore)中被 Delete 標(biāo)記覆蓋的數(shù)據(jù)羡微,不會清除 Delete 標(biāo)記谷饿。
- major compact:大合并會刪除三類無效數(shù)據(jù):被刪除的數(shù)據(jù)(打了 Delete 標(biāo)記的數(shù)據(jù))、TTL 過期數(shù)據(jù)妈倔、版本號超過設(shè)定版本號的數(shù)據(jù)博投。
為什么 Flush 不清除 Delete 標(biāo)記?
因為 Flush 只能清除 memStore 中的數(shù)據(jù)盯蝴,還要留著 Delete 標(biāo)記供 major compact 合并時去清除其他 StoreFile 中的數(shù)據(jù)毅哗。
七、Hbase優(yōu)化
RowKey設(shè)計
唯一原則:Rowkey必須具有唯一性捧挺,不能重復(fù)虑绵,一個Rowkey唯一標(biāo)識一條數(shù)據(jù)
業(yè)務(wù)原則:Rowkey的設(shè)計必須貼合業(yè)務(wù)的需求,一般選擇最常用的查詢條件作為rowkey的前綴
組合原則:將更多的經(jīng)常作為的查詢條件的列放入Rowkey中闽烙,可以滿足更多的條件查詢可以走索引查詢
-
散列原則:為了避免出現(xiàn)熱點(diǎn)問題翅睛,需要將數(shù)據(jù)的rowkey生成規(guī)則構(gòu)建散列的rowkey
- 方案一:更換不是連續(xù)的字段作為前綴,例如用戶id
- 方案二:反轉(zhuǎn)黑竞,一般用于時間作為前綴捕发,查詢時候必須將數(shù)據(jù)反轉(zhuǎn)再查詢
- 方案三:加鹽(Salt),本質(zhì)對數(shù)據(jù)進(jìn)行編碼很魂,生成數(shù)字加字母組合的結(jié)果
-
長度原則:在滿足業(yè)務(wù)需求情況下扎酷,rowkey越短越好,一般建議Rowkey的長度小于100字節(jié)
- 原因:rowkey越長遏匆,比較性能越差法挨,rowkey在底層的存儲是冗余的
- 如果rowkey超過了100字節(jié)骤铃,將一個長的rowkey,編碼為8位坷剧,16位惰爬,32位
內(nèi)存優(yōu)化
- 讀多寫少,降低MEMStore比例
- 讀少寫多惫企,降低BlockCache比例
壓縮機(jī)制
- 與hadoop支持的壓縮算法相關(guān)
- create ‘t1_snappy’, {NAME=>‘info’, COMPRESSION => ‘SNAPPY’}
布隆過濾
-
ROW:行級布隆過濾
- 生成StoreFile文件時撕瞧,會將這個文件中有哪些Rowkey的數(shù)據(jù)記錄在文件的頭部
- 當(dāng)讀取StoreFile文件時,會從文件頭部獲取這個StoreFile中的所有rowkey狞尔,自動判斷是否包含需要的rowkey丛版,如果包含就讀取這個文件,如果不包含就不讀這個文件
-
ROWCOL:行列級布隆過濾
- 生成StoreFile文件時偏序,會將這個文件中有哪些Rowkey的以及對應(yīng)的列族和列的信息數(shù)據(jù)記錄在文件的頭部
- 當(dāng)讀取StoreFile文件時页畦,會從文件頭部或者這個StoreFile中的所有rowkey以及列的信息,自動判斷是否包含需要的rowkey以及列研儒,如果包含就讀取這個文件豫缨,如果不包含就不讀這個文件
環(huán)境優(yōu)化
-
系統(tǒng)環(huán)境
- 開啟文件系統(tǒng)的預(yù)讀緩存可以提高讀取速度
- 最大限度使用物理內(nèi)存
- 調(diào)整文件及進(jìn)程句柄數(shù)
-
HDFS
- 保證RPC調(diào)用會有較多的線程數(shù)
- 文件塊大小的調(diào)整
- 文件句柄數(shù)
- 超時時間
- 避免DN錯誤宕機(jī)
-
zookeeper
- 優(yōu)化Zookeeper會話超時時間
-
hbase
- 設(shè)置RPC監(jiān)聽數(shù)量
- 優(yōu)化hbase客戶端緩存
- 指定scan.next掃描HBase所獲取的行數(shù)
參考:
https://www.cnblogs.com/wdh01/p/16283244.html
https://blog.csdn.net/qq_33208851/article/details/105223419
https://blog.csdn.net/weixin_44133605/article/details/124635627
https://www.cnblogs.com/baran/p/15629009.html
https://www.cnblogs.com/sx66/p/13425465.html
https://blog.csdn.net/zfw_666666/article/details/126627977
https://blog.csdn.net/llAl_lAll/article/details/122260638
https://blog.csdn.net/weixin_48370579/article/details/125802173