Hbase万亿级存储性能优化总结:配置项、hdfs、zookeeper、jvm参数等
背景
hbase主集群在生產(chǎn)環(huán)境已穩(wěn)定運(yùn)行有1年半時(shí)間,最大的單表region數(shù)已達(dá)7200多個(gè),每天新增入庫量就有百億條,對(duì)hbase的認(rèn)識(shí)經(jīng)歷了懵懂到熟的過程。為了應(yīng)對(duì)業(yè)務(wù)數(shù)據(jù)的壓力,hbase入庫也由最初的單機(jī)多線程升級(jí)為有容災(zāi)機(jī)制的分布式入庫,為及早發(fā)現(xiàn)集群中的問題,還開發(fā)了一套對(duì)hbase集群服務(wù)和應(yīng)用全面監(jiān)控的報(bào)警系統(tǒng)。總結(jié)下hbase優(yōu)化(針對(duì)0.94版本)方面的一些經(jīng)驗(yàn)也算對(duì)這兩年hbase工作的一個(gè)描述。服務(wù)端
1.hbase.regionserver.handler.count:rpc請(qǐng)求的線程數(shù)量,默認(rèn)值是10,生產(chǎn)環(huán)境建議使用100,也不是越大越好,特別是當(dāng)請(qǐng)求內(nèi)容很大的時(shí)候,比如scan/put幾M的數(shù)據(jù),會(huì)占用過多的內(nèi)存,有可能導(dǎo)致頻繁的GC,甚至出現(xiàn)內(nèi)存溢出。
2.hbase.master.distributed.log.splitting:默認(rèn)值為true,建議設(shè)為false。關(guān)閉hbase的分布式日志切割,在log需要replay時(shí),由master來負(fù)責(zé)重放
3.hbase.regionserver.hlog.splitlog.writer.threads:默認(rèn)值是3,建議設(shè)為10,日志切割所用的線程數(shù)
4.hbase.snapshot.enabled:快照功能,默認(rèn)是false(不開啟),建議設(shè)為true,特別是對(duì)某些關(guān)鍵的表,定時(shí)用快照做備份是一個(gè)不錯(cuò)的選擇。
5.hbase.hregion.max.filesize:默認(rèn)是10G, 如果任何一個(gè)column familiy里的StoreFile超過這個(gè)值, 那么這個(gè)Region會(huì)一分為二,因?yàn)閞egion分裂會(huì)有短暫的region下線時(shí)間(通常在5s以內(nèi)),為減少對(duì)業(yè)務(wù)端的影響,建議手動(dòng)定時(shí)分裂,可以設(shè)置為60G。
6.hbase.hregion.majorcompaction:hbase的region主合并的間隔時(shí)間,默認(rèn)為1天,建議設(shè)置為0,禁止自動(dòng)的major主合并,major合并會(huì)把一個(gè)store下所有的storefile重寫為一個(gè)storefile文件,在合并過程中還會(huì)把有刪除標(biāo)識(shí)的數(shù)據(jù)刪除,在生產(chǎn)集群中,主合并能持續(xù)數(shù)小時(shí)之久,為減少對(duì)業(yè)務(wù)的影響,建議在業(yè)務(wù)低峰期進(jìn)行手動(dòng)或者通過腳本或者api定期進(jìn)行major合并。
7.hbase.hregion.memstore.flush.size:默認(rèn)值128M,單位字節(jié),一旦有memstore超過該值將被flush,如果regionserver的jvm內(nèi)存比較充足(16G以上),可以調(diào)整為256M。
8.hbase.hregion.memstore.block.multiplier:默認(rèn)值2,如果一個(gè)memstore的內(nèi)存大小已經(jīng)超過hbase.hregion.memstore.flush.size * hbase.hregion.memstore.block.multiplier,則會(huì)阻塞該memstore的寫操作,為避免阻塞,建議設(shè)置為5,如果太大,則會(huì)有OOM的風(fēng)險(xiǎn)。如果在regionserver日志中出現(xiàn)"Blocking updates for ‘’ on region : memstore size <多少M(fèi)> is >= than blocking <多少M(fèi)> size"的信息時(shí),說明這個(gè)值該調(diào)整了。
9.hbase.hstore.compaction.min:默認(rèn)值為3,如果任何一個(gè)store里的storefile總數(shù)超過該值,會(huì)觸發(fā)默認(rèn)的合并操作,可以設(shè)置5~8,在手動(dòng)的定期major compact中進(jìn)行storefile文件的合并,減少合并的次數(shù),不過這會(huì)延長合并的時(shí)間,以前的對(duì)應(yīng)參數(shù)為hbase.hstore.compactionThreshold。
10.hbase.hstore.compaction.max:默認(rèn)值為10,一次最多合并多少個(gè)storefile,避免OOM。
11.hbase.hstore.blockingStoreFiles:默認(rèn)為7,如果任何一個(gè)store(非.META.表里的store)的storefile的文件數(shù)大于該值,則在flush memstore前先進(jìn)行split或者compact,同時(shí)把該region添加到flushQueue,延時(shí)刷新,這期間會(huì)阻塞寫操作直到compact完成或者超過hbase.hstore.blockingWaitTime(默認(rèn)90s)配置的時(shí)間,可以設(shè)置為30,避免memstore不及時(shí)flush。當(dāng)regionserver運(yùn)行日志中出現(xiàn)大量的“Region has too many store files; delaying flush up to 90000ms"時(shí),說明這個(gè)值需要調(diào)整了
12.hbase.regionserver.global.memstore.upperLimit:默認(rèn)值0.4,regionserver所有memstore占用內(nèi)存在總內(nèi)存中的upper比例,當(dāng)達(dá)到該值,則會(huì)從整個(gè)regionserver中找出最需要flush的region進(jìn)行flush,直到總內(nèi)存比例降到該數(shù)以下,采用默認(rèn)值即可。
13.hbase.regionserver.global.memstore.lowerLimit:默認(rèn)值0.35,采用默認(rèn)值即可。
14.hbase.regionserver.thread.compaction.small:默認(rèn)值為1,regionserver做Minor Compaction時(shí)線程池里線程數(shù)目,可以設(shè)置為5。
15.hbase.regionserver.thread.compaction.large:默認(rèn)值為1,regionserver做Major Compaction時(shí)線程池里線程數(shù)目,可以設(shè)置為8。
16.hbase.regionserver.lease.period:默認(rèn)值60000(60s),客戶端連接regionserver的租約超時(shí)時(shí)間,客戶端必須在這個(gè)時(shí)間內(nèi)匯報(bào),否則則認(rèn)為客戶端已死掉。這個(gè)最好根據(jù)實(shí)際業(yè)務(wù)情況進(jìn)行調(diào)整
17.hfile.block.cache.size:默認(rèn)值0.25,regionserver的block cache的內(nèi)存大小限制,在偏向讀的業(yè)務(wù)中,可以適當(dāng)調(diào)大該值,需要注意的是hbase.regionserver.global.memstore.upperLimit的值和hfile.block.cache.size的值之和必須小于0.8。
18.dfs.socket.timeout:默認(rèn)值60000(60s),建議根據(jù)實(shí)際regionserver的日志監(jiān)控發(fā)現(xiàn)了異常進(jìn)行合理的設(shè)置,比如我們?cè)O(shè)為900000,這個(gè)參數(shù)的修改需要同時(shí)更改hdfs-site.xml
19.dfs.datanode.socket.write.timeout:默認(rèn)480000(480s),有時(shí)regionserver做合并時(shí),可能會(huì)出現(xiàn)datanode寫超時(shí)的情況,480000 millis timeout while waiting for channel to be ready for write,這個(gè)參數(shù)的修改需要同時(shí)更改hdfs-site.xml
jvm和垃圾收集參數(shù):
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"
由于我們服務(wù)器內(nèi)存較大(96G),我們給一部分regionserver的jvm內(nèi)存開到64G,到現(xiàn)在為止,還沒有發(fā)生過一次full gc,hbase在內(nèi)存使用控制方面確實(shí)下了不少功夫,比如各種blockcache的實(shí)現(xiàn),細(xì)心的同學(xué)可以看源碼。
Client端
1.hbase.client.write.buffer:默認(rèn)為2M,寫緩存大小,推薦設(shè)置為5M,單位是字節(jié),當(dāng)然越大占用的內(nèi)存越多,此外測(cè)試過設(shè)為10M下的入庫性能,反而沒有5M好
2.hbase.client.pause:默認(rèn)是1000(1s),如果你希望低延時(shí)的讀或者寫,建議設(shè)為200,這個(gè)值通常用于失敗重試,region尋找等
3.hbase.client.retries.number:默認(rèn)值是10,客戶端最多重試次數(shù),可以設(shè)為11,結(jié)合上面的參數(shù),共重試時(shí)間71s
4.hbase.ipc.client.tcpnodelay:默認(rèn)是false,建議設(shè)為true,關(guān)閉消息緩沖
5.hbase.client.scanner.caching:scan緩存,默認(rèn)為1,避免占用過多的client和rs的內(nèi)存,一般1000以內(nèi)合理,如果一條數(shù)據(jù)太大,則應(yīng)該設(shè)置一個(gè)較小的值,通常是設(shè)置業(yè)務(wù)需求的一次查詢的數(shù)據(jù)條數(shù)
如果是掃描數(shù)據(jù)對(duì)下次查詢沒有幫助,則可以設(shè)置scan的setCacheBlocks為false,避免使用緩存;
6.table用完需關(guān)閉,關(guān)閉scanner
7.限定掃描范圍:指定列簇或者指定要查詢的列,指定startRow和endRow
8.使用Filter可大量減少網(wǎng)絡(luò)消耗
9.通過java多線程入庫和查詢,并控制超時(shí)時(shí)間。后面會(huì)共享下我的hbase單機(jī)多線程入庫的代碼
10.建表注意事項(xiàng):
開啟壓縮
合理的設(shè)計(jì)rowkey
進(jìn)行預(yù)分區(qū)
開啟bloomfilter
zookeeper調(diào)優(yōu)
1.zookeeper.session.timeout:默認(rèn)值3分鐘,不可配置太短,避免session超時(shí),hbase停止服務(wù),線上生產(chǎn)環(huán)境由于配置為1分鐘,如果太長,當(dāng)regionserver掛掉,zk還得等待這個(gè)超時(shí)時(shí)間(已有patch修復(fù)),從而導(dǎo)致master不能及時(shí)對(duì)region進(jìn)行遷移。
2.zookeeper數(shù)量:建議5個(gè)或者7個(gè)節(jié)點(diǎn)。給每個(gè)zookeeper 4G左右的內(nèi)存,最好有獨(dú)立的磁盤。
3.hbase.zookeeper.property.maxClientCnxns:zk的最大連接數(shù),默認(rèn)為300,無需調(diào)整。
4.設(shè)置操作系統(tǒng)的swappiness為0,則在物理內(nèi)存不夠的情況下才會(huì)使用交換分區(qū),避免GC回收時(shí)會(huì)花費(fèi)更多的時(shí)間,當(dāng)超過zk的session超時(shí)時(shí)間則會(huì)出現(xiàn)regionserver宕機(jī)的誤報(bào)
hdfs調(diào)優(yōu)
1.dfs.name.dir:namenode的數(shù)據(jù)存放地址,可以配置多個(gè),位于不同的磁盤并配置一個(gè)nfs遠(yuǎn)程文件系統(tǒng),這樣namenode的數(shù)據(jù)可以有多個(gè)備份
2.dfs.namenode.handler.count:namenode節(jié)點(diǎn)RPC的處理線程數(shù),默認(rèn)為10,可以設(shè)置為60
3.dfs.datanode.handler.count:datanode節(jié)點(diǎn)RPC的處理線程數(shù),默認(rèn)為3,可以設(shè)置為30
4.dfs.datanode.max.xcievers:datanode同時(shí)處理文件的上限,默認(rèn)為256,可以設(shè)置為8192
其它
列族名、column名、rowkey均會(huì)存儲(chǔ)到hfile中,因此這幾項(xiàng)在設(shè)計(jì)表結(jié)構(gòu)時(shí)都盡量短些
regionserver的region數(shù)量不要過1000,過多的region會(huì)導(dǎo)致產(chǎn)生很多memstore,可能會(huì)導(dǎo)致內(nèi)存溢出,也會(huì)增加major compact的耗時(shí)
轉(zhuǎn)載請(qǐng)注明原文鏈接:http://blog.csdn.net/odailidong/article/details/41794403
總結(jié)
以上是生活随笔為你收集整理的Hbase万亿级存储性能优化总结:配置项、hdfs、zookeeper、jvm参数等的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hbase 预写日志WAL处理源码分析之
- 下一篇: ZooKeeper在HBase集群中的作