hbase优化总结一

[size=medium]来自:
http://blog.youkuaiyun.com/rzhzhz/article/details/7481674


因官方Book Performance Tuning部分章节没有按配置项进行索引,不能达到快速查阅的效果。所以我以配置项驱动,重新整理了原文,并补充一些自己的理解,如有错误,欢迎指正。
配置优化
[b]zookeeper.session.timeout[/b]
默认值:3分钟(180000ms)
说明: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的场景。

[b]hbase.regionserver.handler.count[/b]
默认值:10
说明:RegionServer的请求处理IO线程数。
调优:
这个参数的调优与内存息息相关。
较少的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,仅供参考。
[b]hbase.hregion.max.filesize[/b]
默认值:256M
说明:在当前ReigonServer上单个Reigon的最大存储空间,单个Region超过该值时,这个Region会被自动split成更小的region。
调优:
小region对split和compaction友好,因为拆分region或compact小region里的storefile速度很快,内存占用低。缺点是split和compaction会很频繁。
特别是数量较多的小region不停地split, compaction,会导致集群响应时间波动很大,region数量太多不仅给管理上带来麻烦,甚至会引发一些Hbase的bug。
一般512以下的都算小region。
大region,则不太适合经常split和compaction,因为做一次compact和split会产生较长时间的停顿,对应用的读写性能冲击非常大。此外,大region意味着较大的storefile,compaction时对内存也是一个挑战。
当然,大region也有其用武之地。如果你的应用场景中,某个时间点的访问量较低,那么在此时做compact和split,既能顺利完成split和compaction,又能保证绝大多数时间平稳的读写性能。
既然split和compaction如此影响性能,有没有办法去掉?
compaction是无法避免的,split倒是可以从自动调整为手动。
只要通过将这个参数值调大到某个很难达到的值,比如100G,就可以间接禁用自动split(RegionServer不会对未到达100G的region做split)。
再配合RegionSplitter这个工具,在需要split时,手动split。
手动split在灵活性和稳定性上比起自动split要高很多,相反,管理成本增加不多,比较推荐online实时系统使用。
内存方面,小region在设置memstore的大小值上比较灵活,大region则过大过小都不行,过大会导致flush时app的IO wait增高,过小则因store file过多影响读性能。
[b]hbase.regionserver.global.memstore.upperLimit/lowerLimit[/b]
默认值:0.4/0.35
upperlimit说明:hbase.hregion.memstore.flush.size 这个参数的作用是当单个Region内所有的memstore大小总和超过指定值时,flush该region的所有memstore。RegionServer的flush是通过将请求添加一个队列,模拟生产消费模式来异步处理的。那这里就有一个问题,当队列来不及消费,产生大量积压请求时,可能会导致内存陡增,最坏的情况是触发OOM。
这个参数的作用是防止内存占用过大,当ReigonServer内所有region的memstores所占用内存总和达到heap的40%时,HBase会强制block所有的更新并flush这些region以释放所有memstore占用的内存。
lowerLimit说明: 同upperLimit,只不过lowerLimit在所有region的memstores所占用内存达到Heap的35%时,不flush所有的memstore。它会找一个memstore内存占用最大的region,做个别flush,此时写更新还是会被block。lowerLimit算是一个在所有region强制flush导致性能降低前的补救措施。在日志中,表现为 “** Flush thread woke up with memory above low water.”
调优:这是一个Heap内存保护参数,默认值已经能适用大多数场景。
参数调整会影响读写,如果写的压力大导致经常超过这个阀值,则调小读缓存hfile.block.cache.size增大该阀值,或者Heap余量较多时,不修改读缓存大小。
如果在高压情况下,也没超过这个阀值,那么建议你适当调小这个阀值再做压测,确保触发次数不要太多,然后还有较多Heap余量的时候,调大hfile.block.cache.size提高读性能。
还有一种可能性是?hbase.hregion.memstore.flush.size保持不变,但RS维护了过多的region,要知道 region数量直接影响占用内存的大小。
[b]hfile.block.cache.size[/b]
默认值:0.2
说明:storefile的读缓存占用Heap的大小百分比,0.2表示20%。该值直接影响数据读的性能。
调优:当然是越大越好,如果写比读少很多,开到0.4-0.5也没问题。如果读写较均衡,0.3左右。如果写比读多,果断默认吧。设置这个值的时候,你同时要参考?hbase.regionserver.global.memstore.upperLimit?,该值是memstore占heap的最大百分比,两个参数一个影响读,一个影响写。如果两值加起来超过80-90%,会有OOM的风险,谨慎设置。
[b]hbase.hstore.blockingStoreFiles[/b]
默认值:7
说明:在flush时,当一个region中的Store(Coulmn Family)内有超过7个storefile时,则block所有的写请求进行compaction,以减少storefile数量。
调优:block写请求会严重影响当前regionServer的响应时间,但过多的storefile也会影响读性能。从实际应用来看,为了获取较平滑的响应时间,可将值设为无限大。如果能容忍响应时间出现较大的波峰波谷,那么默认或根据自身场景调整即可。
[b]hbase.hregion.memstore.block.multiplier[/b]
默认值: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。
[b]hbase.hregion.memstore.mslab.enabled[/b]
默认值:true
说明:减少因内存碎片导致的Full GC,提高整体性能。
调优:详见 http://kenwublog.com/avoid-full-gc-in-hbase-using-arena-allocation
其他
启用LZO压缩
LZO对比Hbase默认的GZip,前者性能较高,后者压缩比较高,具体参见?Using LZO Compression 。对于想提高HBase读写性能的开发者,采用LZO是比较好的选择。对于非常在乎存储空间的开发者,则建议保持默认。
不要在一张表里定义太多的Column Family
Hbase目前不能良好的处理超过包含2-3个CF的表。因为某个CF在flush发生时,它邻近的CF也会因关联效应被触发flush,最终导致系统产生更多IO。
批量导入
在批量导入数据到Hbase前,你可以通过预先创建regions,来平衡数据的负载。详见?Table Creation: Pre-Creating Regions
避免CMS concurrent mode failure
HBase使用CMS GC。默认触发GC的时机是当年老代内存达到90%的时候,这个百分比由 -XX:CMSInitiatingOccupancyFraction=N 这个参数来设置。concurrent mode failed发生在这样一个场景:
当年老代内存达到90%的时候,CMS开始进行并发垃圾收集,于此同时,新生代还在迅速不断地晋升对象到年老代。当年老代CMS还未完成并发标记时,年老代满了,悲剧就发生了。CMS因为没内存可用不得不暂停mark,并触发一次stop the world(挂起所有jvm线程),然后采用单线程拷贝方式清理所有垃圾对象。这个过程会非常漫长。为了避免出现concurrent mode failed,建议让GC在未到90%时,就触发。
通过设置?-XX:CMSInitiatingOccupancyFraction=N
这个百分比, 可以简单的这么计算。如果你的?hfile.block.cache.size 和?hbase.regionserver.global.memstore.upperLimit 加起来有60%(默认),那么你可以设置 70-80,一般高10%左右差不多。

[b]hbase.balancer.period[/b]
hbase自身进行balance操作的间隔时间,默认为300000,以依情况而定。也可关闭,通过对region的监控,手动调整region。


[b]hbase.client.pause[/b]
client在写时会进行多次的重试,重试的间隔采用的是指数避让的方法,间隔时间为1秒,即为1000,
在默认10次重试的情况下,就会是这样的间隔时间:[1,1,1,2,2,4,4,8,16,32],
从这可以看出当server出现异常时会导致client长时间的等待,因此可以将client的重试间隔时间调短为20ms


[b]hbase.hregion.max.filesize[/b]
如果region是手动split,建议大小在100G或者更大(设置一个不可达到的值),如果是自动split,建议在1G-2G之间

Hbase客户端优化
[b]AutoFlush[/b]
将HTable的setAutoFlush设为false,可以支持客户端批量更新。即当Put填满客户端flush缓存时,才发送到服务端。
默认是true。
[b]Scan Caching[/b]
scanner一次缓存多少数据来scan(从服务端一次抓多少数据回来scan)。
默认值是 1,一次只取一条。
[b]Scan Attribute Selection[/b]
scan时建议指定需要的Column Family,减少通信量,否则scan操作默认会返回整个row的所有数据(所有Coulmn Family)。
Close ResultScanners
通过scan取完数据后,记得要关闭ResultScanner,否则RegionServer可能会出现问题(对应的Server资源无法释放)。
[b]Optimal Loading of Row Keys[/b]
当你scan一张表的时候,返回结果只需要row key(不需要CF, qualifier,values,timestaps)时,你可以在scan实例中添加一个filterList,并设置 MUST_PASS_ALL操作,filterList中add?FirstKeyOnlyFilter或KeyOnlyFilter。这样可以减少网络通信量。
[b]Turn off WAL on Puts[/b]
当Put某些非重要数据时,你可以设置writeToWAL(false),来进一步提高写性能。writeToWAL(false)会在Put时放弃写WAL log。风险是,当RegionServer宕机时,可能你刚才Put的那些数据会丢失,且无法恢复。
[b]启用Bloom Filter[/b]
Bloom Filter通过空间换时间,提高读操作性能。
最后,感谢嬴北望同学对”hbase.hregion.memstore.flush.size”和“hbase.hstore.blockingStoreFiles”错误观点的修正。
本文转自:http://kenwublog.com/hbase-performance-tuning


提升hbase性能的几个地方(转载)
1、使用bloomfilter和mapfile_index_interval
Bloomfilter(开启/未开启=1/0) mapfile_index_interval Exists(0-10000)/ms Get(10001 - 20000)/ms
0 128 22460 23715
0 0 11897 11416
0 64 13692 14034
1 128 3275 3686
1 64 2961 3010
1 0 3339 3498
测试环境为:单机,规模为10万条数据。随机在10000条数据中有99条存在的情况下。
结论:开启bloomfilter比没开启要快3、4倍。而适当的减少mapfile_index_interval可以提升性能




















注意:在1.9.3版本的hbase中,bloomfilter是不支持的,存在一个bug,可以通过如下的修改加以改正:
(1)、在方法org.apache.hadoop.hbase.regionserver.HStore.createReaders()中,找到如下行
BloomFilterMapFile.Reader reader = file.getReader(fs, false, false);
将其改成
BloomFilterMapFile.Reader reader = file.getReader(fs, this.family.isBloomfilter(), false);
(2)、在方法org.apache.hadoop.hbase.HColumnDescriptor.toString()中,找到如下的代码行
if (key != null && key.toUpperCase().equals(BLOOMFILTER)) {
// Don't emit bloomfilter. Its not working.
continue;
}
将其注释掉

2、hbase对于内存有特别的嗜好,在硬件允许的情况下配足够多的内存给它。
通过修改hbase-env.sh中的
export HBASE_HEAPSIZE=3000 #这里默认为1000m

3、修改java虚拟机属性
(1)、在环境允许的情况下换64位的虚拟机
(2)、替换掉默认的垃圾回收器,因为默认的垃圾回收器在多线程环境下会有更多的wait等待
export HBASE_OPTS="-server -XX:NewSize=6m -XX:MaxNewSize=6m -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode"

4、增大RPC数量
通过修改hbase-site.xml中的
hbase.regionserver.handler.count属性,可以适当的放大。默认值为10有点小

5、做程序开发是注意的地方
(1)、需要判断所求的数据行是否存在时,尽量不要用HTable.exists(final byte [] row) 而用HTable.exists(final byte [] row, final byte[] column)等带列族的方法替代。
(2)、不要使用HTable.get(final byte [] row, final byte [] column) == null来判断所求的数据存在,而是用HTable.exists(final byte [] row, final byte[] column)替代
(3)、HTable.close()方法少用.因为我遇到过一些很令人费解的错误

6、记住HBase是基于列模式的存储,如果一个列族能搞定就不要把它分开成两个,关系数据库的那套在这里很不实用.分成多个列来存储会浪费更多的空间,除非你认为现在的硬盘和白菜一个价。

7、如果数据量没有达到TB级别或者没有上亿条记录,很难发挥HBase的优势,建议换关系数据库或别的存储技术。[/size]
<think>我们正在讨论HBase优化问题的解决方案。根据用户提供的引用和之前的讨论,我们需要整理HBase优化的关键点。用户引用了三处来源: 引用[1]:提到了RegionServer崩溃的问题(未完整给出)以及性能优化些方向。 引用[2]:详细说明了HBase性能优化的策略,包括硬件配置、GC优化、数据分布、分区设计,以及解决性能问题的方法(扩容、参数优化、负载均衡、JVM配置)。 引用[3]:展示了个具体的JVM参数优化例子(GC日志打印和CMS垃圾回收器的设置)。 用户需求是:查找HBase优化问题的解决方案或信息。 因此,我们的回答应围绕HBase性能优化展开,涵盖以下几个方面: 1. 硬件和配置优化(内存、磁盘等) 2. JVM优化(GC设置) 3. 数据设计和负载均衡(RowKey设计、分区设计、避免热点) 4. 参数调优(memstore、块缓存、压缩等) 5. 集群扩展(扩容RegionServer) 6. 使用工具(如YARN) 同时,按照用户要求: - 回答结构清晰,逐步解决问题。 - 使用中文。 - 在引用处添加引用标识,如[^2]。 - 生成相关问题。 注意:引用[1]中关于RegionServer崩溃的问题描述不完整,但我们知道RegionServer崩溃是常见问题,通常与内存不足、GC问题等有关,所以我们在优化中会涵盖这些内容。 另外,用户提供的引用[3]是个具体的JVM参数设置示例,我们可以在JVM优化部分引用。 回答结构建议: 1. 引言:简要说明HBase优化的重要性。 2. 分点列出优化策略,每个策略下给出具体方法和建议。 3. 每点中适当引用用户提供的引用内容。 4. 最后给出总结和相关问题。 由于引用内容有限,我们主要基于引用[2]展开,因为它提供了较全面的优化指南,并补充引用[3]的JVM配置实例。 具体优化点(根据引用[2]): 1. 硬件配置:内存、磁盘。 2. GC优化:调整GC参数,如使用CMS,设置合适的堆大小和GC间隔。 3. 数据分布:避免热点,设计良好的RowKey和分区。 4. 参数优化:memstore大小、块缓存大小、压缩算法等。 5. 负载均衡策略:如随机负载均衡。 6. 扩容:增加RegionServer节点。 我们还将引用[3]的具体JVM参数示例放在GC优化部分。 注意:引用[1]中提到了RegionServer崩溃,但是没有给出具体描述,我们可以将其与GC问题或硬件不足联系起来,在相应的优化部分提及。 最后,生成3-5个相关问题。 </think>### HBase优化问题全面解决方案 以下针对HBase常见性能瓶颈,结合官方最佳实践与生产经验,提供系统性优化方案: --- #### 、硬件与配置优化 1. **内存管理** - **RegionServer堆内存**:推荐设置为集群总内存的70%-80%(如64GB物理内存配45GB堆)[^2] - **块缓存(BlockCache)**:占用堆内存40%,使用BucketCache off-heap模式避免Full GC ```xml <!-- hbase-site.xml --> <property> <name>hfile.block.cache.size</name> <value>0.4</value> <!-- 堆内缓存占比 --> </property> <property> <name>hbase.bucketcache.size</name> <value>40960</value> <!-- 40GB堆外缓存 --> </property> ``` 2. **GC调优** - 启用CMS+ParNew组合,避免STW停顿超过200ms[^3]: ```bash export HBASE_OPTS="$HBASE_OPTS -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70" ``` - 监控GC日志:关注`Full GC`频率,超过1次/小时需扩容内存[^2] --- #### 二、数据模型优化 1. **RowKey设计原则** - **散列热点**:对单调递增RowKey添加哈希前缀,如`MD5(user_id)_timestamp` - **长度控制**:不超过16字节,满足$$ \text{存储效率} \propto \frac{1}{\text{RowKey长度}} $$ 2. **分区均衡** - 预分区避免Region分裂延迟:创建表时指定`SPLITS` ```bash create 'orders', 'cf', {NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'} ``` - 监控`hbase:meta`表,确保Region大小均匀(推荐10-20GB/Region)[^2] --- #### 三、读写性能优化 | **参数** | **优化值** | **作用** | |--------------------|------------------|------------------------------| | hbase.hstore.blockingStoreFiles | 20 | 控制Compaction触发阈值 | | hbase.hregion.memstore.flush.size | 256MB | 降低MemStore刷写IO压力 | | hbase.regionserver.handler.count | 256 | 提升并发请求处理能力 | 1. **写入优化** - 批量写入:使用`Put.setDurability(Durability.SKIP_WAL)`跳过WAL(允许数据丢失场景) - 压缩算法:启用Snappy压缩$$ \text{压缩比} \approx 60\% \sim 80\% $$[^2] ```xml <property> <name>hbase.regionserver.codecs</name> <value>snappy</value> </property> ``` 2. **查询优化** - **布隆过滤器**:对随机读场景启用`ROW`模式 ```java HColumnDescriptor.setBloomFilterType(BloomType.ROW); ``` - **批量Scan**:设置`setCaching(1000)`减少RPC次数 --- #### 四、集群运维优化 1. **水平扩展** - RegionServer数量公式:$$ N = \frac{\text{总数据量}}{\text{单节点内存上限}} \times 1.2 $$ - 添加节点后执行`balance_switch true`触发负载均衡[^2] 2. **监控指标** | **关键指标** | **健康阈值** | **优化动作** | |----------------------------|--------------------|----------------------------| | CompactionQueueSize | < 20 | 增加`hbase.hstore.thread.compaction.large` | | MemStoreSize | < 80%堆内存 | 调低flush.size或扩容内存 | | BlockCacheHitRatio | > 95% | 增大缓存比例 | --- ### 总结优化路径 ```mermaid graph LR A[性能瓶颈分析] --> B{问题类型} B -->|写入慢| C[优化MemStore/WAL] B -->|查询慢| D[调整BlockCache/布隆过滤器] B -->|节点热点| E[RowKey散列+预分区] C --> F[参数调优] D --> G[查询模式改造] E --> H[负载均衡] ``` --- ### 相关问题 1. RegionServer频繁Full GC如何定位和解决? 2. HBase如何实现热点Region的动态分裂与合并? 3. 如何设计RowKey以同时支持范围扫描和高并发写入? 4. HBase与Spark集成时有哪些性能调优关键点? > 建议通过`hbase shell`执行`status 'detailed'`持续监控集群状态,并结合Grafana+Prometheus实现实时指标分析[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值