HBase數據寫入通常會遇到兩種問題,壹種是寫入性能差,另壹種是根本無法寫入數據。這兩類問題的切入點也不同,如下圖所示:
優化原理:數據寫入過程可以理解為壹個順序寫入墻+壹個寫緩存。通常,寫緩存延遲非常低,因此提高寫性能的唯壹方法是從WAL開始。壹方面,WAL機制是為了確保即使寫緩存丟失也可以恢復數據,另壹方面是為了集群之間的異步復制。默認的WAL機制是打開的,WAL是使用同步機制編寫的。首先,考慮服務是否需要編寫WAL。壹般來說,大多數服務都會開啟WAL機制(默認),但對於某些服務來說,它們可能並不特別關心異常情況下的某些數據丟失,而是更關心數據寫入吞吐量。例如,對於壹些推薦服務,即使丟失了壹些用戶行為數據,也可能不會對推薦結果產生很大影響,但它需要較高的寫入吞吐量,並且不能導致數據隊列擁塞。在這種場景下,我們可以考慮關閉WAL寫入,寫入吞吐量可以提升2倍~ 3倍。退而求其次,有些服務不能接受不寫WAL,但可以接受異步寫WAL,這也可以考慮優化,通常會帶來1x ~ 2x的性能提升。
優化建議:根據業務考慮在WAL機制和寫入吞吐量之間進行選擇。
其他註意事項:對於使用Increment操作的業務,可以將WAL設置為close或設置為異步寫入,方法與Put類似。我相信大部分增量操作可能對WAL沒那麽敏感~
優化原理:HBase分別提供單放和批量放的API接口。使用batch put接口可以減少客戶端和RegionServer之間的RPC連接數,提高寫入性能。此外,應該註意的是,所有批處理put請求都將成功返回,否則將引發異常。
優化建議:使用batch put進行寫請求。
優化原則:如果業務可以接受異常情況下少量數據的丟失,也可以通過異步批量提交的方式提交請求。提交分兩個階段執行:用戶提交寫入請求後,數據將被寫入客戶端緩存,並返回用戶的成功寫入;當客戶端緩存達到閾值(默認2M)時,它將被批量提交到RegionServer。需要註意的是,在某些情況下,如果客戶端出現異常,緩存的數據可能會丟失。
優化建議:當業務可以接受時,開始異步批量提交。
用法:setAutoFlush(false)
優化原則:如果當前集群中表的區域數量小於RegionServer的數量,即Num(region of table):Num(region server),則增加區域數量的效果並不明顯。
優化建議:在Num(Region of table)《Num(Region server)場景下,分段部分請求負載較高的區域,遷移到其他區域服務器;
優化原則:另壹個需要考慮的問題是寫請求是否平衡。如果不這樣做,壹方面會導致系統並發量低,另壹方面也可能造成某些節點的高負載,從而影響其他服務。分布式系統特別害怕壹個節點的高負載,這可能會降低整個集群的速度。這是因為很多業務會使用Mutli批量提交讀寫請求,壹旦部分請求落在節點上,將無法得到及時響應,從而導致整個批量請求超時。所以不怕節點掉下來,就怕節點快死了!
優化建議:檢查行鍵設計和預分區策略,以確保平衡的寫請求。
KeyValue的大小對寫入性能有很大影響。壹旦寫入性能不佳,就需要考慮是否是由於寫入過多的KeyValue數據導致的。鍵值大小對寫入性能的影響圖如下:
在圖中,橫坐標是寫入的壹行數據的大小(每行數據為10列),左側縱坐標是寫入吞吐量,右側坐標是平均寫入延遲(ms)。可以看出,隨著單行數據量的增加,寫入吞吐量急劇下降,在100K K後寫入延遲急劇增加。
說到這裏,有必要與您分享生產線環境中業務的大KeyValue所導致的兩個嚴重問題。壹個是由於大字段業務的寫入導致其他業務的吞吐量急劇下降,另壹個是大字段業務掃描導致RegionServer宕機。
案例1:大型字段的寫入導致其他服務的吞吐量急劇下降。
壹些服務報告群集寫入突然變慢,數據開始累積。查看集群表級數據讀寫的QPS監控,我們發現了問題的第壹個關鍵點:業務A開始寫後,整個集群中其他服務的QPS寫幾乎壹落千丈,初步懷疑黑手是業務A
下圖是當時《商業A》對QPS的寫作(事後發現腦殘們忘了截取其他表格中QPS墜崖的悲劇形象),但第壹感覺是QPS並不高,為什麽要影響別人呢?
於是我繼續查看其他監控信息。首先,我確認系統資源(主要是IO)沒有達到瓶頸。其次,我確認了寫作的平衡。直到我看到下圖,我跟蹤了影響其他業務編寫的第二個關鍵點:RegionServer的處理程序(配置150)被殘酷地耗盡了:
對比上面兩張圖,是不是出奇的壹致,基本可以確認這個RegionServer的handler是因為這個服務的寫入而耗盡的,然後其他服務得不到handler,自然就寫不進去了。這就是問題所在。為什麽?在正常情況下,handler會在處理完客戶端請求後立即釋放。唯壹的解釋是這些請求的延遲太大了。
想象壹下,我們去漢堡店排隊買漢堡,有150個窗口服務。正常情況下,每個人都很快購買壹個,因此150 windows可能只需要50個服務。假設突然來了壹群大個子,想定制超大漢堡。嗯,所有的窗口都在工作,而且服務非常慢,因為大漢堡不容易制作,這將不可避免地導致其他用戶排隊等待很長時間,直到他們超時。
但當我回想起來,這是壹個寫作請求,怎麽會有這麽大的請求延遲!經與業務方溝通,確認該表主要存儲語料庫文檔信息,平均約為100K。妳猜到結果了嗎?是的,因為這項業務的關鍵價值太大了。過大的KeyValue會導致HLog文件寫入頻繁切換,flush和COMPACT頻繁觸發,寫入性能急劇下降。
目前,還沒有直接解決如此大的KeyValue的寫入性能差的問題。幸運的是,社區已經意識到了這個問題,即將發布的HBase 2.0.0下壹個大版本將針對這個問題進行進壹步優化。詳見HBase MOB。優化後,用戶在使用HBase存儲文檔和圖片等二進制數據時將獲得出色的性能體驗。
案例2:大字段掃描導致RegionServer宕機。
案例場景:有壹次,壹個0.98集群的RegionServer頻繁宕機,查看日誌的原因是“Java . lang . out of memory error:requested array size over VM limit”,如下圖所示:
原因分析:通過查看源代碼和相關文檔,確認掃描結果數據發送回客戶端時出現異常,應用的數組大小超過了最大值(inter。max _ value-2)由JVM指定。這種異常的兩個最常見原因是:
有些童鞋要提問了,說如果返回結果的大小已經被限制了,那麽如果列太寬,列數可以不被限制嗎?這裏需要澄清的是,如果列數據不受限制,數據將始終逐行返回,即使壹行數據的大小大於返回結果的設置限制大小,也將返回完整的壹行數據。在這種情況下,如果該行數據超過了數組大小閾值,也將觸發OOM異常。
解決方案:目前,該異常有兩種解決方案。壹個是把集群升級到1.0,所有問題都解決了。第二是要求客戶端限制返回結果的大小(掃描。setmaxresultsize(2 1024 1024))並限制列數(scan . set batch(100))。當然也可以在0.98.13版本之後返回。
以上幾點主要集中在寫入性能的優化上。此外,在某些情況下會發生寫入異常。壹旦發生這種情況,需要考慮以下兩種情況(由於GC原因未介紹):
問題分析:用RegionServer級別的flush進行分析,HBase設置壹旦整個RegionServer上所有Memstore占用的內存大小之和大於配置文件中的upperlimit,系統將執行RegionServer級別的flush,flush算法將首先根據Region的大小進行排序,然後按此順序進行flush,直到Memstore的總大小與lowerlimit壹樣低。這種刷新通常會阻塞很長時間,日誌中會出現“內存高於高水位線,阻塞時間為7452毫秒”的消息,表明這種刷新將阻塞大約7秒..
問題檢查點:
問題分析:對於數據寫入速度較快的集群,我們需要特別註意壹個參數:h base . hstore . blockingstorefiles .該參數表示如果當前hstore中的文件數量大於該值,系統將強制執行壓縮操作來合並文件,合並過程將阻塞整個h store的寫入。通常,當數據快速寫入時會出現這種情況,並且可以在日誌中找到“在比較時等待了3722毫秒以清除‘太多的存儲文件’”。
問題檢查點:
從寫性能優化和寫異常診斷兩個方面詳細說明了HBase中數據寫入可能存在的問題。我相信它是基於0.98版本編寫的最佳解決方案。然而,壹些企業可能仍然覺得它不夠快。畢竟,“更快”是所有存儲系統活下去的動力。還有改進的空間嗎?當然,以下是對後HBase版本寫入性能優化的兩個核心改進的簡要介紹:
該功能意味著WAL可以單獨放在SSD上,這樣即使在默認情況下(WALSync),寫入性能也會大大提高。應該註意的是,該功能基於HDFS 2.6.0+,而以前版本的HDFS不支持該功能。詳情請參考https://issues.apache.org/jira/browse/HBASE-12848.官方吉拉
該功能也是對WAL的修改。目前,WAL被設計為由RegionServer上的所有Region*** * *共享。可想而知,當寫入吞吐量較高時,將會出現資源競爭,從而降低整體性能。為了解決這個問題,社區合作夥伴(阿裏巴巴神)提出了Multiple WALs機制,管理員可以為每個名稱空間下的所有表設置壹個* * * Wals。這樣,寫作成績可以提高20% ~ 40%左右。詳情請參考https://issues.apache.org/jira/browse/HBASE-14457.官方吉拉