1. 程式人生 > >HBase – Memstore Flush和flush shell操作 深度解析

HBase – Memstore Flush和flush shell操作 深度解析

是否 log文件 整理 相關 提升 避免 為什麽 rlimit href

//memstore flush機制 和flush shell命令刷新
//Memstore是HBase框架中非常重要的組成部分之一,是HBase能夠實現高性能隨機讀寫至關重要的一環。深入理解Memstore的工作原理、運行機制以及相關配置,對hbase集群管理、性能調優都有著非常重要的幫助。

寫機制(大約)
1、HBase是基於LSM-Tree模型的,
2、所有的數據更新插入操作都首先寫入Memstore中(同時會順序寫到日誌HLog中),
3、達到指定大小之後再將這些修改操作批量寫入磁盤,生成一個新的HFile文件,這種設計可以極大地提升HBase的寫入性能;
4、HBase為了方便按照RowKey進行檢索,要求HFile中數據都按照RowKey進行排序,

5、Memstore數據在flush為HFile之前會進行一次排序,將數據有序化;

讀機制(大約)
1、根據局部性原理,新寫入的數據會更大概率被讀取,
2、因此HBase在讀取數據的時候首先檢查請求的數據是否在Memstore,
3、寫緩存未命中的話再到讀緩存中查找,讀緩存還未命中才會到HFile文件中查找,最終返回merged的一個結果給用戶。

//可見,Memstore無論是對HBase的寫入性能還是讀取性能都至關重要。其中flush操作又是Memstore最核心的操作。

問題:
接下來重點針對Memstore的flush操作進行深入地解析:
1、首先分析HBase在哪些場景下會觸發flush,
2、然後結合源代碼分析整個flush的操作流程。

3、最後再重點整理總結和flush相關的配置參數,這些參數對於性能調優、問題定位都非常重要。

HBase會在如下幾種情況下觸發flush操作?
//提示:
需要註意的是MemStore的最小flush單元是HRegion而不是單個MemStore。 //這就話可以理解Wie:
當一個region是2個列族的時候,就會有2個memstore 比如如果其中一個menstore=128M了,另一個沒有達到128M 不會flush
只有當region中的2個memstore都達到了128M的時候,才會觸發真正的刷新region級別的flush
可想而知,如果一個HRegion中Memstore過多,每次flush的開銷必然會很大,因此我們也建議在進行表設計的時候盡量減少ColumnFamily的個數。建議列族為1-3個,熱門業務的列族就設計成1個

1、Memstore級別限制:當Region中任意一個MemStore的大小達到了上限(hbase.hregion.memstore.flush.size,默認128MB),會觸發Memstore刷新。
2、Region級別限制:當Region中所有Memstore的大小總和達到了上限(hbase.hregion.memstore.block.multiplier hbase.hregion.memstore.flush.size,默認 2 128M = 256M),會觸發memstore刷新。
3、Region Server級別限制:當一個Region Server中所有Memstore的大小總和達到了上限 (hbase.regionserver.global.memstore.upperLimit * hbase_heapsize,默認 40%的JVM內存使用量),會觸發部分Memstore刷新。Flush順序是按照Memstore由大到小執行,先Flush Memstore最大的Region,再執行次大的,直至總體Memstore內存使用量低於閾值(hbase.regionserver.global.memstore.lowerLimit * hbase_heapsize,默認 38%的JVM內存使用量)。
//影響很大
4、當一個Region Server中HLog數量達到上限(可通過參數hbase.regionserver.maxlogs配置)時,系統會選取最早的一個 HLog對應的一個或多個Region進行flush
5、HBase定期刷新Memstore:默認周期為1小時,確保Memstore不會長時間沒有持久化。為避免所有的MemStore在同一時間都進行flush導致的問題,定期的flush操作有20000左右的隨機延時。
6、手動執行flush:用戶可以通過shell命令 flush ‘tablename’或者flush ‘region name’分別對一個表或者一個Region進行flush。
//6種方式可以觸發 flush的操作,以上參數在cdh中都有

Memstore Flush流程 //具體見博客
為了減少flush過程對讀寫的影響,HBase采用了類似於兩階段提交的方式,將整個flush過程分為三個階段:
1、prepare階段
(1)遍歷當前Region中的所有Memstore,將Memstore中當前數據集kvset做一個快照snapshot,然後再新建一個新的kvset。
(2)後期的所有寫入操作都會寫入新的kvset中,而整個flush階段讀操作會首先分別遍歷kvset和snapshot,如果查找不到再會到HFile中查找。
(3)prepare階段需要加一把updateLock對寫請求阻塞,結束之後會釋放該鎖。
(4)因為此階段沒有任何費時操作,因此持鎖時間很短
2、flush階段
(1)遍歷所有Memstore,將prepare階段生成的snapshot持久化為臨時文件,臨時文件會統一放到目錄.tmp下。
(2)這個過程因為涉及到磁盤IO操作,因此相對比較耗時。
3、commit階段
(1)遍歷所有的Memstore,將flush階段生成的臨時文件移到指定的ColumnFamily目錄下,
(2)針對HFile生成對應的storefile和Reader,把storefile添加到HStore的storefiles列表中,
(3)最後再清空prepare階段生成的snapshot。

Memstore Flush對業務讀寫的影響
1、想必對於HBase用戶來說,最關心的是flush行為會對讀寫請求造成哪些影響以及如何避免。
2、因為不同觸發方式下的flush操作對用戶請求影響不盡相同,因此下面會根據flush的不同觸發方式分別進行總結,並且會根據影響大小進行歸類:
(1)影響甚微
正常情況下,大部分Memstore Flush操作都不會對業務讀寫產生太大影響,比如這幾種場景:HBase定期刷新Memstore、手動執行flush操作、觸發Memstore級別限制、觸發HLog數量限制以及觸發Region級別限制等,這幾種場景只會阻塞對應Region上的寫請求,阻塞時間很短,毫秒級別。

(2)影響較大
然而一旦觸發Region Server級別限制導致flush,就會對用戶請求產生較大的影響。會阻塞所有落在該Region Server上的更新操作,阻塞時間很長,甚至可以達到分鐘級別。一般情況下Region Server級別限制很難觸發,但在一些極端情況下也不排除有觸發的可能,下面分析一種可能觸發這種flush操作的場景:
//
相關JVM配置以及HBase配置:

maxHeap = 71
hbase.regionserver.global.memstore.upperLimit = 0.35
hbase.regionserver.global.memstore.lowerLimit = 0.30

基於上述配置,可以得到觸發Region Server級別的總Memstore內存和為24.9G,如下所示:

2015-10-12 13:05:16,232 INFO [regionserver60020] regionserver.MemStoreFlusher: globalMemStoreLimit=24.9 G, globalMemStoreLimitLowMark=21.3 G, maxHeap=71 G
//根據上面第3條件的設置
710.30~710.35 //就是region server當memstore的內存綜合趨於 21.3 24.85 高於24.85 就觸發flush 要低於 21.3

分析:
假設每個Memstore大小為默認128M,在上述配置下如果每個Region有兩個Memstore,整個Region Server上運行了100個region,根據計算可得總消耗內存 = 128M 100 2 = 25.6G > 24.9G,很顯然,這種情況下就會觸發Region Server級別限制,對用戶影響相當大。

小結:
1、根據上面的分析,導致觸發Region Server級別限制的因素主要有一個Region Server上運行的Region總數,
2、一個是Region上的Store數(即表的ColumnFamily數)。
3、對於前者,根據讀寫請求量一般建議線上一個Region Server上運行的Region保持在50~80個左右,太小的話會浪費資源,太大的話有可能觸發其他異常;
4、對於後者,建議ColumnFamily越少越好,如果從邏輯上確實需要多個ColumnFamily,最好控制在3個以內。

小夥伴的問題1:
一個查詢需要查一個Store中的mem和file。
如果發現block在blockcache中會去blockcache中讀取,就可以不需要去讀取那個file。
mem是肯定要被讀取(否則讀取的數據有問題)。
cache和file兩者不一定,但是新生成的file如果沒有被讀取過肯定不在blockcache中。
答:
基本正確

小夥伴的問題2:
在memstore flush 機制中 *****
4、當一個Region Server中HLog數量達到上限(可通過參數hbase.regionserver.maxlogs配置)時,系統會選取最早的一個 HLog對應的一個或多個Region進行flush。
“一個Region Server中HLog數量” 不就只有一個嘛,為什麽一個region server 的hlog數量之說,而且博主在“HBase - 數據寫入流程解析”裏面也說了“每個Region Server擁有一個HLog日誌”。這邊描述是否有點問題。不是很明白,還是博主解答。

答:
《HBase - 數據寫入流程解析》中說到“每個Region Server擁有一個HLog日誌”是想強調所有Region共用HLog。一個Region Server中所有Region都會向同一個HLog寫日誌,當HLog大小超過閾值就會新生成一個HLog文件接收新的寫入。所以HLog文件個數實際上有多個的。

小夥伴的問題3:
因此HBase在讀取數據的時候首先檢查請求的數據是否在Memstore,寫緩存未命中的話再到讀緩存中查找,讀緩存還未命中才會到HFile文件中查找,
———————————————
你好!這裏我有個疑問,假如我是scan查詢,寫緩存或者讀緩存只有部分數據滿足要求,這時服務端是直接返回這部分數據,還是會繼續到HFile中查找
答:
全部查詢得到所有結果之後統一返回

參考鏈接: http://hbasefly.com/2016/03/23/hbase-memstore-flush/

HBase – Memstore Flush和flush shell操作 深度解析