1. 調整scan緩存
優化原理:在解釋這個問題之前,首先需要解釋什麼是scan
緩存,通常來講一次scan
會返回大量數據,因此客戶端發起一次scan
請求,實際並不會一次就將所有數據加載到本地,而是分成多次RPC
請求進行加載,這樣設計一方面是因爲大量數據請求可能會導致網絡帶寬嚴重消耗進而影響其他業務,另一方面也有可能因爲數據量太大導致本地客戶端發生OOM
。在這樣的設計體系下用戶會首先加載一部分數據到本地,然後遍歷處理,再加載下一部分數據到本地處理,如此往復,直至所有數據都加載完成。數據加載到本地就存放在scan
緩存中,默認100
條數據大小。通常情況下,默認的scan
緩存設置就可以正常工作的。但是在一些大scan
(一次scan
可能需要查詢幾萬甚至幾十萬行數據)來說,每次請求100
條數據意味着一次scan
需要幾百甚至幾千次RPC
請求,這種交互的代價無疑是很大的。因此可以考慮將scan
緩存設置增大,比如設爲500
或者1000
就可能更加合適。在一次scan
掃描10w+
條數據量的條件下,將scan
緩存從100
增加到1000
,可以有效降低scan
請求的總體延遲,延遲基本降低了25%
左右。
優化建議:大scan
場景下將scan
緩存從100
增大到500
或者1000
,用以減少RPC
次數.
2. 批量get
優化原理:HBase
分別提供了單條get
以及批量get
的API
接口,使用批量get
接口可以減少客戶端到RegionServer
之間的RPC
連接數,提高讀取性能。另外需要注意的是,批量get
請求要麼成功返回所有請求數據,要麼拋出異常。
優化建議:使用批量get
進行讀取請求
3. 顯示指定列族或者列
優化原理:HBase
是典型的列族數據庫,意味着同一列族的數據存儲在一起,不同列族的數據分開存儲在不同的目錄下。如果一個表有多個列族,只是根據rowkey
而不指定列族進行檢索的話不同列族的數據需要獨立進行檢索,性能必然會比指定列族的查詢差很多,很多情況下甚至會有2倍~3倍
的性能損失。
優化建議:可以指定列族或者列進行精確查找的儘量指定查找
4. 離線批量讀取時設置禁止緩存
優化原理:通常離線批量讀取數據會進行一次性全表掃描,一方面數據量很大,另一方面請求只會執行一次。這種場景下如果使用scan
默認設置,就會將數據從HDFS
加載出來之後放到緩存。可想而知,大量數據進入緩存必將其他實時業務熱點數據擠出,其他業務不得不從HDFS
加載,進而會造成明顯的讀延遲
優化建議:離線批量讀取請求設置禁用緩存,scan.setBlockCache(false)
5. 讀請求負載均衡
優化原理:極端情況下假如所有的讀請求都落在一臺RegionServer
的某幾個Region
上,這一方面不能發揮整個集羣的併發處理能力,另一方面勢必造成此臺RegionServer
資源嚴重消耗(比如I/O
耗盡、handler
耗盡等),落在該臺RegionServer
上的其他業務會因此受到很大的波及。可見,讀請求不均衡不僅會造成本身業務性能很差,還會嚴重影響其他業務。當然,寫請求不均衡也會造成類似的問題,可見負載不均衡是HBase的大忌。
優化建議:rowkey
必須進行散列化處理(比如MD5
散列),同時建表必須進行預分區處理
6. BlockCache調節
優化原理:BlockCache
作爲讀緩存,對於讀性能來說至關重要。默認情況下BlockCache
和Memstore
的配置相對比較均衡(各佔40%
),可以根據集羣業務進行修正,比如讀多寫少業務可以將BlockCache
佔比調大。另一方面,BlockCache
的策略選擇也很重要,不同策略對讀性能來說影響並不是很大,但是對GC
的影響卻相當顯著,尤其BucketCache
的offheap
模式下GC
表現很優越。另外,HBase 2.0
對offheap
的改造(HBASE-11425
)將會使HBase
的讀性能得到2~4
倍的提升,同時GC
表現會更好。觀察所有RegionServer的緩存未命中率、配置文件相關配置項一級GC日誌,確認BlockCache是否可以優化
優化建議:JVM Memory < 20GB
,BlockCache
策略選擇LRU
;否則選擇BucketCache
策略的offheap
模式;
7. HFile文件數量
優化原理:HBase
讀取數據通常首先會到Memstore
和BlockCache
中檢索(讀取最近寫入數據和熱點數據),如果查找不到就會到文件中檢索。HBase的類LSM
結構會導致每個store
包含多數HFile
文件,文件越多,檢索所需的I/O
次數必然越多,讀取延遲也就越高。文件數量通常取決於Compaction
的執行策略,一般和兩個配置參數有關:hbase.hstore.compaction.min
和hbase.hstore.compaction.max.size
,前者表示一個store
中的文件數超過多少就應該進行合併,後者表示參數合併的文件大小最大是多少,超過此大小的文件不能參與合併。這兩個參數不能設置太’松’(前者不能設置太大,後者不能設置太小),導致Compaction
合併文件的實際效果不明顯,進而很多文件得不到合併。這樣就會導致HFile
文件數變多。觀察RegionServer
級別以及Region
級別的storefile
數,確認HFile
文件是否過多。
優化建議:hbase.hstore.compaction.min
設置不能太大,默認是3個;設置需要根據Region
大小確定,通常可以簡單的認爲hbase.hstore.compaction.max.size = RegionSize / hbase.hstore.compaction.min
。
8. 控制Compaction消耗系統資源情況
優化原理:Compaction
是將小文件合併爲大文件,提高後續業務隨機讀性能,但是也會帶來I/O
放大以及帶寬消耗問題(數據遠程讀取以及三副本寫入都會消耗系統帶寬)。正常配置情況下Minor Compaction
並不會帶來很大的系統資源消耗,除非因爲配置不合理導致Minor Compaction
太過頻繁,或者Region
設置太大情況下發生Major Compaction
。觀察系統I/O
資源以及帶寬資源使用情況,再觀察Compaction
隊列長度,確認是否由於Compaction
導致系統資源消耗過多。
優化建議:Minor Compaction
設置:hbase.hstore.compaction.min
設置不能太小,又不能設置太大,因此建議設置爲5~6
;hbase.hstore.compaction.max.size = RegionSize / hbase.hstore.compaction.min
; Major Compaction
設置:大Region
讀延遲敏感業務( 100G以上)通常不建議開啓自動Major Compaction
,手動低峯期觸發。小Region
或者延遲不敏感業務可以開啓Major Compaction
,但建議限制流量。
9. 調整數據本地率
數據本地率:HDFS
數據通常存儲三份,假如當前RegionA
處於Node1
上,數據a
寫入的時候三副本爲(Node1
,Node2
,Node3
),數據b
寫入三副本是(Node1
,Node4
,Node5
),數據c
寫入三副本(Node1
,Node3
,Node5
),可以看出來所有數據寫入本地Node1
肯定會寫一份,數據都在本地可以讀到,因此數據本地率是100%
。現在假設RegionA
被遷移到了Node2
上,只有數據a
在該節點上,其他數據(b
和c
)讀取只能遠程跨節點讀,本地率就爲33%
(假設a
,b
和c
的數據大小相同)。
優化原理:數據本地率太低很顯然會產生大量的跨網絡I/O
請求,必然會導致讀請求延遲較高,因此提高數據本地率可以有效優化隨機讀性能。數據本地率低的原因一般是因爲Region
遷移(自動balance
開啓、RegionServer
宕機遷移、手動遷移等),因此一方面可以通過避免Region
無故遷移來保持數據本地率,另一方面如果數據本地率很低,也可以通過執行major_compact
提升數據本地率到100%。
優化建議:避免Region
無故遷移,比如關閉自動balance
、RegionServer
宕機及時拉起並遷回飄走的Region
等;在業務低峯期執行major_compact
提升數據本地率。