因官方Book Performance Tuning部分章節(jié) 沒有按配置項(xiàng)進(jìn)行索引,不能達(dá)到快速查閱的效果。所以我以配置項(xiàng)驅(qū)動(dòng),重新整理了原文,并補(bǔ)充一些自己的理解,如有錯(cuò)誤,歡迎指正。
配置優(yōu)化
zookeeper.session.timeout
默認(rèn)值:3分鐘(180000ms)
說(shuō)明:RegionServer與Zookeeper間的連接超時(shí)時(shí)間。當(dāng)超時(shí)時(shí)間到后,ReigonServer會(huì)被Zookeeper從RS集群清單中移除,HMaster收到移除通知后,會(huì)對(duì)這臺(tái)server負(fù)責(zé)的regions重新balance,讓其他存活的RegionServer接管.
調(diào)優(yōu):
這個(gè)timeout決定了RegionServer是否能夠及時(shí)的failover。設(shè)置成1分鐘或更低,可以減少因等待超時(shí)而被延長(zhǎng)的failover時(shí)間。
不過(guò)需要注意的是,對(duì)于一些Online應(yīng)用,RegionServer從宕機(jī)到恢復(fù)時(shí)間本身就很短的(網(wǎng)絡(luò)閃斷,crash等故障,運(yùn)維可快速介入),如果調(diào)低timeout時(shí)間,反而會(huì)得不償失。因?yàn)楫?dāng)ReigonServer被正式從RS集群中移除時(shí),HMaster就開始做balance了 (讓其他RS根據(jù)故障機(jī)器記錄的WAL日志進(jìn)行恢復(fù))。當(dāng)故障的RS在人工介入恢復(fù)后,這個(gè)balance動(dòng)作是毫無(wú)意義的,反而會(huì)使負(fù)載不均勻,給RS 帶來(lái)更多負(fù)擔(dān)。特別是那些固定分配regions的場(chǎng)景。
hbase.regionserver.handler.count
默認(rèn)值:10
說(shuō)明:RegionServer的請(qǐng)求處理IO線程數(shù)。
調(diào)優(yōu):
這個(gè)參數(shù)的調(diào)優(yōu)與內(nèi)存息息相關(guān)。
較少的IO線程,適用于處理單次請(qǐng)求內(nèi)存消耗較高的Big PUT場(chǎng)景(大容量單次PUT或設(shè)置了較大cache的scan,均屬于Big PUT)或ReigonServer的內(nèi)存比較緊張的場(chǎng)景。
較多的IO線程,適用于單次請(qǐng)求內(nèi)存消耗低,TPS要求非常高的場(chǎng)景。設(shè)置該值的時(shí)候,以監(jiān)控內(nèi)存為主要參考。
這里需要注意的是如果server的region數(shù)量很少,大量的請(qǐng)求都落在一個(gè)region上,因快速充滿memstore觸發(fā)flush導(dǎo)致的讀寫鎖會(huì)影響全局TPS,不是IO線程數(shù)越高越好。
壓測(cè)時(shí),開啟Enabling RPC-level logging ,可以同時(shí)監(jiān)控每次請(qǐng)求的內(nèi)存消耗和GC的狀況,最后通過(guò)多次壓測(cè)結(jié)果來(lái)合理調(diào)節(jié)IO線程數(shù)。
這里是一個(gè)案例 Hadoop and HBase Optimization for Read Intensive Search Applications ,作者在SSD的機(jī)器上設(shè)置IO線程數(shù)為100,僅供參考。
hbase.hregion.max.filesize
默認(rèn)值:256M
說(shuō)明:在當(dāng)前ReigonServer上單個(gè)Reigon的最大存儲(chǔ)空間,單個(gè)Region超過(guò)該值時(shí),這個(gè)Region會(huì)被自動(dòng)split成更小的region。
調(diào)優(yōu):
小region對(duì)split和compaction友好,因?yàn)椴鸱謗egion或compact小region里的storefile速度很快,內(nèi)存占用低。缺點(diǎn)是split和compaction會(huì)很頻繁。
特別是數(shù)量較多的小region不停地split, compaction,會(huì)導(dǎo)致集群響應(yīng)時(shí)間波動(dòng)很大,region數(shù)量太多不僅給管理上帶來(lái)麻煩,甚至?xí)l(fā)一些Hbase的bug。
一般512以下的都算小region。
大region,則不太適合經(jīng)常split和compaction,因?yàn)樽鲆淮蝐ompact和split會(huì)產(chǎn)生較長(zhǎng)時(shí)間的停頓,對(duì)應(yīng)用的讀寫性能沖擊非常大。此外,大region意味著較大的storefile,compaction時(shí)對(duì)內(nèi)存也是一個(gè)挑戰(zhàn)。
當(dāng)然,大region也有其用武之地。如果你的應(yīng)用場(chǎng)景中,某個(gè)時(shí)間點(diǎn)的訪問(wèn)量較低,那么在此時(shí)做compact和split,既能順利完成split和compaction,又能保證絕大多數(shù)時(shí)間平穩(wěn)的讀寫性能。
既然split和compaction如此影響性能,有沒有辦法去掉?
compaction是無(wú)法避免的,split倒是可以從自動(dòng)調(diào)整為手動(dòng)。
只要通過(guò)將這個(gè)參數(shù)值調(diào)大到某個(gè)很難達(dá)到的值,比如100G,就可以間接禁用自動(dòng)split(RegionServer不會(huì)對(duì)未到達(dá)100G的region做split)。
再配合RegionSplitter這個(gè)工具,在需要split時(shí),手動(dòng)split。
手動(dòng)split在靈活性和穩(wěn)定性上比起自動(dòng)split要高很多,相反,管理成本增加不多,比較推薦online實(shí)時(shí)系統(tǒng)使用。
內(nèi)存方面,小region在設(shè)置memstore的大小值上比較靈活,大region則過(guò)大過(guò)小都不行,過(guò)大會(huì)導(dǎo)致flush時(shí)app的IO wait增高,過(guò)小則因store file過(guò)多影響讀性能。
hbase.regionserver.global.memstore.upperLimit/lowerLimit
默認(rèn)值:0.4/0.35
upperlimit說(shuō)明:hbase.hregion.memstore.flush.size 這個(gè)參數(shù)的作用是 當(dāng)單個(gè)memstore達(dá)到指定值時(shí),flush該memstore。但是,一臺(tái)ReigonServer可能有成百上千個(gè)memstore,每個(gè) memstore也許未達(dá)到flush.size,jvm的heap就不夠用了。該參數(shù)就是為了限制memstores占用的總內(nèi)存。
當(dāng)ReigonServer內(nèi)所有的memstore所占用的內(nèi)存總和達(dá)到heap的40%時(shí),HBase會(huì)強(qiáng)制block所有的更新并flush這些memstore以釋放所有memstore占用的內(nèi)存。
lowerLimit說(shuō)明: 同upperLimit,只不過(guò)當(dāng)全局memstore的內(nèi)存達(dá)到35%時(shí),它不會(huì)flush所有的memstore,它會(huì)找一些內(nèi)存占用較大的 memstore,做個(gè)別flush,當(dāng)然更新還是會(huì)被block。lowerLimit算是一個(gè)在全局flush導(dǎo)致性能暴跌前的補(bǔ)救措施。為什么說(shuō)是性能暴跌?可以想象一下,如果memstore需要在一段較長(zhǎng)的時(shí)間內(nèi)做全量flush,且這段時(shí)間內(nèi)無(wú)法接受任何讀寫請(qǐng)求,對(duì)HBase集群的性能影響是很大的。
調(diào)優(yōu):
這是一個(gè)Heap內(nèi)存保護(hù)參數(shù),默認(rèn)值已經(jīng)能適用大多數(shù)場(chǎng)景。它的調(diào)整一般是為了配合某些專屬優(yōu)化,比如讀密集型應(yīng)用,將讀緩存開大,降低該值,騰出更多內(nèi)存給其他模塊使用。
這個(gè)參數(shù)會(huì)給使用者帶來(lái)什么影響?
比如,10G內(nèi)存,100個(gè)region,每個(gè)memstore 64M,假設(shè)每個(gè)region只有一個(gè)memstore,那么當(dāng)100個(gè)memstore平均占用到50%左右時(shí),就會(huì)達(dá)到lowerLimit的限制。假設(shè)此時(shí),其他memstore同樣有很多的寫請(qǐng)求進(jìn)來(lái)。在那些大的region未flush完,就可能又超過(guò)了upperlimit,則所有 region都會(huì)被block,開始觸發(fā)全局flush。
不過(guò),除了你的內(nèi)存非常小或你的應(yīng)用場(chǎng)景里大多數(shù)都是讀,我覺得不需要去調(diào)這個(gè)參數(shù)。
hfile.block.cache.size
默認(rèn)值:0.2
說(shuō)明:storefile的讀緩存占用Heap的大小百分比,0.2表示20%。該值直接影響數(shù)據(jù)讀的性能。
調(diào)優(yōu):
當(dāng)然是越大越好,如果讀比寫少,開到0.4-0.5也沒問(wèn)題。如果讀寫較均衡,0.3左右。如果寫比讀多,果斷默認(rèn)吧。設(shè)置這個(gè)值的時(shí)候,你同時(shí)要參考 hbase.regionserver.global.memstore.upperLimit ,該值是memstore占heap的最大百分比,兩個(gè)參數(shù)一個(gè)影響讀,一個(gè)影響寫。如果兩值加起來(lái)超過(guò)80-90%,會(huì)有OOM的風(fēng)險(xiǎn),謹(jǐn)慎設(shè)置。
hbase.hstore.blockingStoreFiles
默認(rèn)值:7
說(shuō)明:在compaction時(shí),如果一個(gè)Store(Coulmn Family)內(nèi)有超過(guò)7個(gè)storefile需要合并,則block所有的寫請(qǐng)求,進(jìn)行flush,限制storefile數(shù)量增長(zhǎng)過(guò)快。
調(diào)優(yōu):
block寫請(qǐng)求會(huì)影響當(dāng)前region的性能,將值設(shè)為單個(gè)region可以支撐的最大store file數(shù)量會(huì)是個(gè)不錯(cuò)的選擇,即允許comapction時(shí),memstore繼續(xù)生成storefile。最大storefile數(shù)量可通過(guò) region size/memstore size來(lái)計(jì)算。如果你將region size設(shè)為無(wú)限大,那么你需要預(yù)估一個(gè)region可能產(chǎn)生的最大storefile數(shù)。
hbase.hregion.memstore.block.multiplier
默認(rèn)值:2
說(shuō)明:當(dāng)一個(gè)region里的memstore超過(guò)單個(gè)memstore.size兩倍的大小時(shí),block該region的所有請(qǐng)求,進(jìn)行 flush,釋放內(nèi)存。雖然我們?cè)O(shè)置了memstore的總大小,比如64M,但想象一下,在最后63.9M的時(shí)候,我Put了一個(gè)100M的數(shù)據(jù),此時(shí) memstore的大小會(huì)瞬間暴漲到超過(guò)預(yù)期的memstore.size。這個(gè)參數(shù)的作用是當(dāng)memstore的大小增至超過(guò) memstore.size時(shí),block所有請(qǐng)求,遏制風(fēng)險(xiǎn)進(jìn)一步擴(kuò)大。
調(diào)優(yōu):
其他
啟用LZO壓縮
LZO對(duì)比Hbase默認(rèn)的GZip,前者性能較高,后者壓縮比較高,具體參見 Using LZO Compression 。對(duì)于想提高HBase讀寫性能的開發(fā)者,采用LZO是比較好的選擇。對(duì)于非常在乎存儲(chǔ)空間的開發(fā)者,則建議保持默認(rèn)。
不要在一張表里定義太多的Column Family
Hbase目前不能良好的處理超過(guò)包含2-3個(gè)CF的表。因?yàn)槟硞€(gè)CF在flush發(fā)生時(shí),它鄰近的CF也會(huì)因關(guān)聯(lián)效應(yīng)被觸發(fā)flush,最終導(dǎo)致系統(tǒng)產(chǎn)生更多IO。
批量導(dǎo)入
在批量導(dǎo)入數(shù)據(jù)到Hbase前,你可以通過(guò)預(yù)先創(chuàng)建regions,來(lái)平衡數(shù)據(jù)的負(fù)載。詳見 Table Creation: Pre-Creating Regions
避免CMS concurrent mode failure
HBase使用CMS GC。默認(rèn)觸發(fā)GC的時(shí)機(jī)是當(dāng)年老代內(nèi)存達(dá)到90%的時(shí)候,這個(gè)百分比由 -XX:CMSInitiatingOccupancyFraction=N 這個(gè)參數(shù)來(lái)設(shè)置。concurrent mode failed發(fā)生在這樣一個(gè)場(chǎng)景:
當(dāng)年老代內(nèi)存達(dá)到90%的時(shí)候,CMS開始進(jìn)行并發(fā)垃圾收集,于此同時(shí),新生代還在迅速不斷地晉升對(duì)象到年老代。當(dāng)年老代CMS還未完成并發(fā)標(biāo)記時(shí),年老代滿了,悲劇就發(fā)生了。CMS因?yàn)闆]內(nèi)存可用不得不暫停mark,并觸發(fā)一次全jvm的stop the world(掛起所有線程),然后采用單線程拷貝方式清理所有垃圾對(duì)象。這個(gè)過(guò)程會(huì)非常漫長(zhǎng)。為了避免出現(xiàn)concurrent mode failed,我們應(yīng)該讓GC在未到90%時(shí),就觸發(fā)。
通過(guò)設(shè)置 -XX:CMSInitiatingOccupancyFraction=N
這個(gè)百分比, 可以簡(jiǎn)單的這么計(jì)算。如果你的 hfile.block.cache.size 和 hbase.regionserver.global.memstore.upperLimit 加起來(lái)有60%(默認(rèn)),那么你可以設(shè)置 70-80,一般高10%左右差不多。
Hbase客戶端優(yōu)化
AutoFlush
將HTable的setAutoFlush設(shè)為false,可以支持客戶端批量更新。即當(dāng)Put填滿客戶端flush緩存時(shí),才發(fā)送到服務(wù)端。
默認(rèn)是true。
Scan Caching
scanner一次緩存多少數(shù)據(jù)來(lái)scan(從服務(wù)端一次抓多少數(shù)據(jù)回來(lái)scan)。
默認(rèn)值是 1,一次只取一條。
Scan Attribute Selection
scan時(shí)建議指定需要的Column Family,減少通信量,否則scan操作默認(rèn)會(huì)返回整個(gè)row的所有數(shù)據(jù)(所有Coulmn Family)。
Close ResultScanners
通過(guò)scan取完數(shù)據(jù)后,記得要關(guān)閉ResultScanner,否則RegionServer可能會(huì)出現(xiàn)問(wèn)題(對(duì)應(yīng)的Server資源無(wú)法釋放)。
Optimal Loading of Row Keys
當(dāng)你scan一張表的時(shí)候,返回結(jié)果只需要row key(不需要CF, qualifier,values,timestaps)時(shí),你可以在scan實(shí)例中添加一個(gè)filterList,并設(shè)置 MUST_PASS_ALL操作,filterList中add FirstKeyOnlyFilter或KeyOnlyFilter。這樣可以減少網(wǎng)絡(luò)通信量。
Turn off WAL on Puts
當(dāng)Put某些非重要數(shù)據(jù)時(shí),你可以設(shè)置writeToWAL(false),來(lái)進(jìn)一步提高寫性能。writeToWAL(false)會(huì)在Put時(shí)放棄寫WAL log。風(fēng)險(xiǎn)是,當(dāng)RegionServer宕機(jī)時(shí),可能你剛才Put的那些數(shù)據(jù)會(huì)丟失,且無(wú)法恢復(fù)。
啟用Bloom Filter
Bloom Filter通過(guò)空間換時(shí)間,提高讀操作性能。
原文鏈接:http://baiyunl./blog/1119129
【編輯推薦】