HBase讀寫性能優化


一個系統上線之后,開發和調優將會一直伴隨在系統的整個生命周期中,HBase也不例外。下面我們要學習如何進行HBase讀寫性能調優,以獲取最大的讀寫效率。

HBase寫入優化
客戶端優化
批量寫
采用批量寫,可以減少客戶端到RegionServer之間的RPC的次數,提高寫入性能。批量寫請求要么全部成功返回,要么拋出異常。

HTable.put(List<Put>);


異步批量提交
如果業務可以接受異常情況下丟失少量數據,可以使用異步批量提交方式提交請求。

用戶提交寫請求之后,數據會先寫入客戶端緩存,並返回用戶寫入成功(此時數據並為提交到RegionServer),當客戶端緩存達到閾值(默認2M,可通過hbase.client.write.buffer配置)時才會批量提交給RegionServer。需要注意的是,在某些情況下客戶端異常的情況下緩存數據有可能丟失。

HTable.setWriteBufferSize(writeBufferSize); // 設置緩存大小
HTable.setAutoFlush(false);


多線程並發寫
客戶端開啟多個HTable寫線程,每個寫線程負責一個HTable對象的flush操作,這樣結合定時flush和寫buffer,可以即保證在數據量小的時候,數據可以在較短時間內被flush,同時又保證在數據量大的時候,寫buffer一滿就即使進行flush。

使用BulkLoad寫入
在HBase中數據都是以HFile形式保存在HDFS中的,當有大量數據需要寫入到HBase的時候,可以采用BulkLoad方式完成。

使用MapReduce或者Spark直接生成HFile格式的數據文件,然后再通過RegionServer將HFile數據文件移動到相應的Region上去。

寫數據表設計調優
COMPRESSION
配置數據的壓縮算法,這里的壓縮是HFile中block級別的壓縮。對於可以壓縮的數據,配置壓縮算法可以有效減少磁盤的IO,從而達到提高性能的目的。但是並不是所有數據都可以進行有效壓縮,如圖片,因為圖片一般是已經壓縮后的數據,所以壓縮效果有限。常用的壓縮算法是SNAPPY,因為它有較好的壓縮和解壓速度和可以接受的壓縮率。

IN_MEMORY
配置表的數據優先緩存在內存中,這樣可以有效提升讀取的性能。適合小表,而且需要頻繁進行讀取操作的。

預分區
在HBase中數據是分布在各個Region中的,每個Region都負責一個起始RowKey和結束Rowkey的范圍,在向HBase中寫數據的時候,會根據RowKey請求到對應的Region上,如果寫請求都集中在某一個Region或某幾個Region上的時候,性能肯定不如寫請求均勻分布在各個Region上好。默認情況下,創建的HBase的只有一個Region分區,會隨着數據量的變大,進行split,拆分成多個Region,最開始的性能肯定會很不好

建議在設計HBase的的時候,進行預分區,並設計一個良好的Rowkey生成規則(關於RowKey設計,可以參考《一篇文章帶你快速搞懂HBase RowKey設計》),盡量將數據分散到各個Region上,那樣在進行HBase的讀寫的時候,對性能會有很好的改善。

合理設置WAL存儲級別
數據在寫入HBase的時候,先寫WAL,再寫入緩存。通常情況下寫緩存延遲很低,WAL機制一方面是為了確保數據即使寫入緩存后數據丟失也可以通過WAL恢復,另一方面是為了集群之間的復制。默認WAL機制是開啟的,並且使用的是同步機制寫WAL。

如果業務不特別關心異常情況下部分數據的丟失,而更關心數據寫入吞吐量,可考慮關閉WAL寫,這樣可以提升2~3倍數據寫入的吞吐量。

如果業務不能接受不寫WAL,但是可以接受WAL異步寫入,這樣可以帶了1~2倍性能提升。

HBase中可以通過設置WAL的持久化等級決定是否開啟WAL機制、以及HLog的落盤方式。

WAL的持久化等級分為如下四個等級:

  1. SKIP_WAL:只寫緩存,不寫HLog日志。這種方式因為只寫內存,因此可以極大的提升寫入性能,但是數據有丟失的風險。在實際應用過程中並不建議設置此等級,除非確認不要求數據的可靠性。
  2. ASYNC_WAL:異步將數據寫入HLog日志中。
  3. SYNC_WAL:同步將數據寫入日志文件中,需要注意的是數據只是被寫入文件系統中,並沒有真正落盤,默認。
  4. FSYNC_WAL:同步將數據寫入日志文件並強制落盤。最嚴格的日志寫入等級,可以保證數據不會丟失,但是性能相對比較差。

同樣,除了在創建表的時候直接設置WAL存儲級別,也可以通過客戶端設置WAL持久化等級,代碼:

put.setDurability(Durability.SYNC_WAL);


HBase讀取優化
客戶端優化
批量get請求
使用批量請求,可以減少RPC的次數,顯著提高吞吐量。需要注意的是,批量get請求要么成功返回所有請求數據,要么拋出異常。

Result[] re= table.get(List<Get> gets);


合理設置scan緩存大小
一次scan可能會返回大量數據,但是實際客戶端發起一次scan請求,並不會將所有數據一次性加載到本地,而是分成多次RPC請求進行加載,這樣設計一方面是因為大量數據請求可能會導致網絡帶寬嚴重消耗進而影響其他業務,另一方面是有可能因為數據量太大導致客戶端發生OOM。所以采用先加載一部分數據到本地,然后進行遍歷,每次加載一部分數據,如此往復,直至所有數據加載完成。數據加載到本地就存放在scan緩存中,默認100。

增大scan的緩存,可以讓客戶端減少一次scan的RPC次數,從而從整體上提升數據讀取的效率。

scan.setCaching(int caching); //大scan可以設置為1000


指定請求列族或者列名
HBase是列族數據庫,同一列族的數據存儲在一塊,不同列族是分開存儲的,如果一個表由多個列族,只是根據RowKey而不指定列族進行檢索的話,不同列族的數據需要獨立進行檢索,性能必然會比指定列族的查詢差的多。

此外指定請求的列的話,不需要將整個列族的所有列的數據返回,這樣就減少了網路IO。

scan.addColumn();


設置只讀Rowkey過濾器
在只需要Rowkey數據時,可以為Scan添加一個只讀取Rowkey的filter(FirstKeyOnlyFilter或KeyOnlyFilter)。

關閉ResultScanner
在使用table.getScanner之后,記得關閉,否則它會和服務器端一直保持連接,資源無法釋放,從而導致服務端的某些資源不可用。

scanner.close();


離線計算訪問HBase建議禁用緩存
當離線訪問HBase時,往往會對HBase表進行掃描,此時讀取的數據沒有必要存放在BlockCache中,否則會降低掃描的效率。

scan.setBlockCache(false);
建議在對HBase表進行掃描時禁用緩存。

對於頻繁查詢HBase的應用場景不需要禁用緩存,並且可以考慮在應用程序和HBase之間加一層緩存系統(如Redis),先查詢緩存,緩存沒有命中再去查詢HBase。

讀數據表設計調優
COMPRESSION
同寫性能優化COMPRESSION部分。

BLOCKSIZE
配置HFile中block塊的大小,不同的block大小,可以影響HBase讀寫數據的效率。越大的block塊,配置壓縮算法,壓縮的效率就越好;但是由於HBase的讀取數據時以block塊為單位的,所以越大的block塊,對於隨機讀的情況,性能可能會比較差,如果要提升寫入的性能,一般擴大到128kb或者256kb,可以提升寫數據的效率,也不會影響太大的隨機讀性能。

DATA_BLOCK_ENCODING
配置HFile中block塊的編碼方法。當一行數據中存在多個列時,一般可以配置為"FAST_DIFF",可以有效的節省數據存儲的空間,從而提升性能。

BloomFilter
優化原理:BloomFilter主要用來過濾不存在待檢索RowKey或者Row-Col的HFile文件,避免無用的IO操作。它會告訴你在這個HFile文件中是否可能存在待檢索的KeyValue,如果不存在,就可以不用小號IO打開文件進行seek。通過設置BloomFilter可以提升讀寫的性能。

BloomFilter是一個列族級別的配置屬性,如果列族設置了BloomFilter,那么HBase會在生成StoreFile時包含一份BloomFilter的結構的數據,稱為MetaBlock(一旦寫入就無法更新)。MetaBlock和DataBlock(真實的KeyValue數據)一起由LRUBlockCache維護,所以開啟了BloomFilter會有一定的存儲即內存cache開銷。

HBase利用BloomFilter可以節省必須讀磁盤過程,可以提高隨機讀(get)的性能,但是對於順序讀(scan)而言,設置BloomFilter是沒有作用的(0.92版本以后,如果設置了BloomFilter為ROWCOL,對於執行了qualifier的scan有一定的優化)

BloomFilter取值有兩個,ROW和ROWCOL,需要根據業務來確定具體使用哪種。

  • 如果業務大多數隨機查詢僅僅使用row作為查詢條件,BloomFilter一定要設置為ROW。
  • 如果大多數隨機查詢使用row+col作為查詢條件,BloomFilter需要設置為ROWCOL。
  • 如果不確定業務查詢類型,設置為ROW。‘

預分區
同寫性能優化預分區部分。

HBase服務端調優
GC_OPTS
HBase是利用內存完成讀寫操作。提高HBase內存可以有效提高HBase性能。GC_OPTS主要需要調整HeapSize和NewSize的大小。調整HeapSize大小的時候,建議將Xms和Xmx設置成相同的值,這樣可以避免JVM動態調整HeapSize大小的時候影響性能。調整NewSize大小的時候,建議把其設置為HeapSize大小的1/9。

當HBase集群規模越大,Region數量越多時,可以適當調大HMaster的GC_OPTS參數

RegionServer需要比HMaster更大的內存,在內存充足的情況下,HeapSize可以相對設置大一些。

HMaster的HeapSize為4G的時候,HBase集群可以支持100000個Region的規模。根據經驗值,單個RegionServer的HeapSize不建議超過20GB。

  1. # HMaster、RegionServer GC_OPTS配置如下:
  2. HMaster: -Xms2G -Xmx2G -XX:NewSize=256M -XX:MaxNewSize=256M
  3. RegionServer: -Xms4G -Xmx4G -XX:NewSize=512M -XX:MaxNewSize=512M

RegionServer並發請求處理數量
hbase.regionserver.handler.count表示RegionServer在同一時刻能夠並發處理多少請求。如果設置過高會導致激烈的線程競爭,如果設置過小,請求將會在RegionServer長時間等待,降低處理能力。應該根據資源情況,適當增加處理線程數。

建議根據CPU的使用情況,可以設置為100至300之間的值。

控制MemStore的大小
hbase.hregion.memstore.flush.size默認值128M,單位字節,一旦有MemStore超過該值將被flush,如果regionserver的jvm內存比較充足(16G以上),可以調整為256M。在內存足夠put負載大情況下可以調整增大。

BlockCache優化
BlockCache作為讀緩存,合理設置對於提高讀性能非常重要。默認情況下,BlockCache和MemStore的配置各占40%,可以根據集群業務進行修正,比如讀多寫少業務可以將BlockCache占比調大。另外BlockCache的策略也很重要,不同策略對讀性能來說影響並不大,但是對GC的影響 卻很顯著。

HBase緩存區大小,主要影響查詢性能。根據查詢模式以及查詢記錄分布情況來決定緩存區的大小。如果采用隨機查詢使得緩存區的命中率較低,可以適當降低緩存大小。

  1. hfile.block.cache.size,默認0.4,用來提高讀性能
  2. hbase.regionserver.global.memstore.size,默認0.4,用來提高寫性能

控制HFile個數
MemStore在flush之前,會進行StoreFile的文件數量校驗(通過hbase.hstore.blockingStoreFiles參數配置),如果大於設定值,系統將會強制執行Compaction操作進行文件合並,在合並的過程中會阻塞MemStore的數據寫入,等待其他線程將StoreFile進行合並。通常情況下發生在數據寫入很快的情況下。

hbase.hstore.compactionThreshold表示啟動Compaction的最低閾值,該值不能太大,否則會積累太多文件,一般建議設置為5~8左右。

hbase.hstore.blockingStoreFiles默認設置為7,可以適當調大一些。

Split優化
hbase.hregion.max.filesize表示HBase中Region的文件總大小的最大值。當Region中的文件大於該參數時,將會導致Region分裂。

  • 如果該參數設置過小時,可能會導致Split操作頻繁
  • 如果該參數設置過大時,會導致Compaction操作需要處理的文件個數增大,影響Compaction執行效率

Compaction優化
hbase.hstore.compaction.min當一個Store中文件超過該值時,會進行Compaction,適當增大該值,可以減少文件被重復執行Compaction。但是如果過大,會導致Store中文件數過多而影響讀取的性能。

hbase.hstore.compaction.max控制一次Compaction操作時的文件數據量的最大值。

hbase.hstore.compaction.max.size如果一個HFile文件的大小大於該值,那么在Minor Compaction操作中不會選擇這個文件進行Compaction操作,除非進行Major Compaction操作。這個值可以防止較大的HFile參與Compaction操作。在禁止Major Compaction后,一個Store中可能存在幾個HFile,而不會合並成為一個HFile,這樣不會對數據讀取造成太大的性能影響。

原則是:盡量要減小Compaction的次數和Compaction的執行時間

總結
在HBase使用過程中,要想獲取好的讀寫性能,可以從以下幾個方面進行優化:

  1. 一個優秀的HBase表列族設置方案,可以參考《帶你快速上手HBase | HBase列族優化》
  2. 一個優秀的HBase RowKey設計方案,可以參考《一篇文章帶你快速搞懂HBase RowKey設計》
  3. 讀寫時客戶端相關配置
  4. HBase服務器優化


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM