1. 程式人生 > >Hbase效能優化總結

Hbase效能優化總結

本文主要是從HBase應用程式設計與開發的角度,總結幾種常用的效能優化方法。

Auto Flash

通過呼叫HTable.setAutoFlushTo(false)方法可以將HTable寫客戶端自動flush關閉,這樣可以批量寫入資料到HBase,而不是有一條put就執行一次更新,只有當put填滿客戶端寫快取的時候,才會向HBase服務端發起寫請求。預設情況下auto flush是開啟的。

Write Buffer

通過呼叫HTable.setWriteBufferSize(writeBufferSize)方法可以設定HTable客戶端的寫buffer大小,如果新設定的buffer小於當前寫buffer中的資料時,buffer將會被flush到服務端。其中,writeBufferSize的單位是byte位元組數,可以根基實際寫入資料量的多少來設定該值。

WAL Flag

在HBase中,客戶端向叢集中的RegionServer提交資料時(Put/Delete操作),首先會寫到WAL(Write Ahead Log)日誌,即HLog,一個RegionServer上的所有Region共享一個HLog,只有當WAL日誌寫成功後,再接著寫MemStore,然後客戶端被通知提交資料成功,如果寫WAL日誌失敗,客戶端被告知提交失敗,這樣做的好處是可以做到RegionServer宕機後的資料恢復。 對於不太重要的資料,可以在Put/Delete操作時,通過呼叫Put.setWriteToWAL(false)Delete.setWriteToWAL(false)

函式,放棄寫WAL日誌,以提高資料寫入的效能。

注:如果關閉WAL日誌,一旦RegionServer宕機,Put/Delete的資料將會無法根據WAL日誌進行恢復。

Compression 壓縮

資料量大,邊壓邊寫也會提升效能的,畢竟IO是大資料的最嚴重的瓶頸,哪怕使用了SSD也是一樣。眾多的壓縮方式中,推薦使用SNAPPY。從壓縮率和壓縮速度來看,價效比最高。

HColumnDescriptor hcd = new HColumnDescriptor(familyName);   
hcd.setCompressionType(Algorithm.SNAPPY);  

批量寫

通過呼叫HTable.put(Put)

方法可以將一個指定的row key記錄寫入HBase,同樣HBase提供了另一個方法:通過呼叫HTable.put(List<Put>)方法可以將指定的row key列表,批量寫入多行記錄,這樣做的好處是批量執行,只需要一次網路I/O開銷,這對於對資料實時性要求高,網路傳輸RTT高的情景下可能帶來明顯的效能提升。

多執行緒併發寫

在客戶端開啟多個 HTable 寫執行緒,每個寫執行緒負責一個 HTable 物件的 flush 操作,這樣結合定時 flush 和寫 buffer(writeBufferSize),可以既保證在資料量小的時候,資料可以在較短時間內被 flush(如1秒內),同時又保證在資料量大的時候,寫 buffer 一滿就及時進行 flush。

批量讀

通過呼叫 HTable.get(Get) 方法可以根據一個指定的 row key 獲取一行記錄,同樣 HBase 提供了另一個方法:通過呼叫 HTable.get(List) 方法可以根據一個指定的 row key 列表,批量獲取多行記錄,這樣做的好處是批量執行,只需要一次網路 I/O 開銷,這對於對資料實時性要求高而且網路傳輸 RTT 高的情景下可能帶來明顯的效能提升。

快取查詢結果

對於頻繁查詢 HBase 的應用場景,可以考慮在應用程式中做快取,當有新的查詢請求時,首先在快取中查詢,如果存在則直接返回,不再查詢 HBase;否則對 HBase 發起讀請求查詢,然後在應用程式中將查詢結果快取起來。至於快取的替換策略,可以考慮 LRU 等常用的策略。

HBase資料表優化

預分割槽

預設情況下,在建立HBase表的時候會自動建立一個Region分割槽,當匯入資料的時候,所有的HBase客戶端都向Region寫資料,知道這個Region足夠大才進行切分,一種可以加快批量寫入速度的方法是通過預先建立一些空的Regions,這樣當資料寫入HBase的時候,會按照Region分割槽情況,在進群內做資料的負載均衡。

Rowkey優化

rowkey是按照字典儲存,因此設定rowkey時,要充分利用排序特點,將經常一起讀取的資料儲存到一塊,將最近可能會被訪問的資料放到一塊。 rowkey若是遞增生成的,建議不要使用正序直接寫入,可以使用字串反轉方式寫入,使得rowkey大致均衡分佈,這樣設計的好處是能將RegionServer的負載均衡,否則容易產生所有新資料都在集中在一個RegionServer上堆積的現象,這一點還可以結合table的與分割槽設計。

減少Column Family數量

不要在一張表中定義太多的column family。目前HBase並不能很好的處理超過2-3個column family的表,因為某個column family在flush的時候,它臨近的column family也會因關聯效應被觸發flush,最終導致系統產生更過的I/O;

設定最大版本數

建立表的時候,可以通過 HColumnDescriptor.setMaxVersions(int maxVersions) 設定表中資料的最大版本,如果只需要儲存最新版本的資料,那麼可以設定 setMaxVersions(1)。

快取策略(setCaching)

建立表的時候,可以通過HColumnDEscriptor.setInMemory(true)將表放到RegionServer的快取中,保證在讀取的時候被cache命中。

設定儲存生命期

建立表的時候,可以通過HColumnDescriptor.setTimeToLive(int timeToLive)設定表中資料的儲存生命週期,過期資料將自動被刪除

磁碟配置

每臺RegionServer管理10-1000個Regions。每個Region在1-2G,則每臺server最少要10G,最大要1000*2G=2TB,考慮3備份,需要6TB。方案1是3塊2TB磁碟,2是12塊500G磁碟,頻寬足夠時,後者能提供更大的吞吐率,更細力度的冗餘備份,更快速的單盤故障恢復。

分配何時的記憶體給RegionServer

在不影響其他服務的情況下,越大越好。在HBase的conf目錄下的hbase-env.sh的最後新增export HBASE_REGIONSERVER_OPTS="- Xmx16000m $HBASE_REGIONSERVER_OPTS" 其中16000m為分配給REgionServer的記憶體大小。

寫資料的備份數

備份數與讀效能是成正比,與寫效能成反比,且備份數影響高可用性。有兩種配置方式,一種是將hdfs-site.xml拷貝到hbase的conf目錄下,然後在其中新增或修改配置項dfs.replication的值為要設定的備份數,這種修改所有的HBase使用者都生效。另一種方式是改寫HBase程式碼,讓HBase支援針對列族設定備份數,在建立表時,設定列族備份數,預設為3,此種備份數支隊設定的列族生效。

客戶端一次從伺服器拉取的數量

通過配置一次拉取較大的資料量可以減少客戶端獲取資料的時間,但是他會佔用客戶端的記憶體,有三個地方可以進行配置

  1. 在HBase的conf配置檔案中進行配置hbase.client.scanner.caching;
  2. 通過呼叫HTble.setScannerCaching(int scannerCaching)進行配置;
  3. 通過呼叫Sacn.setCaching(int caching)進行配置,三者的優先順序越來越高。

客戶端拉取的時候指定列族

scan是指定需要column family,可以減少網路傳輸資料量,否則預設scan操作會返回整行所有column family的資料

拉取完資料之後關閉ResultScanner

通過 scan 取完資料後,記得要關閉 ResultScanner,否則 RegionServer 可能會出現問題(對應的 Server 資源無法釋放)。

RegionServer的請求處理IO執行緒數

較少的IO執行緒適用於處理單次請求記憶體消耗較高的Big Put場景(大容量單詞Put或設定了較大cache的scan,均資料Big Put)或RegionServer的記憶體比較緊張的場景。

較多的IO執行緒,適用於單次請求記憶體消耗低,TPS要求(每次事務處理量)非常高的場景。這隻該值的時候,以監控記憶體為主要參考

在hbase-site.xml配置檔案中配置項為hbase.regionserver.handle.count

Region大小設定

配置項hbase.hregion.max.filesize,所屬配置檔案為hbase-site.xml,預設大小是256m。

在當前RegionServer上單個Region的最大儲存空間,單個Region超過該值時,這個Region會被自動split成更小的Region。小Region對split和compaction友好,因為拆分Region或compact小Region裡的StoreFile速度非常快,記憶體佔用低。缺點是split和compaction會很頻繁,特別是數量較多的小Region不同的split,compaction,會導致叢集響應時間波動很大,Region數量太多不僅給管理上帶來麻煩,設定會引起一些HBase個bug。一般 512M 以下的都算小 Region。大 Region 則不太適合經常 split 和 compaction,因為做一次 compact 和 split 會產生較長時間的停頓,對應用的讀寫效能衝擊非常大。

此外,大 Region 意味著較大的 StoreFile,compaction 時對記憶體也是一個挑戰。如果你的應用場景中,某個時間點的訪問量較低,那麼在此時做 compact 和 split,既能順利完成 split 和 compaction,又能保證絕大多數時間平穩的讀寫效能。compaction 是無法避免的,split 可以從自動調整為手動。只要通過將這個引數值調大到某個很難達到的值,比如 100G,就可以間接禁用自動 split(RegionServer 不會對未到達 100G 的 Region 做 split)。再配合 RegionSplitter 這個工具,在需要 split 時,手動 split。手動 split 在靈活性和穩定性上比起自動 split 要高很多,而且管理成本增加不多,比較推薦 online 實時系統使用。記憶體方面,小 Region 在設定 memstore 的大小值上比較靈活,大 Region 則過大過小都不行,過大會導致 flush 時 app 的 IO wait 增高,過小則因 StoreFile 過多影響讀效能。

作者:digger30 連結:https://www.jianshu.com/p/1dbf52073132 來源:簡書 簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。