hbase优化 读写速度
hbase集群优化主要从 hdfs、hbase服务端配置、客户端配置、gc部分、hbase硬件设备配置几部分进行优化。
点击查看隐藏内容🎁
25 HDFS优化部分
HBase是基于hdfs文件系统的一个数据库,其数据最终是写到hdfs中的,因此涉及hdfs调优的部分也是必不可少的。
(1)dfs.replication.interval:默认3秒
可以调高,避免hdfs频繁备份,从而提高吞吐率。
(2)dfs.datanode.handler.count:默认为10
可以调高这个处理线程数,使得写数据更快
(3)dfs.namenode.handler.count:默认为8
(4)dfs.datanode.socket.write.timeout:默认480秒
并发写数据量大的时候可以调高一些,
(5)dfs.socket.timeout:最好也要调高,默认的很小。
-- dfs.datanode.handler.count=64
-- dfs.namenode.handler.count=256
HDFS其它相关配置
dfs.datanode.max.transfer.threads=12288
dfs.namenode.service.handler.count=256
同上,可以调高,提高整体速度与性能。
26 HBase服务端配置
(1) zookeeper.session.timeout(默认3分钟)
ZK的超期参数,默认配置为3分钟,在生产环境上建议减小这个值在1分钟或更小。
设置原则:这个值越小,当RS故障时Hmaster获知越快,Hlog分裂和region 部署越快,集群恢复时间越短。 但是,设置这个值得原则是留足够的时间进行GC回收,否则会导致频繁的RS宕机。一般就做默认即可
(2)hbase.regionserver.handler.count(默认10)
对于大负载的put(达到了M范围)或是大范围的Scan操作,handler数目不易过大,易造成OOM。 对于小负载的put或是get,delete等操作,handler数要适当调大。根据上面的原则,要看我们的业务的情况来设置。(具体情况具体分析)。
(3)HBASE_HEAPSIZE(hbase-env.sh中配置)
我的前两篇文章Memstoresize40%(默认) blockcache 20%(默认)就是依据这个而成的,总体HBase内存配置。设到机器内存的1/2即可。
(4)选择使用压缩算法,目前HBase默认支持的压缩算法包括GZ,LZO以及snappy(hbase-site.xml中配置)
(5)hbase.hregion.max.filesize默认256M
上面说过了,hbase自动拆分region的阈值,可以设大或者无限大,无限大需要手动拆分region,懒的人别这样。
(6)hbase.hregion.memstore.flush.size
单个region内所有的memstore大小总和超过指定值时,flush该region的所有memstore。
(7)hbase.hstore.blockingStoreFiles 默认值:7
说明:在flush时,当一个region中的Store(CoulmnFamily)内有超过7个storefile时,则block所有的写请求进行compaction,以减少storefile数量。
调优:block写请求会严重影响当前regionServer的响应时间,但过多的storefile也会影响读性能。从实际应用来看,为了获取较平滑的响应时间,可将值设为无限大。如果能容忍响应时间出现较大的波峰波谷,那么默认或根据自身场景调整即可。
(8)hbase.hregion.memstore.block.multiplier默认值:2
说明:当一个region里总的memstore占用内存大小超过hbase.hregion.memstore.flush.size两倍的大小时,block该region的所有请求,进行flush,释放内存。
虽然我们设置了region所占用的memstores总内存大小,比如64M,但想象一下,在最后63.9M的时候,我Put了一个200M的数据,此时memstore的大小会瞬间暴涨到超过预期的hbase.hregion.memstore.flush.size的几倍。这个参数的作用是当memstore的大小增至超过hbase.hregion.memstore.flush.size 2倍时,block所有请求,遏制风险进一步扩大。
调优: 这个参数的默认值还是比较靠谱的。如果你预估你的正常应用场景(不包括异常)不会出现突发写或写的量可控,那么保持默认值即可。如果正常情况下,你的写请求量就会经常暴长到正常的几倍,那么你应该调大这个倍数并调整其他参数值,比如hfile.block.cache.size和hbase.regionserver.global.memstore.upperLimit/lowerLimit,以预留更多内存,防止HBase server OOM。
(9)hbase.regionserver.global.memstore.upperLimit:默认40%
当ReigonServer内所有region的memstores所占用内存总和达到heap的40%时,HBase会强制block所有的更新并flush这些region以释放所有memstore占用的内存。
hbase.regionserver.global.memstore.lowerLimit:默认35%
同upperLimit,只不过lowerLimit在所有region的memstores所占用内存达到Heap的35%时,不flush所有的memstore。它会找一个memstore内存占用最大的region,做个别flush,此时写更新还是会被block。lowerLimit算是一个在所有region强制flush导致性能降低前的补救措施。在日志中,表现为 “** Flushthread woke up with memory above low water.”。
调优:这是一个Heap内存保护参数,默认值已经能适用大多数场景。
(10)hfile.block.cache.size:默认20%
这是涉及hbase读取文件的主要配置,BlockCache主要提供给读使用。读请求先到memstore中查数据,查不到就到blockcache中查,再查不到就会到磁盘上读,并把读的结果放入blockcache。由于blockcache是一个LRU,因此blockcache达到上限(heapsize * hfile.block.cache.size)后,会启动淘汰机制,淘汰掉最老的一批数据。对于注重读响应时间的系统,应该将blockcache设大些,比如设置blockcache=0.4,memstore=0.39,这会加大缓存命中率。
(11)hbase.regionserver.hlog.blocksize和hbase.regionserver.maxlogs
之所以把这两个值放在一起,是因为WAL的最大值由hbase.regionserver.maxlogs*hbase.regionserver.hlog.blocksize (2GB by default)决定。一旦达到这个值,Memstore flush就会被触发。所以,当你增加Memstore的大小以及调整其他的Memstore的设置项时,你也需要去调整HLog的配置项。否则,WAL的大小限制可能会首先被触发,因而,你将利用不到其他专门为Memstore而设计的优化。抛开这些不说,通过WAL限制来触发Memstore的flush并非最佳方式,这样做可能会会一次flush很多Region,尽管“写数据”是很好的分布于整个集群,进而很有可能会引发flush“大风暴”。
提示:最好将hbase.regionserver.hlog.blocksize* hbase.regionserver.maxlogs 设置为稍微大于hbase.regionserver.global.memstore.lowerLimit* HBASE_HEAPSIZE。
应用层响应配置
响应配置的优化能够提升HBase服务端的处理性能,一般情况下默认配置都是无法满足高并发需求的。
hbase.master.handler.count=256: Master处理客户端请求最大线程数
hbase.regionserver.handler.count=256: RS处理客户端请求最大线程数
说明:如果设置小了,高并发的情况下,应用层将会收到HBase服务端抛出的无法创建新线程的异常从而导致应用层线程阻塞。
hbase.client.retries.number=3
hbase.rpc.timeout=5000
说明:默认值太大了,一旦应用层连接不上HBse服务端将会进行近乎无限的重试,从而导致线程堆积应用假死等,影响比较严重,可以适当减少。
hbase.hstore.blockingStoreFiles=100: storefile个数达到该值则block写入
说明:线上该参数可以调大一些,不然hfile达到指定数量时就会block等到compact。
配置汇总
RegionServer JavaHeap堆栈大小: 40G
hbase.hregion.max.filesize=30G
hbase.hregion.memstore.flush.size=256M
hbase.hregion.memstore.block.multiplier=3
hbase.regionserver.global.memstore.upperLimit=0.6
hbase.regionserver.global.memstore.lowerLimit=0.55
hbase.bucketcache.size=64 * 1024M
hbase.bucketcache.ioengine=offheap
hbase.bucketcache.percentage.in.combinedcache=0.9
hfile.block.cache.size=0.15
hbase.master.handler.count=256
hbase.regionserver.handler.count=256
hbase.client.retries.number=3
hbase.rpc.timeout=5000
hbase.hstore.blockingStoreFiles=100
这里只给出相对比较重要的配置,其余参数视情况参考文档说明
27 客户端优化
27.1 HBase客户端
hbase-env.sh 的 HBase 客户端环境高级配置代码段
配置了G1垃圾回收器和其他相关属性
-XX:+UseG1GC
-XX:InitiatingHeapOccupancyPercent=65
-XX:-ResizePLAB
-XX:MaxGCPauseMillis=90
-XX:+UnlockDiagnosticVMOptions
-XX:+G1SummarizeConcMark
-XX:+ParallelRefProcEnabled
-XX:G1HeapRegionSize=32m
-XX:G1HeapWastePercent=20
-XX:ConcGCThreads=4
-XX:ParallelGCThreads=16
-XX:MaxTenuringThreshold=1
-XX:G1MixedGCCountTarget=64
-XX:+UnlockExperimentalVMOptions
-XX:G1NewSizePercent=2
-XX:G1OldCSetRegionThresholdPercent=5
27.2 其它
(1)用户在编写程序入库时,HBase的自动刷写是默认开启的,即用户每一次put都会提交到HBase server进行一次刷写,如果需要高速插入数据,则会造成I/O负载过重。在这里可以关闭自动刷写功能,setAutoFlush(false)。如此,put实例会先写到一个缓存中,这个缓存的大小通过hbase.client.write.buffer这个值来设定缓存区,当缓存区被填满之后才会被送出。如果想要显示刷写数据,可以调用flushCommits()方法。
此处引申:采取这个方法要估算服务器端内存占用则可以:hbase.client.write.buffer*hbase.regionserver.handler.count得出内存情况。
(2)第二个方法,是关闭每次put上的WAL(writeToWAL(flase))这样可以刷写数据前,不需要预写日志,但是如果数据重要的话建议不要关闭。
(3)hbase.client.scanner.caching:默认为1
这是设计客户端读取数据的配置调优,在hbase-site.xml中进行配置,代表scanner一次缓存多少数据(从服务器一次抓取多少数据来scan)默认的太小,但是对于大文件,值不应太大。
(4)hbase.regionserver.lease.period默认值:60000
说明:客户端租用HRegion server 期限,即超时阀值。
调优:这个配合hbase.client.scanner.caching使用,如果内存够大,但是取出较多数据后计算过程较长,可能超过这个阈值,适当可设置较长的响应时间以防被认为宕机。
28 GC 优化
参考 hbase GC怎样优化