Hbase性(xing)能調(diao)優(you)
因部(bu)分章節沒有按配(pei)置項進行索引(yin),不能達到快速查閱的(de)效果(guo)。所以我以配(pei)置項驅(qu)動,重新整理了(le)原(yuan)文(wen),并補充一些自己的(de)理解,如有錯誤,歡迎指正。
配置優化
zookeeper.session.timeout
默認值:3分鐘(180000ms)
說明:RegionServer與Zookeeper間的連接超時時間。當超時時間到后,ReigonServer會被Zookeeper從RS集群清單中移除,HMaster收到移除通知后,會對這臺server負責的regions重新balance,讓其他存活的RegionServer接管.
調優:
這個timeout決定了RegionServer是否能夠及時的failover。設置成1分鐘或更低,可以減少因等待超時而被延長的failover時間。
不(bu)過需要注(zhu)意的是,對于一些(xie)Online應用(yong),RegionServer從宕(dang)機到恢(hui)(hui)復(fu)時(shi)間本身就(jiu)很(hen)短的(網絡閃斷(duan),crash等故(gu)(gu)(gu)障,運(yun)維(wei)可(ke)快速介入(ru)),如(ru)果調低timeout時(shi)間,反而(er)會得不(bu)償失。因為當ReigonServer被(bei)正式(shi)從RS集(ji)群(qun)中移除時(shi),HMaster就(jiu)開始做(zuo)balance了(讓其他RS根據故(gu)(gu)(gu)障機器記錄的WAL日志進行(xing)恢(hui)(hui)復(fu))。當故(gu)(gu)(gu)障的RS在(zai)人工介入(ru)恢(hui)(hui)復(fu)后,這(zhe)個balance動作是毫無(wu)意義的,反而(er)會使負(fu)載不(bu)均勻,給RS帶來更多負(fu)擔。特別是那些(xie)固定分配regions的場景(jing)。
hbase.regionserver.handler.count
默認值:10
說明:RegionServer的請求處理IO線程數。
調優:
這個參數的調優與內存息息相關。
較少的IO線程,適用于處理單次請求內存消耗較高的Big PUT場景(大容量單次PUT或設置了較大cache的scan,均屬于Big PUT)或ReigonServer的內存比較緊張的場景。
較多的IO線程,適用于單次請求內存消耗低,TPS要求非常高的場景。設置該值的時候,以監控內存為主要參考。
這里需要注意的是如果server的region數量很少,大量的請求都落在一個region上,因快速充滿memstore觸發flush導致的讀寫鎖會影響全局TPS,不是IO線程數越高越好。
壓測時,開啟,可以同時監控每次請求的內存消耗和GC的狀況,最后通過多次壓測結果來合理調節IO線程數。
這里是一個案例 ,作者在SSD的機器(qi)上設(she)置IO線程數為100,僅供(gong)參考(kao)。
hbase.hregion.max.filesize
默認值:256M
說明:在當前ReigonServer上單個Reigon的最大存儲空間,單個Region超過該值時,這個Region會被自動split成更小的region。
調優:
小region對split和compaction友好,因為拆分region或compact小region里的storefile速度很快,內存占用低。缺點是split和compaction會很頻繁。
特別是數量較多的小region不停地split, compaction,會導致集群響應時間波動很大,region數量太多不僅給管理上帶來麻煩,甚至會引發一些Hbase的bug。
一(yi)般512以下的都算小region。
大region,則不太適合經常split和compaction,因為做一次compact和split會產生較長時間的停頓,對應用的讀寫性能沖擊非常大。此外,大region意味著較大的storefile,compaction時對內存也是一個挑戰。
當(dang)然,大region也有其用武之(zhi)地。如果你的應用場景中(zhong),某個時(shi)(shi)間(jian)點的訪問量較低,那(nei)么(me)在此時(shi)(shi)做(zuo)compact和(he)split,既能(neng)順利完(wan)成(cheng)split和(he)compaction,又能(neng)保證絕大多數(shu)時(shi)(shi)間(jian)平(ping)穩的讀寫性能(neng)。
既然split和compaction如此影響性能,有沒有辦法去掉?
compaction是無法避免的,split倒是可以從自動調整為手動。
只要通過將這個參數值調大到某個很難達到的值,比如100G,就可以間接禁用自動split(RegionServer不會對未到達100G的region做split)。
再配合這個工具,在需要split時,手動split。
手動split在(zai)靈活性和穩定性上比起自(zi)動split要高(gao)很多,相(xiang)反,管(guan)理成本增加不多,比較推薦online實(shi)時系統(tong)使(shi)用。
內存(cun)方面,小(xiao)region在設置(zhi)memstore的大(da)小(xiao)值上(shang)比較靈(ling)活,大(da)region則(ze)過(guo)大(da)過(guo)小(xiao)都(dou)不行(xing),過(guo)大(da)會(hui)導(dao)致flush時app的IO wait增高(gao),過(guo)小(xiao)則(ze)因store file過(guo)多影響讀(du)性能(neng)。
hbase.regionserver.global.memstore.upperLimit/lowerLimit
默認值:0.4/0.35
upperlimit說明:hbase.hregion.memstore.flush.size 這個參數的作用是當單個Region內所有的memstore大小總和超過指定值時,flush該region的所有memstore。RegionServer的flush是通過將請求添加一個隊列,模擬生產消費模式來異步處理的。那這里就有一個問題,當隊列來不及消費,產生大量積壓請求時,可能會導致內存陡增,最壞的情況是觸發OOM。
這個參數的作用是防止內存占用過大,當ReigonServer內所有region的memstores所占用內存總和達到heap的40%時,HBase會強制block所有的更新并flush這些region以釋放所有memstore占用的內存。
lowerLimit說明: 同upperLimit,只不過lowerLimit在所有region的memstores所占用內存達到Heap的35%時,不flush所有的memstore。它會找一個memstore內存占用最大的region,做個別flush,此時寫更新還是會被block。lowerLimit算是一個在所有region強制flush導致性能降低前的補救措施。在日志中,表現為 “ Flush thread woke up with memory above low water.” 調優**:這是一個Heap內存保護參數,默認值已經能適用大多數場景。
參數調整會影響讀寫,如果寫的壓力大導致經常超過這個閥值,則調小讀緩存hfile.block.cache.size增大該閥值,或者Heap余量較多時,不修改讀緩存大小。
如果在高壓情況下,也沒超過這個閥值,那么建議你適當調小這個閥值再做壓測,確保觸發次數不要太多,然后還有較多Heap余量的時候,調大hfile.block.cache.size提高讀性能。
還(huan)有一(yi)種可能(neng)性是 hbase.hregion.memstore.flush.size保(bao)持不變,但RS維(wei)護了過(guo)多的(de)region,要知道 region數量直接(jie)影響占(zhan)用(yong)內存的(de)大小(xiao)。
hfile.block.cache.size
默認值:0.2
說明:storefile的讀緩存占用Heap的大小百分比,0.2表示20%。該值直接影響數據讀的性能。
調優:當然(ran)是(shi)越(yue)大越(yue)好,如(ru)果(guo)寫(xie)比(bi)(bi)讀少很(hen)多,開到0.4-0.5也沒問題。如(ru)果(guo)讀寫(xie)較均衡,0.3左右。如(ru)果(guo)寫(xie)比(bi)(bi)讀多,果(guo)斷(duan)默認吧。設(she)置(zhi)這個(ge)(ge)值(zhi)(zhi)的(de)時(shi)候,你同時(shi)要參(can)考(kao) hbase.regionserver.global.memstore.upperLimit ,該值(zhi)(zhi)是(shi)memstore占heap的(de)最大百分比(bi)(bi),兩(liang)個(ge)(ge)參(can)數一(yi)個(ge)(ge)影響讀,一(yi)個(ge)(ge)影響寫(xie)。如(ru)果(guo)兩(liang)值(zhi)(zhi)加起來(lai)超(chao)過(guo)80-90%,會有OOM的(de)風險,謹慎設(she)置(zhi)。
hbase.hstore.blockingStoreFiles
默認值:7
說明:在flush時,當一個region中的Store(Coulmn Family)內有超過7個storefile時,則block所有的寫請求進行compaction,以減少storefile數量。
調優:block寫請(qing)求會嚴重影(ying)響當前regionServer的(de)響應(ying)時間,但過多的(de)storefile也會影(ying)響讀(du)性能(neng)。從(cong)實際應(ying)用來看,為(wei)了獲(huo)取(qu)較(jiao)平滑的(de)響應(ying)時間,可將值設為(wei)無限(xian)大。如(ru)果(guo)能(neng)容忍響應(ying)時間出現(xian)較(jiao)大的(de)波(bo)峰波(bo)谷(gu),那么默認或(huo)根據(ju)自身場景(jing)調整即(ji)可。
hbase.hregion.memstore.block.multiplier
默認值:2
說明:當一個region里的memstore占用內存大小超過hbase.hregion.memstore.flush.size兩倍的大小時,block該region的所有請求,進行flush,釋放內存。
雖然我們設置了region所占用的memstores總內存大小,比如64M,但想象一下,在最后63.9M的時候,我Put了一個200M的數據,此時memstore的大小會瞬間暴漲到超過預期的hbase.hregion.memstore.flush.size的幾倍。這個參數的作用是當memstore的大小增至超過hbase.hregion.memstore.flush.size 2倍時,block所有請求,遏制風險進一步擴大。
調優: 這個參數(shu)的默(mo)認值還(huan)是比較靠譜的。如(ru)果(guo)你預(yu)估(gu)你的正(zheng)常(chang)應(ying)用場景(不包括異常(chang))不會出現突(tu)發寫(xie)或寫(xie)的量可控(kong),那么(me)保持默(mo)認值即可。如(ru)果(guo)正(zheng)常(chang)情(qing)況下,你的寫(xie)請求(qiu)量就(jiu)會經常(chang)暴長到正(zheng)常(chang)的幾倍,那么(me)你應(ying)該調大這個倍數(shu)并調整其他(ta)參數(shu)值,比如(ru)hfile.block.cache.size和hbase.regionserver.global.memstore.upperLimit/lowerLimit,以預(yu)留(liu)更多(duo)內存,防止HBase server OOM。
hbase.hregion.memstore.mslab.enabled
默認值:true
說明:減少因內存碎片導致的Full GC,提高整體性能。
調優:詳見
其他
啟用LZO壓縮
LZO對比Hbase默認的GZip,前者性能較高,后者壓縮比較高,具體參見 。對于想(xiang)提高(gao)HBase讀寫性能的開(kai)發者,采用LZO是(shi)比(bi)較好的選擇。對于非常(chang)在乎(hu)存(cun)儲空(kong)間(jian)的開(kai)發者,則建議保持(chi)默認(ren)。
不要在一張表里定義太多的Column Family
Hbase目(mu)前不(bu)能良好(hao)的(de)處理(li)超(chao)過包含2-3個CF的(de)表(biao)。因(yin)為(wei)某(mou)個CF在flush發(fa)生時,它(ta)鄰近的(de)CF也會因(yin)關(guan)聯效應被觸發(fa)flush,最終導致系統產生更多IO。
批量導入
在批量導入數據(ju)到Hbase前,你可(ke)以通過(guo)預先創建regions,來平(ping)衡數據(ju)的(de)負(fu)載。詳見
避免CMS concurrent mode failure
HBase使用CMS GC。默認觸發GC的時機是當年老代內存達到90%的時候,這個百分比由 -XX:CMSInitiatingOccupancyFraction=N 這個參數來設置。concurrent mode failed發生在這樣一個場景:
當(dang)年(nian)老(lao)(lao)代(dai)內(nei)存達到(dao)(dao)90%的(de)時(shi)候,CMS開始進行并(bing)發垃圾收(shou)集(ji),于此同時(shi),新(xin)生(sheng)代(dai)還在迅速(su)不(bu)(bu)斷地晉升對象到(dao)(dao)年(nian)老(lao)(lao)代(dai)。當(dang)年(nian)老(lao)(lao)代(dai)CMS還未(wei)完(wan)成并(bing)發標記時(shi),年(nian)老(lao)(lao)代(dai)滿了,悲劇就發生(sheng)了。CMS因為(wei)沒內(nei)存可(ke)用(yong)不(bu)(bu)得(de)不(bu)(bu)暫(zan)停mark,并(bing)觸(chu)發一次(ci)stop the world(掛起所有(you)jvm線(xian)程),然后采(cai)用(yong)單(dan)線(xian)程拷貝方式(shi)清理所有(you)垃圾對象。這個過程會非常漫(man)長。為(wei)了避免出現concurrent mode failed,建議讓GC在未(wei)到(dao)(dao)90%時(shi),就觸(chu)發。
通過設(she)置(zhi) -XX:CMSInitiatingOccupancyFraction=N
這(zhe)個(ge)百分比, 可以(yi)(yi)簡(jian)單的這(zhe)么(me)計算。如果你的 hfile.block.cache.size 和(he) hbase.regionserver.global.memstore.upperLimit 加起來有(you)60%(默(mo)認),那么(me)你可以(yi)(yi)設置 70-80,一般高10%左右差不多。
Hbase客戶端優化
AutoFlush
將的setAutoFlush設為false,可以支持客戶端批量更新。即當Put填滿客戶端flush緩存時,才發送到服務端。
默認是true。
Scan Caching
scanner一次緩存多少數據來scan(從服務端一次抓多少數據回來scan)。
默認值是(shi) 1,一次只(zhi)取一條。
Scan Attribute Selection
scan時建(jian)議指定需要的Column Family,減少(shao)通信量,否則scan操(cao)作(zuo)默認會返回(hui)整個row的所有數(shu)據(ju)(所有Coulmn Family)。
Close ResultScanners
通過(guo)scan取完數據后(hou),記得要(yao)關閉ResultScanner,否則RegionServer可能會出現問(wen)題(對應的Server資源無法釋放)。
Optimal Loading of Row Keys
當你scan一張表的時候,返(fan)回結果只需要row key(不需要CF, qualifier,values,timestaps)時,你可以(yi)在scan實例中(zhong)添加(jia)一個filterList,并設置(zhi) MUST_PASS_ALL操作,filterList中(zhong)add 或。這樣可以(yi)減少網(wang)絡(luo)通(tong)信量。
Turn off WAL on Puts
當Put某些(xie)非(fei)重要數據時,你可以設(she)置writeToWAL(false),來(lai)進一步(bu)提高(gao)寫性能(neng)。writeToWAL(false)會在Put時放棄寫WAL log。風險(xian)是,當RegionServer宕機時,可能(neng)你剛才Put的那些(xie)數據會丟失,且無(wu)法(fa)恢(hui)復。
啟用Bloom Filter
通過空間換時間,提高讀(du)操(cao)作性能。
參考:
//jm.taobao.org/2013/09/15/975/
//jm.taobao.org/2011/06/22/983/
