鞍山建設(shè)局的網(wǎng)站seo快速排名系統(tǒng)
HBase客戶(hù)端、服務(wù)器端、列簇設(shè)計(jì)、HDFS相關(guān)優(yōu)化,HBase寫(xiě)性能優(yōu)化切入點(diǎn),寫(xiě)異常問(wèn)題檢查點(diǎn)
- HBase讀優(yōu)化
- 1.1 HBase客戶(hù)端優(yōu)化
- 1) scan緩存是否設(shè)置合理?
- 2) get請(qǐng)求是否可以使用批量請(qǐng)求?
- 3) 請(qǐng)求是否可以顯示指定列簇或者列?
- 4) 離線批量讀取請(qǐng)求是否設(shè)置禁止緩存?
- 1.2 HBase服務(wù)器端優(yōu)化
- 1) 讀請(qǐng)求是否均衡?
- 2) BlockCache是否設(shè)置合理?
- 3) HFile文件是否太多?
- 4) Compaction是否消耗系統(tǒng)資源過(guò)多?
- 1.3 HBase列簇設(shè)計(jì)優(yōu)化
- 1) Bloomfilter是否設(shè)置?是否設(shè)置合理?
- 1.4 HDFS相關(guān)優(yōu)化
- 1) Short-Circuit Local Read功能是否開(kāi)啟?
- 2) Hedged Read功能是否開(kāi)啟?
- 3) 數(shù)據(jù)本地率是否太低?
- 1.5 HBase讀性能優(yōu)化歸納
- HBase寫(xiě)優(yōu)化
- 2.1 寫(xiě)性能優(yōu)化切入點(diǎn)
- 1) 是否需要寫(xiě)WAL?WAL是否需要同步寫(xiě)入?
- 2) Put是否可以同步批量提交?
- 3) Put是否可以異步批量提交?
- 4) Region是否太少?
- 5) 寫(xiě)入請(qǐng)求是否不均衡?
- 6) 寫(xiě)入KeyValue數(shù)據(jù)是否太大?
- 案件一:大字段寫(xiě)入導(dǎo)致其他業(yè)務(wù)吞吐量急劇下降
- 案件二:大字段scan導(dǎo)致RegionServer宕機(jī)
- 2.2 寫(xiě)異常問(wèn)題檢查點(diǎn)
- 1) Memstore設(shè)置是否會(huì)觸發(fā)Region級(jí)別或者RegionServer級(jí)別flush操作?
- 2) Store中HFile數(shù)量是否大于配置參數(shù)blockingStoreFile?
HBase讀優(yōu)化
1.1 HBase客戶(hù)端優(yōu)化
和大多數(shù)系統(tǒng)一樣,客戶(hù)端作為業(yè)務(wù)讀寫(xiě)的入口,姿勢(shì)使用不正確通常會(huì)導(dǎo)致本業(yè)務(wù)讀延遲較高實(shí)際上存在一些使用姿勢(shì)的推薦用法,這里一般需要關(guān)注四個(gè)問(wèn)題:
1) scan緩存是否設(shè)置合理?
優(yōu)化原理:在解釋這個(gè)問(wèn)題之前,首先需要解釋什么是scan緩存,通常來(lái)講一次scan會(huì)返回大量數(shù)據(jù),因此客戶(hù)端發(fā)起一次scan請(qǐng)求,實(shí)際并不會(huì)一次就將所有數(shù)據(jù)加載到本地,而是分成多次RPC請(qǐng)求進(jìn)行加載,這樣設(shè)計(jì)一方面是因?yàn)榇罅繑?shù)據(jù)請(qǐng)求可能會(huì)導(dǎo)致網(wǎng)絡(luò)帶寬嚴(yán)重消耗進(jìn)而影響其他業(yè)務(wù),另一方面也有可能因?yàn)閿?shù)據(jù)量太大導(dǎo)致本地客戶(hù)端發(fā)生OOM。
在這樣的設(shè)計(jì)體系下用戶(hù)會(huì)首先加載一部分?jǐn)?shù)據(jù)到本地,然后遍歷處理,再加載下一部分?jǐn)?shù)據(jù)到本地處理,如此往復(fù),直至所有數(shù)據(jù)都加載完成。數(shù)據(jù)加載到本地就存放在scan緩存中,默認(rèn)100條數(shù)據(jù)大小。
通常情況下,默認(rèn)的scan緩存設(shè)置就可以正常工作的。但是在一些大scan(一次scan可能需要查詢(xún)幾萬(wàn)甚至幾十萬(wàn)行數(shù)據(jù))來(lái)說(shuō),每次請(qǐng)求100條數(shù)據(jù)意味著一次scan需要幾百甚至幾千次RPC請(qǐng)求,這種交互的代價(jià)無(wú)疑是很大的。因此可以考慮將scan緩存設(shè)置增大,比如設(shè)為500或者1000就可能更加合適。
之前做過(guò)一次試驗(yàn),在一次scan掃描10w+條數(shù)據(jù)量的條件下,將scan緩存從100增加到1000,可以有效降低scan請(qǐng)求的總體延遲,延遲基本降低了25%左右。
優(yōu)化建議:大scan場(chǎng)景下將scan緩存從100增大到500或者1000,用以減少RPC次數(shù)
2) get請(qǐng)求是否可以使用批量請(qǐng)求?
優(yōu)化原理:HBase分別提供了單條get
以及批量get
的API接口,使用批量get接口可以減少客戶(hù)端到RegionServer之間的RPC連接數(shù),提高讀取性能。
另外需要注意的是,批量get請(qǐng)求要么成功返回所有請(qǐng)求數(shù)據(jù),要么拋出異常。
優(yōu)化建議:使用批量get進(jìn)行讀取請(qǐng)求
3) 請(qǐng)求是否可以顯示指定列簇或者列?
優(yōu)化原理:HBase是典型的列簇?cái)?shù)據(jù)庫(kù),意味著同一列簇的數(shù)據(jù)存儲(chǔ)在一起,不同列簇的數(shù)據(jù)分開(kāi)存儲(chǔ)在不同的目錄下。
如果一個(gè)表有多個(gè)列簇,只是根據(jù)Rowkey而不指定列簇進(jìn)行檢索的話不同列簇的數(shù)據(jù)需要獨(dú)立進(jìn)行檢索,性能必然會(huì)比指定列簇的查詢(xún)差很多,很多情況下甚至?xí)?code>2倍~3倍的性能損失。
優(yōu)化建議:可以指定列簇或者列進(jìn)行精確查找的盡量指定查找
4) 離線批量讀取請(qǐng)求是否設(shè)置禁止緩存?
優(yōu)化原理:通常離線批量讀取數(shù)據(jù)會(huì)進(jìn)行一次性全表掃描,一方面數(shù)據(jù)量很大,另一方面請(qǐng)求只會(huì)執(zhí)行一次。這種場(chǎng)景下如果使用scan默認(rèn)設(shè)置,就會(huì)將數(shù)據(jù)從HDFS加載出來(lái)之后放到緩存。
可想而知,大量數(shù)據(jù)進(jìn)入緩存必將其他實(shí)時(shí)業(yè)務(wù)熱點(diǎn)數(shù)據(jù)擠出,其他業(yè)務(wù)不得不從HDFS加載,進(jìn)而會(huì)造成明顯的讀延遲毛刺
優(yōu)化建議:離線批量讀取請(qǐng)求設(shè)置禁用緩存,scan.setBlockCache(false)
1.2 HBase服務(wù)器端優(yōu)化
一般服務(wù)端端問(wèn)題一旦導(dǎo)致業(yè)務(wù)讀請(qǐng)求延遲較大的話,通常是集群級(jí)別的,即整個(gè)集群的業(yè)務(wù)都會(huì)反映讀延遲較大??梢詮?個(gè)方面入手:
1) 讀請(qǐng)求是否均衡?
優(yōu)化原理:極端情況下假如所有的讀請(qǐng)求都落在一臺(tái)RegionServer
的某幾個(gè)Region
上,這一方面不能發(fā)揮整個(gè)集群的并發(fā)處理能力,另一方面勢(shì)必造成此臺(tái)RegionServer資源嚴(yán)重消耗(比如IO耗盡、handler耗盡等),落在該臺(tái)RegionServer上的其他業(yè)務(wù)會(huì)因此受到很大的波及。
可見(jiàn),讀請(qǐng)求不均衡不僅會(huì)造成本身業(yè)務(wù)性能很差,還會(huì)嚴(yán)重影響其他業(yè)務(wù)。當(dāng)然,寫(xiě)請(qǐng)求不均衡也會(huì)造成類(lèi)似的問(wèn)題,可見(jiàn)負(fù)載不均衡是HBase的大忌。
觀察確認(rèn):觀察所有RegionServer的讀請(qǐng)求QPS曲線,確認(rèn)是否存在讀請(qǐng)求不均衡現(xiàn)象
優(yōu)化建議:RowKey必須進(jìn)行散列化處理(比如MD5散列),同時(shí)建表必須進(jìn)行預(yù)分區(qū)處理
2) BlockCache是否設(shè)置合理?
優(yōu)化原理:BlockCache作為讀緩存,對(duì)于讀性能來(lái)說(shuō)至關(guān)重要。默認(rèn)情況下BlockCache和Memstore的配置相對(duì)比較均衡(各占40%),可以根據(jù)集群業(yè)務(wù)進(jìn)行修正,比如讀多寫(xiě)少業(yè)務(wù)可以將BlockCache占比調(diào)大。
另一方面,BlockCache的策略選擇也很重要,不同策略對(duì)讀性能來(lái)說(shuō)影響并不是很大,但是對(duì)GC的影響卻相當(dāng)顯著,尤其BucketCache的offheap模式下GC表現(xiàn)很優(yōu)越。另外,HBase 2.0對(duì)offheap的改造(HBASE-11425)將會(huì)使HBase的讀性能得到2~4倍的提升,同時(shí)GC表現(xiàn)會(huì)更好!
觀察確認(rèn):觀察所有RegionServer的緩存未命中率、配置文件相關(guān)配置項(xiàng)一級(jí)GC日志,確認(rèn)BlockCache是否可以?xún)?yōu)化
優(yōu)化建議:JVM內(nèi)存配置量 < 20G,BlockCache策略選擇LRUBlockCache;否則選擇BucketCache策略的offheap模式;期待HBase 2.0的到來(lái)!
3) HFile文件是否太多?
優(yōu)化原理:HBase讀取數(shù)據(jù)通常首先會(huì)到Memstore和BlockCache中檢索(讀取最近寫(xiě)入數(shù)據(jù)&熱點(diǎn)數(shù)據(jù)),如果查找不到就會(huì)到文件中檢索。
HBase的類(lèi)LSM結(jié)構(gòu)會(huì)導(dǎo)致每個(gè)store包含多數(shù)HFile文件,文件越多,檢索所需的IO次數(shù)必然越多,讀取延遲也就越高。
文件數(shù)量通常取決于Compaction的執(zhí)行策略,一般和兩個(gè)配置參數(shù)有關(guān):
hbase.hstore.compactionThreshold
hbase.hstore.compaction.max.size
前者表示一個(gè)store中的文件數(shù)超過(guò)多少就應(yīng)該進(jìn)行合并,后者表示參數(shù)合并的文件大小最大是多少,超過(guò)此大小的文件不能參與合并。這兩個(gè)參數(shù)不能設(shè)置太"松"(前者不能設(shè)置太大,后者不能設(shè)置太小),導(dǎo)致Compaction合并文件的實(shí)際效果不明顯,進(jìn)而很多文件得不到合并。這樣就會(huì)導(dǎo)致HFile文件數(shù)變多。
觀察確認(rèn):觀察RegionServer級(jí)別以及Region級(jí)別的storefile數(shù),確認(rèn)HFile文件是否過(guò)多
優(yōu)化建議:hbase.hstore.compactionThreshold
設(shè)置不能太大,默認(rèn)是3個(gè);設(shè)置需要根據(jù)Region大小確定,通??梢院?jiǎn)單的認(rèn)為 hbase.hstore.compaction.max.size = RegionSize / hbase.hstore.compactionThreshold
4) Compaction是否消耗系統(tǒng)資源過(guò)多?
優(yōu)化原理:Compaction是將小文件合并為大文件,提高后續(xù)業(yè)務(wù)隨機(jī)讀性能,但是也會(huì)帶來(lái)IO放大以及帶寬消耗問(wèn)題(數(shù)據(jù)遠(yuǎn)程讀取以及三副本寫(xiě)入都會(huì)消耗系統(tǒng)帶寬)。
正常配置情況下Minor Compaction并不會(huì)帶來(lái)很大的系統(tǒng)資源消耗,除非因?yàn)榕渲貌缓侠韺?dǎo)致Minor Compaction太過(guò)頻繁,或者Region設(shè)置太大情況下發(fā)生Major Compaction。
觀察確認(rèn):觀察系統(tǒng)IO資源以及帶寬資源使用情況,再觀察Compaction隊(duì)列長(zhǎng)度,確認(rèn)是否由于Compaction導(dǎo)致系統(tǒng)資源消耗過(guò)多
優(yōu)化建議:
-
Minor Compaction
設(shè)置:hbase.hstore.compactionThreshold
設(shè)置不能太小,又不能設(shè)置太大,因此建議設(shè)置為5~6;hbase.hstore.compaction.max.size = RegionSize / hbase.hstore.compactionThreshold
-
Major Compaction
設(shè)置:大Region讀延遲敏感業(yè)務(wù)( 100G以上)通常不建議開(kāi)啟自動(dòng)Major Compaction,手動(dòng)低峰期觸發(fā)。小Region或者延遲不敏感業(yè)務(wù)可以開(kāi)啟Major Compaction,但建議限制流量; -
期待更多的優(yōu)秀Compaction策略,類(lèi)似于stripe-compaction盡早提供穩(wěn)定服務(wù)
1.3 HBase列簇設(shè)計(jì)優(yōu)化
HBase列簇設(shè)計(jì)對(duì)讀性能影響也至關(guān)重要,其特點(diǎn)是只影響單個(gè)業(yè)務(wù),并不會(huì)對(duì)整個(gè)集群產(chǎn)生太大影響。列簇設(shè)計(jì)主要從以下方面檢查:
1) Bloomfilter是否設(shè)置?是否設(shè)置合理?
優(yōu)化原理:Bloomfilter主要用來(lái)過(guò)濾不存在待檢索RowKey或者Row-Col的HFile文件,避免無(wú)用的IO操作。
它會(huì)告訴你在這個(gè)HFile文件中是否可能存在待檢索的KV,如果不存在,就可以不用消耗IO打開(kāi)文件進(jìn)行seek。很顯然,通過(guò)設(shè)置Bloomfilter可以提升隨機(jī)讀寫(xiě)的性能。
Bloomfilter取值有兩個(gè),row以及rowcol,需要根據(jù)業(yè)務(wù)來(lái)確定具體使用哪種。如果業(yè)務(wù)大多數(shù)隨機(jī)查詢(xún)僅僅使用row作為查詢(xún)條件,Bloomfilter一定要設(shè)置為row,否則如果大多數(shù)隨機(jī)查詢(xún)使用row+cf作為查詢(xún)條件,Bloomfilter需要設(shè)置為rowcol。如果不確定業(yè)務(wù)查詢(xún)類(lèi)型,設(shè)置為row。
優(yōu)化建議:任何業(yè)務(wù)都應(yīng)該設(shè)置Bloomfilter,通常設(shè)置為row就可以,除非確認(rèn)業(yè)務(wù)隨機(jī)查詢(xún)類(lèi)型為row+cf,可以設(shè)置為rowcol
1.4 HDFS相關(guān)優(yōu)化
HDFS作為HBase最終數(shù)據(jù)存儲(chǔ)系統(tǒng),通常會(huì)使用三副本策略存儲(chǔ)HBase數(shù)據(jù)文件以及日志文件。
從HDFS的角度望上層看,HBase即是它的客戶(hù)端,HBase通過(guò)調(diào)用它的客戶(hù)端進(jìn)行數(shù)據(jù)讀寫(xiě)操作,因此HDFS的相關(guān)優(yōu)化也會(huì)影響HBase的讀寫(xiě)性能。這里主要關(guān)注如下三個(gè)方面:
1) Short-Circuit Local Read功能是否開(kāi)啟?
優(yōu)化原理:當(dāng)前HDFS讀取數(shù)據(jù)都需要經(jīng)過(guò)DataNode,客戶(hù)端會(huì)向DataNode發(fā)送讀取數(shù)據(jù)的請(qǐng)求,DataNode接受到請(qǐng)求之后從硬盤(pán)中將文件讀出來(lái),再通過(guò)TPC發(fā)送給客戶(hù)端。Short Circuit策略允許客戶(hù)端繞過(guò)DataNode直接讀取本地?cái)?shù)據(jù)。(具體原理參考此處)
優(yōu)化建議:開(kāi)啟Short Circuit Local Read功能
2) Hedged Read功能是否開(kāi)啟?
優(yōu)化原理:HBase數(shù)據(jù)在HDFS中一般都會(huì)存儲(chǔ)三份,而且優(yōu)先會(huì)通過(guò)Short-Circuit Local Read
功能?chē)L試本地讀。但是在某些特殊情況下,有可能會(huì)出現(xiàn)因?yàn)榇疟P(pán)問(wèn)題或者網(wǎng)絡(luò)問(wèn)題引起的短時(shí)間本地讀取失敗,為了應(yīng)對(duì)這類(lèi)問(wèn)題,社區(qū)開(kāi)發(fā)者提出了補(bǔ)償重試機(jī)制 – Hedged Read。
該機(jī)制基本工作原理為:客戶(hù)端發(fā)起一個(gè)本地讀,一旦一段時(shí)間之后還沒(méi)有返回,客戶(hù)端將會(huì)向其他DataNode發(fā)送相同數(shù)據(jù)的請(qǐng)求。哪一個(gè)請(qǐng)求先返回,另一個(gè)就會(huì)被丟棄。
優(yōu)化建議:開(kāi)啟Hedged Read功能
3) 數(shù)據(jù)本地率是否太低?
數(shù)據(jù)本地率:HDFS數(shù)據(jù)通常存儲(chǔ)三份,假如當(dāng)前RegionA處于Node1上,數(shù)據(jù)a寫(xiě)入的時(shí)候三副本為(Node1,Node2,Node3
),數(shù)據(jù)b寫(xiě)入三副本是(Node1,Node4,Node5
),數(shù)據(jù)c寫(xiě)入三副本(Node1,Node3,Node5
),可以看出來(lái)所有數(shù)據(jù)寫(xiě)入本地Node1肯定會(huì)寫(xiě)一份,數(shù)據(jù)都在本地可以讀到,因此數(shù)據(jù)本地率是100%。
現(xiàn)在假設(shè)RegionA被遷移到了Node2上,只有數(shù)據(jù)a在該節(jié)點(diǎn)上,其他數(shù)據(jù)(b和c)讀取只能遠(yuǎn)程跨節(jié)點(diǎn)讀,本地率就為33%(假設(shè)a,b和c的數(shù)據(jù)大小相同)。
優(yōu)化原理:數(shù)據(jù)本地率太低很顯然會(huì)產(chǎn)生大量的跨網(wǎng)絡(luò)IO請(qǐng)求,必然會(huì)導(dǎo)致讀請(qǐng)求延遲較高,因此提高數(shù)據(jù)本地率可以有效優(yōu)化隨機(jī)讀性能。
數(shù)據(jù)本地率低的原因一般是因?yàn)镽egion遷移(自動(dòng)balance開(kāi)啟、RegionServer宕機(jī)遷移、手動(dòng)遷移等),因此一方面可以通過(guò)避免Region無(wú)故遷移來(lái)保持?jǐn)?shù)據(jù)本地率,另一方面如果數(shù)據(jù)本地率很低,也可以通過(guò)執(zhí)行major_compact提升數(shù)據(jù)本地率到100%。
優(yōu)化建議:避免Region無(wú)故遷移,比如關(guān)閉自動(dòng)balance、RS宕機(jī)及時(shí)拉起并遷回飄走的Region等;在業(yè)務(wù)低峰期執(zhí)行major_compact提升數(shù)據(jù)本地率
1.5 HBase讀性能優(yōu)化歸納
在本文開(kāi)始的時(shí)候提到讀延遲較大無(wú)非三種常見(jiàn)的表象,單個(gè)業(yè)務(wù)慢
、集群隨機(jī)讀慢
、某個(gè)業(yè)務(wù)隨機(jī)讀之后其他業(yè)務(wù)受到影響導(dǎo)致隨機(jī)讀延遲很大
。
了解完常見(jiàn)的可能導(dǎo)致讀延遲較大的一些問(wèn)題之后,我們將這些問(wèn)題進(jìn)行如下歸類(lèi),讀者可以在看到現(xiàn)象之后在對(duì)應(yīng)的問(wèn)題列表中進(jìn)行具體定位:
HBase寫(xiě)優(yōu)化
和讀相比,HBase寫(xiě)數(shù)據(jù)流程倒是顯得很簡(jiǎn)單:數(shù)據(jù)先順序?qū)懭際Log,再寫(xiě)入對(duì)應(yīng)的緩存Memstore,當(dāng)Memstore中數(shù)據(jù)大小達(dá)到一定閾值(128M)之后,系統(tǒng)會(huì)異步將Memstore中數(shù)據(jù)flush到HDFS形成小文件。
HBase數(shù)據(jù)寫(xiě)入通常會(huì)遇到兩類(lèi)問(wèn)題,一類(lèi)是寫(xiě)性能較差,另一類(lèi)是數(shù)據(jù)根本寫(xiě)不進(jìn)去。這兩類(lèi)問(wèn)題的切入點(diǎn)也不盡相同,如下圖所示:
2.1 寫(xiě)性能優(yōu)化切入點(diǎn)
1) 是否需要寫(xiě)WAL?WAL是否需要同步寫(xiě)入?
優(yōu)化原理:數(shù)據(jù)寫(xiě)入流程可以理解為一次順序?qū)慦AL + 一次寫(xiě)緩存
,通常情況下寫(xiě)緩存延遲很低,因此提升寫(xiě)性能就只能從WAL入手。
WAL機(jī)制一方面是為了確保數(shù)據(jù)即使寫(xiě)入緩存丟失也可以恢復(fù),另一方面是為了集群之間異步復(fù)制。默認(rèn)WAL機(jī)制開(kāi)啟且使用同步機(jī)制寫(xiě)入WAL。
首先考慮業(yè)務(wù)是否需要寫(xiě)WAL,通常情況下大多數(shù)業(yè)務(wù)都會(huì)開(kāi)啟WAL機(jī)制(默認(rèn)),但是對(duì)于部分業(yè)務(wù)可能并不特別關(guān)心異常情況下部分?jǐn)?shù)據(jù)的丟失,而更關(guān)心數(shù)據(jù)寫(xiě)入吞吐量,比如某些推薦業(yè)務(wù),這類(lèi)業(yè)務(wù)即使丟失一部分用戶(hù)行為數(shù)據(jù)可能對(duì)推薦結(jié)果并不構(gòu)成很大影響,但是對(duì)于寫(xiě)入吞吐量要求很高,不能造成數(shù)據(jù)隊(duì)列阻塞。這種場(chǎng)景下可以考慮關(guān)閉WAL寫(xiě)入,寫(xiě)入吞吐量可以提升2x~3x。退而求其次,有些業(yè)務(wù)不能接受不寫(xiě)WAL,但可以接受WAL異步寫(xiě)入,也是可以考慮優(yōu)化的,通常也會(huì)帶來(lái)1x~2x的性能提升。
優(yōu)化推薦:根據(jù)業(yè)務(wù)關(guān)注點(diǎn)在WAL機(jī)制與寫(xiě)入吞吐量之間做出選擇
其他注意點(diǎn):對(duì)于使用Increment操作的業(yè)務(wù),WAL可以設(shè)置關(guān)閉,也可以設(shè)置異步寫(xiě)入,方法同Put類(lèi)似。相信大多數(shù)Increment操作業(yè)務(wù)對(duì)WAL可能都不是那么敏感~
2) Put是否可以同步批量提交?
優(yōu)化原理:HBase分別提供了單條put以及批量put的API接口,使用批量put接口可以減少客戶(hù)端到RegionServer之間的RPC連接數(shù),提高寫(xiě)入性能。另外需要注意的是,批量put請(qǐng)求要么全部成功返回,要么拋出異常。
優(yōu)化建議:使用批量put進(jìn)行寫(xiě)入請(qǐng)求
3) Put是否可以異步批量提交?
優(yōu)化原理:業(yè)務(wù)如果可以接受異常情況下少量數(shù)據(jù)丟失的話,還可以使用異步批量提交的方式提交請(qǐng)求。提交分為兩階段執(zhí)行:用戶(hù)提交寫(xiě)請(qǐng)求之后,數(shù)據(jù)會(huì)寫(xiě)入客戶(hù)端緩存,并返回用戶(hù)寫(xiě)入成功;當(dāng)客戶(hù)端緩存達(dá)到閾值(默認(rèn)2M)之后批量提交給RegionServer。需要注意的是,在某些情況下客戶(hù)端異常的情況下緩存數(shù)據(jù)有可能丟失。
優(yōu)化建議:在業(yè)務(wù)可以接受的情況下開(kāi)啟異步批量提交
使用方式:setAutoFlush(false)
4) Region是否太少?
優(yōu)化原理:當(dāng)前集群中表的Region個(gè)數(shù)如果小于RegionServer個(gè)數(shù),即Num(Region of Table) < Num(RegionServer),可以考慮切分Region并盡可能分布到不同RegionServer來(lái)提高系統(tǒng)請(qǐng)求并發(fā)度,如果Num(Region of Table) > Num(RegionServer),再增加Region個(gè)數(shù)效果并不明顯。
優(yōu)化建議:在Num(Region of Table) < Num(RegionServer)的場(chǎng)景下切分部分請(qǐng)求負(fù)載高的Region并遷移到其他RegionServer;
5) 寫(xiě)入請(qǐng)求是否不均衡?
優(yōu)化原理:另一個(gè)需要考慮的問(wèn)題是寫(xiě)入請(qǐng)求是否均衡,如果不均衡,一方面會(huì)導(dǎo)致系統(tǒng)并發(fā)度較低,另一方面也有可能造成部分節(jié)點(diǎn)負(fù)載很高,進(jìn)而影響其他業(yè)務(wù)。分布式系統(tǒng)中特別害怕一個(gè)節(jié)點(diǎn)負(fù)載很高的情況,一個(gè)節(jié)點(diǎn)負(fù)載很高可能會(huì)拖慢整個(gè)集群,這是因?yàn)楹芏鄻I(yè)務(wù)會(huì)使用Mutli批量提交讀寫(xiě)請(qǐng)求,一旦其中一部分請(qǐng)求落到該節(jié)點(diǎn)無(wú)法得到及時(shí)響應(yīng),就會(huì)導(dǎo)致整個(gè)批量請(qǐng)求超時(shí)。因此不怕節(jié)點(diǎn)宕掉,就怕節(jié)點(diǎn)奄奄一息!
優(yōu)化建議:檢查RowKey設(shè)計(jì)以及預(yù)分區(qū)策略,保證寫(xiě)入請(qǐng)求均衡。
6) 寫(xiě)入KeyValue數(shù)據(jù)是否太大?
KeyValue大小對(duì)寫(xiě)入性能的影響巨大,一旦遇到寫(xiě)入性能比較差的情況,需要考慮是否由于寫(xiě)入KeyValue數(shù)據(jù)太大導(dǎo)致。KeyValue大小對(duì)寫(xiě)入性能影響曲線圖如下:
圖中橫坐標(biāo)是寫(xiě)入的一行數(shù)據(jù)(每行數(shù)據(jù)10列)大小,左縱坐標(biāo)是寫(xiě)入吞吐量,右坐標(biāo)是寫(xiě)入平均延遲(ms)??梢钥闯鲭S著單行數(shù)據(jù)大小不斷變大,寫(xiě)入吞吐量急劇下降,寫(xiě)入延遲在100K之后急劇增大。
說(shuō)到這里,有必要和大家分享兩起在生產(chǎn)線環(huán)境因?yàn)闃I(yè)務(wù)KeyValue較大導(dǎo)致的嚴(yán)重問(wèn)題,一起是因?yàn)榇笞侄螛I(yè)務(wù)寫(xiě)入導(dǎo)致其他業(yè)務(wù)吞吐量急劇下降,另一起是因?yàn)榇笞侄螛I(yè)務(wù)scan導(dǎo)致RegionServer宕機(jī)。
案件一:大字段寫(xiě)入導(dǎo)致其他業(yè)務(wù)吞吐量急劇下降
部分業(yè)務(wù)反饋集群寫(xiě)入忽然變慢、數(shù)據(jù)開(kāi)始堆積的情況,查看集群表級(jí)別的數(shù)據(jù)讀寫(xiě)QPS監(jiān)控,發(fā)現(xiàn)問(wèn)題的第一個(gè)關(guān)鍵點(diǎn):業(yè)務(wù)A開(kāi)始寫(xiě)入之后整個(gè)集群其他部分業(yè)務(wù)寫(xiě)入QPS都幾乎斷崖式下跌,初步懷疑黑手就是業(yè)務(wù)A。
下圖是當(dāng)時(shí)業(yè)務(wù)A的寫(xiě)入QPS(事后發(fā)現(xiàn)忘了截取其他表QPS斷崖式下跌的慘象),但是第一感覺(jué)是QPS并不高啊,怎么去影響別人!
于是就繼續(xù)查看其他監(jiān)控信息,首先確認(rèn)系統(tǒng)資源(主要是IO)并沒(méi)有到達(dá)瓶頸,其次確認(rèn)了寫(xiě)入的均衡性,直至看到下圖,才追蹤到影響其他業(yè)務(wù)寫(xiě)入的第二個(gè)關(guān)鍵點(diǎn):RegionServer的handler(配置150)被殘暴耗盡:
對(duì)比上面兩張圖,是不是發(fā)現(xiàn)出奇的一致,那就可以基本確認(rèn)是由于該業(yè)務(wù)寫(xiě)入導(dǎo)致這臺(tái)RegionServer的handler
被耗盡,進(jìn)而其他業(yè)務(wù)拿不到handler,自然寫(xiě)不進(jìn)去。那問(wèn)題來(lái)了,為什么會(huì)這樣?
正常情況下handler在處理完客戶(hù)端請(qǐng)求之后會(huì)立馬釋放,唯一的解釋是這些請(qǐng)求的延遲實(shí)在太大。
試想,我們?nèi)h堡店排隊(duì)買(mǎi)漢堡,有150個(gè)窗口服務(wù),正常情況下大家買(mǎi)一個(gè)很快,這樣150個(gè)窗口可能只需要50個(gè)服務(wù)。假設(shè)忽然來(lái)了一批大漢,要定制超大漢堡,好了,所有的窗口都工作起來(lái),而且因?yàn)榇鬂h堡不好制作導(dǎo)致服務(wù)很慢,這樣必然會(huì)導(dǎo)致其他排隊(duì)的用戶(hù)長(zhǎng)時(shí)間等待,直至超時(shí)。
可回頭一想這可是寫(xiě)請(qǐng)求啊,怎么會(huì)有這么大的請(qǐng)求延遲!和業(yè)務(wù)方溝通之后確認(rèn)該表主要存儲(chǔ)語(yǔ)料庫(kù)文檔信息,都是平均100K左右的數(shù)據(jù),是不是已經(jīng)猜到了結(jié)果,沒(méi)錯(cuò),就是因?yàn)檫@個(gè)業(yè)務(wù)KeyValue太大導(dǎo)致。KeyValue太大會(huì)導(dǎo)致HLog文件寫(xiě)入頻繁切換、flush以及compaction頻繁觸發(fā),寫(xiě)入性能急劇下降。
目前針對(duì)這種較大KeyValue寫(xiě)入性能較差的問(wèn)題還沒(méi)有直接的解決方案,好在社區(qū)已經(jīng)意識(shí)到這個(gè)問(wèn)題,在接下來(lái)即將發(fā)布的下一個(gè)大版本HBase 2.0.0版本會(huì)針對(duì)該問(wèn)題進(jìn)行深入優(yōu)化,詳見(jiàn)HBase MOB,優(yōu)化后用戶(hù)使用HBase存儲(chǔ)文檔、圖片等二進(jìn)制數(shù)據(jù)都會(huì)有極佳的性能體驗(yàn)。
案件二:大字段scan導(dǎo)致RegionServer宕機(jī)
案件現(xiàn)場(chǎng):有段時(shí)間有個(gè)0.98集群的RegionServer經(jīng)常頻繁宕機(jī),查看日志是由于”java.lang.OutOfMemoryError: Requested array size exceeds VM limit
”,如下圖所示:
原因分析:通過(guò)查看源碼以及相關(guān)文檔,確認(rèn)該異常發(fā)生在scan結(jié)果數(shù)據(jù)回傳給客戶(hù)端時(shí)由于數(shù)據(jù)量太大導(dǎo)致申請(qǐng)的array大小超過(guò)JVM規(guī)定的最大值( Interge.Max_Value-2)。造成該異常的兩種最常見(jiàn)原因分別是:
- 表列太寬(幾十萬(wàn)列或者上百萬(wàn)列),并且scan返回沒(méi)有對(duì)列數(shù)量做任何限制,導(dǎo)致一行數(shù)據(jù)就可能因?yàn)榘罅苛卸鴶?shù)據(jù)超過(guò)array大小閾值
- KeyValue太大,并且scan返回沒(méi)有對(duì)返回結(jié)果大小做任何限制,導(dǎo)致返回?cái)?shù)據(jù)結(jié)果大小超過(guò)array大小閾值
有的童鞋就要提問(wèn)啦,說(shuō)如果已經(jīng)對(duì)返回結(jié)果大小做了限制,在表列太寬的情況下是不是就可以不對(duì)列數(shù)量做限制呢。這里需要澄清一下,如果不對(duì)列數(shù)據(jù)做限制,數(shù)據(jù)總是一行一行返回的,即使一行數(shù)據(jù)大小大于設(shè)置的返回結(jié)果限制大小,也會(huì)返回完整的一行數(shù)據(jù)。在這種情況下,如果這一行數(shù)據(jù)已經(jīng)超過(guò)array大小閾值,也會(huì)觸發(fā)OOM異常。
解決方案:目前針對(duì)該異常有兩種解決方案,其一是升級(jí)集群到1.0,問(wèn)題都解決了。其二是要求客戶(hù)端訪問(wèn)的時(shí)候?qū)Ψ祷亟Y(jié)果大小做限制(scan.setMaxResultSize(210241024))、并且對(duì)列數(shù)量做限制(scan.setBatch(100)),當(dāng)然,0.98.13版本以后也可以對(duì)返回結(jié)果大小在服務(wù)器端進(jìn)行限制,設(shè)置參數(shù)hbase.server.scanner.max.result.size即可
2.2 寫(xiě)異常問(wèn)題檢查點(diǎn)
上述幾點(diǎn)主要針對(duì)寫(xiě)性能優(yōu)化進(jìn)行了介紹,除此之外,在一些情況下還會(huì)出現(xiàn)寫(xiě)異常,一旦發(fā)生需要考慮下面兩種情況(GC引起的不做介紹):
1) Memstore設(shè)置是否會(huì)觸發(fā)Region級(jí)別或者RegionServer級(jí)別flush操作?
問(wèn)題解析:以RegionServer級(jí)別flush進(jìn)行解析,HBase設(shè)定一旦整個(gè)RegionServer上所有Memstore占用內(nèi)存大小總和大于配置文件中upperlimit時(shí),系統(tǒng)就會(huì)執(zhí)行RegionServer級(jí)別flush,flush算法會(huì)首先按照Region大小進(jìn)行排序,再按照該順序依次進(jìn)行flush,直至總Memstore大小低至lowerlimit。這種flush通常會(huì)block較長(zhǎng)時(shí)間,在日志中會(huì)發(fā)現(xiàn)“Memstore is above high water mark and block 7452 ms”,表示這次flush將會(huì)阻塞7s左右。
問(wèn)題檢查點(diǎn):
- Region規(guī)模與Memstore總大小設(shè)置是否合理?如果RegionServer上Region較多,而Memstore總大小設(shè)置的很小(JVM設(shè)置較小或者upper.limit設(shè)置較小),就會(huì)觸發(fā)RegionServer級(jí)別flush。集群規(guī)劃相關(guān)內(nèi)容可以參考文章《HBase最佳實(shí)踐-集群規(guī)劃》
- 列族是否設(shè)置過(guò)多,通常情況下表列族建議設(shè)置在1~3個(gè)之間,最好一個(gè)。如果設(shè)置過(guò)多,會(huì)導(dǎo)致一個(gè)Region中包含很多Memstore,導(dǎo)致更容易觸到高水位upperlimit
2) Store中HFile數(shù)量是否大于配置參數(shù)blockingStoreFile?
問(wèn)題解析:對(duì)于數(shù)據(jù)寫(xiě)入很快的集群,還需要特別關(guān)注一個(gè)參數(shù):hbase.hstore.blockingStoreFiles
,此參數(shù)表示如果當(dāng)前hstore中文件數(shù)大于該值,系統(tǒng)將會(huì)強(qiáng)制執(zhí)行compaction操作進(jìn)行文件合并,合并的過(guò)程會(huì)阻塞整個(gè)hstore的寫(xiě)入。通常情況下該場(chǎng)景發(fā)生在數(shù)據(jù)寫(xiě)入很快的情況下,在日志中可以發(fā)現(xiàn)"Waited 3722ms on a compaction to clean up ‘too many store files
"
問(wèn)題檢查點(diǎn):
- 參數(shù)設(shè)置是否合理?
hbase.hstore.compactionThreshold
表示啟動(dòng)compaction的最低閾值,該值不能太大,否則會(huì)積累太多文件,一般建議設(shè)置為5~8左右。hbase.hstore.blockingStoreFiles
默認(rèn)設(shè)置為7,可以適當(dāng)調(diào)大一些。