一:hbase现有硬件资源的理论性能
1.集群容量规划公式:
优化调整,发挥硬件的最大优势;
Disk Size / Java Heap=RegionSize / MemstoreSize * ReplicationFactor * HeapFractionForMemstore *2
按照默认配置,
- RegionSize = 10G,对应参数为hbase.hregion.max.filesize;
- MemstoreSize = 128M,对应参数为hbase.hregion.memstore.flush.size;
- ReplicationFactor = 3,对应参数为dfs.replication;
- HeapFractionForMemstore = 0.4,对应参数为hbase.regionserver.global.memstore.lowerLimit;
推导公式;
- 硬盘容量纬度下Region个数:
Disk Size / (RegionSize * ReplicationFactor) - Java Heap纬度下Region个数:
Java Heap * HeapFractionForMemstore / (MemstoreSize / 2 )
Disk Size / (RegionSize * ReplicationFactor) = Java Heap * HeapFractionForMemstore / (MemstoreSize / 2 )
=> Disk Size / Java Heap = RegionSize / MemstoreSize * ReplicationFactor * HeapFractionForMemstore * 2
2.hbase对于cpu要求高,越多core越好
3.软硬件独立的hbase集群
其他硬件配置,
- 集群使用万兆网卡(千兆对于大数据集群来说实在太小,很容易打满,影响较大),
- 磁盘尽可能大,
- 内存不用太高,一般128G就已经特别多了HBase本身对内存的需求并不是配的越大越好。
- CPU核数越多越好,HBase本身压缩数据、compaction线程等都是很吃CPU资源的。
二:hbase现集群调优参数
属 性 值 | cdh集群现有 | 集群效果 |
---|---|---|
hbase.hstore.blockingStoreFiles | 100 | HStore的storeFile的文件数大于配置值, |
则在flush memstore前先进行split或者compact, | ||
除非超过 | ||
hbase.hstore.blockingWaitTime配置的时间, | ||
默认为7,可调大,比如:100, | ||
避免memstore不及时flush,当写入量大时, | ||
触发memstore的block,从而阻塞写操作。 | ||
cachecompress | FALSE | 开启cache的压缩, |
50% increase in throughput | ||
and 30% improvement in mean latency while, | ||
increasing garbage collection by 80% | ||
and increasing overall CPU load by 2% | ||
hbase.regionserver.thread.compaction.small | 5 | 压缩的线程数,增加压缩性能。 |
hbase.hregion.memstore.flush.size | 256 | 当前系统flush比较频繁,并且内存资源比较充足, |
可以适当将该值调整为256M。避免频繁的flush | ||
hbase.hstore.compactionThreshold | 5 | 有五个store file就触发compact操作, |
减少压缩队列。 | ||
HBase HRegion 最大化压缩 | 0 | 禁止自动大合并(时间长,耗费资源), |
hbase.hregion.majorcompaction | 业务低峰期进行手动合并。 | |
GC-region server配置(JDK1.7) | -XX:+UseG1GC | G1日志打印: |
-XX:MaxGCPauseMillis=100 | -verbose:gc | |
-XX:InitiatingHeapOccupancyPercent=70 | -XX:+PrintGC | |
-XX:G1HeapRegionSize=16m | -XX:+PrintGCDetails | |
-XX:+ParallelRefProcEnabled | -XX:+PrintGCApplicationStoppedTime | |
-XX:+UnlockExperimentalVMOptions | -XX:+PrintHeapAtGC | |
-XX:-ResizePLAB | -XX:+PrintGCDateStamps | |
-XX:+PrintAdaptiveSizePolicy | ||
-XX:+PrintTenuringDistribution | ||
-XX:+PrintSafepointStatistics | ||
-XX:PrintSafepointStatisticsCount=1 | ||
-XX:PrintFLSStatistics=1 | ||
zookeeper.session.timeout | 120000 | 加大zk超时时间,防止其他意外导致超时 |
hbase.bucketcache.ioengine | 现在用blockcache,0.6 | 降低了JVM GC对业务请求的实际影响 |
hbase.regionserver.maxlogs | 32 | region flush的触发条件之一, |
计算方法: | wal日志文件总数超过该阈值就会强制执行flush操作。该默认值对于很多集群来说太小 | |
maxLogs = | ||
HEAP_SIZE * memstoreRatio * 2/ LogRollSize | ||
hbase.hregion.max.filesize | 10G | 会进行region的切分; |
改进: | ||
手动进行split,调一个每天的数据量不可能达到、 | ||
定时器万一失灵也不会造成麻烦的值。 | ||
100G的文件split大约需要1小时的时间 | ||
hbase.hregion.memstore.mslab.enabled | TRUE | 减少因内存碎片导致的Full GC,提高整体性能。 |
hbase.regionserver.handler.count | 200 | 特别是当请求内容很大的时候, |
比如scan/put几M的数据,会占用过多的内存, | ||
有可能导致频繁的GC,甚至出现内存溢出。 |
hbase参数名 | 现有值 | 描述说明建议 |
---|---|---|
zookeeper.session.timeout | 120000 | RegionServer与Zookeeper间的连接超时时间。 |
超时时间到后,ReigonServer会被Zookeeper从RS集群清单中移除, | ||
HMaster收到移除通知后,会对这台server负责的regions重新balance, | ||
让其他存活的RegionServer接管. | ||
这个timeout决定了RegionServer是否能够及时的failover。 | ||
设置成1分钟或更低,可以减少因等待超时而被延长的failover时间。 | ||
不过需要注意的是,对于一些Online应用, | ||
RegionServer从宕机到恢复时间本身就很短的(网络闪断,crash等故障,运维可快速介入),如果调低timeout时间,反而会得不偿失。 | ||
因为当ReigonServer被正式从RS集群中移除时,HMaster就开始做balance了(让其他RS根据故障机器记录的WAL日志进行恢复)。 | ||
当故障的RS在人工介入恢复后,这个balance动作是毫无意义的,反而会使负载不均匀,给RS带来更多负担。特别是那些固定分配regions的场景。 | ||
推荐:120000 | ||
参考:http://hbase.apache.org/1.2/book.html#trouble.rs.runtime.zkexpired | ||
HDFS 服务 | HDFS | 此 HBase 服务实例依赖的 HDFS 服务的名称 |
ZooKeeper 服务 | Zookeeper | 此 HBase 服务实例依赖的 ZooKeeper 服务的名称。 |
hbase.master.handler.count | 200 | HBase Master 中启动的 RPC 服务器实例数量; |
Master处理事务的线程数,如果Master十分繁忙或者Region Server数很多时,可以适当增大该值。 | ||
经验法则是根据集群的约为负载,在每个请求的有效负载较大时保持低值,并在有效负载较小时保持高值。 | ||
hbase.regionserver.handler.count | 200 | 这个参数的调优与内存息息相关。 |
较少的IO线程,适用于处理单次请求内存消耗较高的Big PUT场景(大容量单次PUT或设置了较大cache的scan,均属于Big PUT)或ReigonServer的内存比较紧张的场景。 | ||
较多的IO线程,适用于单次请求内存消耗低,TPS要求非常高的场景。设置该值的时候,以监控内存为主要参考。设置太多适得其反。 | ||
这里需要注意的是如果server的region数量很少,大量的请求都落在一个region上,因快速充满memstore触发flush导致的读写锁会影响全局TPS,不是IO线程数越高越好。 | ||
压测时,开启Enabling RPC-level logging,可以同时监控每次请求的内存消耗和GC的状况,最后通过多次压测结果来合理调节IO线程数。 | ||
这里是一个案例?Hadoop and HBase Optimization for Read Intensive Search Applications,作者在SSD的机器上设置IO线程数为100,仅供参考。 | ||
经验法则是在每个请求的有效负载较大时保持低值,并在有效负载较小时保持高值。 将hbase.regionserver.handler.count增加到大约为区域服务器上的CPU数量的值 | ||
建议: | ||
从cpu*2开始调整, | ||
hbase.regionserver.global.memstore.upperLimit, | 0.2 | 根据实际业务集群的读写比例来设置。 |
hbase.regionserver.global.memstore.size | ||
hbase.hregion.memstore.flush.size | 256M | 如 memstore 大小超过此值(字节数),Memstore 将刷新到磁盘。通过运行由 hbase.server.thread.wakefrequency 指定的频率的线程检查此值。 |
在集群内存足够的情况下。增大,针对刷数据频繁操作。 | ||
hbase.hstore.compactionThreshold | 5 | 当store中文件数超过该阈值就会触发compaction。通常建议生产线上写入qps较高的系统调高此值 |
建议: | ||
太大的compact需要足够的内存来记录压缩期间的所有更新,减少compact次数,增加compact时间,影响读数据。如果太大,客户端在压缩期间会超时。 | ||
hbase.hstore.blockingStoreFiles | 100 | HStore的storeFile的文件数大于配置值,则在flush memstore前先进行split或者compact,除非超过hbase.hstore.blockingWaitTime配置的时间,比如:100,避免memstore不及时flush,当写入量大时,触发memstore的block,从而阻塞写操作。 |
参考: | ||
http://hbase.apache.org/1.2/book.html#hbase.hstore.blockingStoreFiles | ||
hbase.hstore.compaction.max | 10 | 一次minicompact选取的最大store file数量,设置太大则会有更多的storefile进入compact中,一般情况,默认值够用。 |
建议:默认值。 | ||
hbase.hregion.majorcompaction | 0 | 禁用hbase的自动compact,在低峰期进行手动compact操作。 |
hfile.block.cache.size | 0.6 | 根据集群读写业务设置比例 |
dfs.client.hedged.read.threadpool.size | 16 | 通常,为每个读请求生成一个线程。 |
然而,如果Hedged Reads被启用, | ||
那么客户端等待了一些可配置的时间后, | ||
如果读取没有返回,则客户端会生成第二个读取请求, | ||
去读取相同数据的不同块备份。 | ||
首先返回的读取结果会被使用,另一个读取请求将被丢弃。 | ||
Hedged reads 对于一个由错误的磁盘或脆弱的网络连接造成的罕见的慢读,很有帮助。 | ||
dfs.client.hedged.read.threshold.millis - 在生成第二个读取线程前等待的毫秒数。 | ||
专用于服务Hedged Reads的线程数。如果被设置成 0 (默认值), hedged reads被禁用 | ||
建议: | ||
线程池大小可以与读handler的数目相同, | ||
而超时阈值不适宜调整的太小,否则会对集群和客户端都增加压力。 | ||
使用以下度量方式调整集群上Hedged Reads的设置。 | ||
参考 HBase Metrics 获取更多信息。 | ||
hedgedReadOps - Hedged Read线程被触发的次数。 | ||
这可能表明读取请求通常很慢,或者被触发的读取速度太快。 | ||
hedgeReadOpsWin - Hedged Read 线程快于原有读取线程的次数。这可能表明给定的RegionServer(原有读取线程要读取的数据所在的RegionServer)在请求的服务上有问题。 | ||
hbase.regionserver.thread.compaction.small | 5 | 完成minicompact的线程数,增大可以加快Mini compact |
建议:5 | ||
hbase.ipc.server.read.threadpool.size | 200 | 读取 RegionServer HBase IPC Server 使用的线程池大小。 |
hbase.ipc.server.read.threadpool.size是用来把前端请求放到队列中的参数,HADOOP系统内部都是通过RPC框架来请求资源的。默认这个参数应该是10, | ||
建议; | ||
10个够不够,还是不知道,看整体并发,监控metric:numActiveHandler 解释:Number of active rpc handlers. 如果这个值经常满,那么就需要增加。 | ||
Region Mover 线程 | 5 | 向 RegionServer 加载region或从中卸载region要使用的线程数。可用于提高解除或滚动重新启动操作的速度 |
建议: | ||
比默认值适当增大,加快region移动速度。 | ||
抑制参数验证:HBase HRegion Major Compaction | RegionServer Default Group | 是否抑制 HBase HRegion Major Compaction 参数的内置参数验证产生的配置警告。 |
HBase Region Server 刷新队列监控阈值 | 20 | 刷新队列阈值 |
HBase RegionServer 的 Java 堆栈大小(字节) | 23.12G | Java最大内存。 |
建议一:初始通过fullgc之后,年老代内存的3到4倍设置 | ||
建议二:通过观察线上gc监控,判断内存高峰期使用情况,修改内存。 | ||
hbase-site.xml 的 HBase 服务高级配置代码段(安全阀) | hbase.block.data.cachecompressed:false | cache是否启用压缩; |
enabling this feature with SNAPPY compression has been | ||
shown to result in 50% increase in throughput and 30% improvement in mean latency while, | ||
increasing garbage collection by 80% | ||
and increasing overall CPU load by 2%. | ||
建议: | ||
当前关闭cache压缩;(由于之前开启导致cpu上升) | ||
客户端 Java 配置选项 | -XX:+HeapDumpOnOutOfMemoryError -XX:+UseG1GC -Djava.net.preferIPv4Stack=true | 基于jdk1.7.0_80 |
HBase REST Server 的 Java 配置选项 | -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled | 基于jdk1.7.0_80 |
HBase Thrift Server 的 Java 配置选项 | -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled | 基于jdk1.7.0_80 |
HBase Master 的 Java 配置选项 | -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled | 基于jdk1.7.0_80 |
HBase RegionServer 的 Java 配置选项 | -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:InitiatingHeapOccupancyPercent=70 -XX:G1HeapRegionSize=16m -XX:+ParallelRefProcEnabled -XX:+UnlockExperimentalVMOptions -XX:-ResizePLAB | 基于jdk1.7.0_80,通过观察具体高峰期gc情况优化; |
GC参数: | ||
-Xmx50g | ||
-XX:+UseG1GC | ||
-XX:+UnlockExperimentalVMOptions | ||
-XX:MaxGCPauseMillis=100 | ||
-XX:InitiatingHeapOccupancyPercent=65 | ||
-XX:+ParallelRefProcEnabled | ||
-XX:MaxTenuringThreshold=1 | ||
-XX:G1HeapRegionSize=16m | ||
GC日志打印添加参数: | ||
-verbose:gc | ||
-XX:+PrintGC | ||
-XX:+PrintGCDetails | ||
-XX:+PrintGCApplicationStoppedTime | ||
-XX:+PrintHeapAtGC | ||
-XX:+PrintGCDateStamps | ||
-XX:+PrintAdaptiveSizePolicy | ||
-XX:+PrintTenuringDistribution | ||
-XX:+PrintSafepointStatistics | ||
-XX:PrintSafepointStatisticsCount=1 | ||
-XX:PrintFLSStatistics=1 | ||
-XX:+HeapDumpOnOutOfMemoryError | ||
-XX:HeapDumpPath=path |
三:根据实际场景的hbase优化;
1.冷热数据
现有业务:数据更新频繁;冷数据;
基于数据更新频繁,blockcache比例减少;如果数据不频,开启blockcache同时使用bucketcache,减少blockcache比例,设置bucketcache;.
2.数据get 、scan操作
- 现有业务:get操作比较多;
- scan操作少
- 用来表设计参考;
3.数据读写比例
- 现有业务:hbase数据读大于写
- 根据业务调整memstore、blockcache或者bucketcache比例;
- 设置数据的compact队列及flush队列参数,预防队列过大,调整性能;
4.数据的版本、过期时间、bloom filter、表设计
原则:尽量在表结构设计就考虑性能问题,而不是通过设置参数在调整
- version:根据业务,具体调整数据版本version应该几个?
- TTL,MINVERSION根据数据使用调整数据过期时间TTL;及数据最小版本号minversion;
- bloom filter:根据数据的使用场景设计bloom filter:行级布隆过滤器,因为它在额外的空间开销和利用过滤存储文件提升性能之间取得了更好的平衡。设置数据bllomfilter的开启及设计;
- IN_MEMORY属性;可以将meta表设置为true;
- 设置rowkey、column长度越短越好,数据定义规则
- 针对get与scan频繁的字段:尽量使常用查询的域放入ROWKEY(最重要的放在前面,然后依次拼接),合理设置rowkey,
- 尽量高表使用,通常比宽表性能高50%以上;
- hbase建表预分区;
- 行记录:建议多行存储(不是去增加一个列),更好的get及scan性能,太长的行记录不易region的split
5.gc优化:
GC参数:
-Xmx50g
-Xms50g
-XX:+UseG1GC
-XX:+UnlockExperimentalVMOptions
-XX:MaxGCPauseMillis={50/90/500} for SSD/HDD/offline cluster
-XX:G1NewSizePercent={2/5} for normal/heavy load cluster
-XX:InitiatingHeapOccupancyPercent=65
-XX:+ParallelRefProcEnabled
-XX:MaxTenuringThreshold=1
-XX:G1HeapRegionSize=16m
GC日志打印添加参数:
-verbose:gc
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintHeapAtGC
-XX:+PrintGCDateStamps
-XX:+PrintAdaptiveSizePolicy
-XX:+PrintTenuringDistribution
-XX:+PrintSafepointStatistics
-XX:PrintSafepointStatisticsCount=1
-XX:PrintFLSStatistics=1
6.hbase读优化客户端
- scan.setcaching :
大scan场景下将scan缓存从100增大到500或者1000,用以减少RPC次数 - scan.setbatch
每次请求返回的列数 - scan:
指定列族、startrow、endrow、filter - get :
多get请求采用批量请求;get请求可以指定列族及列; - scan.setBlockCache(false):
如果离线批量读取请求的话;否则会从cache挤出其他热点数据; - filter
优先使用keyfilter,而不是valuefilter - cache
使用redis等缓存系统
7.hbase写性能问题:
- HBase理论平均写延时 < 10ms,时间复杂度O(1)
- 没有可用的handler响应
- 考虑增加handler数目或硬件资源
- 更常见的情况是95%-99%的写入都很快,但有些 写入非常慢,甚至上万倍,一般问题在服务端:
- 写入Memstore慢
- HLog写入超时——考虑HDFS及硬盘异常
- GC——考虑优化内存使用(GC参数及算法调优有限)
- Flush慢
- HFile写入超时——考虑HDFS及硬盘异常
- Compaction被触发且运行时间长——优化高峰期Compaction 策略
- 写入Memstore慢
8.hbase 客户端缓存元数据
- 客户端自己发现自己的缓存是错的,再去拿新meta信息后重试;hbase客户端使用重试的方式解决这个问题,本地有缓存的情况下
- 按照缓存直接访问hregionserver
- regionserver报regionnot online异常
- 客户端知道了我访问错了
- 客户端去取meta
- 客户端更新缓存,拿到正确地址
- 客户端使用正确地址
网友评论