天天看點

Hbase萬億級存儲性能優化總結

背景

      hbase主叢集在生産環境已穩定運作有1年半時間,最大的單表region數已達7200多個,每天新增入庫量就有百億條,對hbase的認識經曆了懵懂到熟的過程。為了應對業務資料的壓力,hbase入庫也由最初的單機多線程更新為有容災機制的分布式入庫,為及早發現叢集中的問題,還開發了一套對hbase叢集服務和應用全面監控的報警系統。總結下hbase優化(針對0.94版本)方面的一些經驗也算對這兩年hbase工作的一個描述。

服務端

1.hbase.regionserver.handler.count:rpc請求的線程數量,預設值是10,生産環境建議使用100,也不是越大越好,特别是當請求内容很大的時候,比如scan/put幾M的資料,會占用過多的記憶體,有可能導緻頻繁的GC,甚至出現記憶體溢出。

2.hbase.master.distributed.log.splitting:預設值為true,建議設為false。關閉hbase的分布式日志切割,在log需要replay時,由master來負責重放

3.hbase.regionserver.hlog.splitlog.writer.threads:預設值是3,建議設為10,日志切割所用的線程數

4.hbase.snapshot.enabled:快照功能,預設是false(不開啟),建議設為true,特别是對某些關鍵的表,定時用快照做備份是一個不錯的選擇。

5.hbase.hregion.max.filesize:預設是10G, 如果任何一個column familiy裡的StoreFile超過這個值, 那麼這個Region會一分為二,因為region分裂會有短暫的region下線時間(通常在5s以内),為減少對業務端的影響,建議手動定時分裂,可以設定為60G。

6.hbase.hregion.majorcompaction:hbase的region主合并的間隔時間,預設為1天,建議設定為0,禁止自動的major主合并,major合并會把一個store下所有的storefile重寫為一個storefile檔案,在合并過程中還會把有删除辨別的資料删除,在生産叢集中,主合并能持續數小時之久,為減少對業務的影響,建議在業務低峰期進行手動或者通過腳本或者api定期進行major合并。

7.hbase.hregion.memstore.flush.size:預設值128M,機關位元組,一旦有memstore超過該值将被flush,如果regionserver的jvm記憶體比較充足(16G以上),可以調整為256M。

8.hbase.hregion.memstore.block.multiplier:預設值2,如果一個memstore的記憶體大小已經超過hbase.hregion.memstore.flush.size *  hbase.hregion.memstore.block.multiplier,則會阻塞該memstore的寫操作,為避免阻塞,建議設定為5,如果太大,則會有OOM的風險。如果在regionserver日志中出現"Blocking updates for '<threadName>' on region <regionName> : memstore size <多少M> is >= than blocking <多少M> size"的資訊時,說明這個值該調整了。

9.hbase.hstore.compaction.min:預設值為3,如果任何一個store裡的storefile總數超過該值,會觸發預設的合并操作,可以設定5~8,在手動的定期major compact中進行storefile檔案的合并,減少合并的次數,不過這會延長合并的時間,以前的對應參數為hbase.hstore.compactionThreshold。

10.hbase.hstore.compaction.max:預設值為10,一次最多合并多少個storefile,避免OOM。

11.hbase.hstore.blockingStoreFiles:預設為7,如果任何一個store(非.META.表裡的store)的storefile的檔案數大于該值,則在flush memstore前先進行split或者compact,同時把該region添加到flushQueue,延時重新整理,這期間會阻塞寫操作直到compact完成或者超過hbase.hstore.blockingWaitTime(預設90s)配置的時間,可以設定為30,避免memstore不及時flush。當regionserver運作日志中出現大量的“Region <regionName> has too many store files; delaying flush up to 90000ms"時,說明這個值需要調整了

12.hbase.regionserver.global.memstore.upperLimit:預設值0.4,regionserver所有memstore占用記憶體在總記憶體中的upper比例,當達到該值,則會從整個regionserver中找出最需要flush的region進行flush,直到總記憶體比例降到該數以下,采用預設值即可。

13.hbase.regionserver.global.memstore.lowerLimit:預設值0.35,采用預設值即可。

14.hbase.regionserver.thread.compaction.small:預設值為1,regionserver做Minor Compaction時線程池裡線程數目,可以設定為5。

15.hbase.regionserver.thread.compaction.large:預設值為1,regionserver做Major Compaction時線程池裡線程數目,可以設定為8。

16.hbase.regionserver.lease.period:預設值60000(60s),用戶端連接配接regionserver的租約逾時時間,用戶端必須在這個時間内彙報,否則則認為用戶端已死掉。這個最好根據實際業務情況進行調整

17.hfile.block.cache.size:預設值0.25,regionserver的block cache的記憶體大小限制,在偏向讀的業務中,可以适當調大該值,需要注意的是hbase.regionserver.global.memstore.upperLimit的值和hfile.block.cache.size的值之和必須小于0.8。

18.dfs.socket.timeout:預設值60000(60s),建議根據實際regionserver的日志監控發現了異常進行合理的設定,比如我們設為900000,這個參數的修改需要同時更改hdfs-site.xml

19.dfs.datanode.socket.write.timeout:預設480000(480s),有時regionserver做合并時,可能會出現datanode寫逾時的情況,480000 millis timeout while waiting for channel to be ready for write,這個參數的修改需要同時更改hdfs-site.xml

jvm和垃圾收集參數:

export HBASE_REGIONSERVER_OPTS="-Xms36g -Xmx36g -Xmn1g -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=15 -XX:CMSInitiatingOccupancyFraction=70 -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/data/logs/gc-$(hostname)-hbase.log"

由于我們伺服器記憶體較大(96G),我們給一部分regionserver的jvm記憶體開到64G,到現在為止,還沒有發生過一次full gc,hbase在記憶體使用控制方面确實下了不少功夫,比如各種blockcache的實作,細心的同學可以看源碼。

Client端

1.hbase.client.write.buffer:預設為2M,寫緩存大小,推薦設定為5M,機關是位元組,當然越大占用的記憶體越多,此外測試過設為10M下的入庫性能,反而沒有5M好

2.hbase.client.pause:預設是1000(1s),如果你希望低延時的讀或者寫,建議設為200,這個值通常用于失敗重試,region尋找等

3.hbase.client.retries.number:預設值是10,用戶端最多重試次數,可以設為11,結合上面的參數,共重試時間71s

4.hbase.ipc.client.tcpnodelay:預設是false,建議設為true,關閉消息緩沖

5.hbase.client.scanner.caching:scan緩存,預設為1,避免占用過多的client和rs的記憶體,一般1000以内合理,如果一條資料太大,則應該設定一個較小的值,通常是設定業務需求的一次查詢的資料條數 

如果是掃描資料對下次查詢沒有幫助,則可以設定scan的setCacheBlocks為false,避免使用緩存;

6.table用完需關閉,關閉scanner

7.限定掃描範圍:指定列簇或者指定要查詢的列,指定startRow和endRow

8.使用Filter可大量減少網絡消耗

9.通過java多線程入庫和查詢,并控制逾時時間。後面會共享下我的hbase單機多線程入庫的代碼

10.建表注意事項:

開啟壓縮

合理的設計rowkey

進行預分區

開啟bloomfilter

zookeeper調優

1.zookeeper.session.timeout:預設值3分鐘,不可配置太短,避免session逾時,hbase停止服務,線上生産環境由于配置為1分鐘,如果太長,當regionserver挂掉,zk還得等待這個逾時時間(已有patch修複),進而導緻master不能及時對region進行遷移。

2.zookeeper數量:建議5個或者7個節點。給每個zookeeper 4G左右的記憶體,最好有獨立的磁盤。

3.hbase.zookeeper.property.maxClientCnxns:zk的最大連接配接數,預設為300,無需調整。

4.設定作業系統的swappiness為0,則在實體記憶體不夠的情況下才會使用交換分區,避免GC回收時會花費更多的時間,當超過zk的session逾時時間則會出現regionserver當機的誤報

hdfs調優

1.dfs.name.dir:namenode的資料存放位址,可以配置多個,位于不同的磁盤并配置一個nfs遠端檔案系統,這樣namenode的資料可以有多個備份

2.dfs.namenode.handler.count:namenode節點RPC的處理線程數,預設為10,可以設定為60

3.dfs.datanode.handler.count:datanode節點RPC的處理線程數,預設為3,可以設定為30

4.dfs.datanode.max.xcievers:datanode同時處理檔案的上限,預設為256,可以設定為8192

其它

列族名、column名、rowkey均會存儲到hfile中,是以這幾項在設計表結構時都盡量短些

regionserver的region數量不要過1000,過多的region會導緻産生很多memstore,可能會導緻記憶體溢出,也會增加major compact的耗時

轉載請注明原文連結:http://blog.csdn.net/odailidong/article/details/41794403