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 過多影響讀性能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章