大数据集群二次开发及调优使用指导(二)-HBase
1 典型业务的调优
1.1 提升写效率
1.1.1 客户端相关配置
在往HBase写入数据时,可以调整客户端的相关参数来提高写入的效率。
参数说明
参数 | 描述 | 默认值 | 调优建议 |
Put List | 客户端调用的一个API接口,使用该接口,可以批量进行Put操作。 | - | 如果需要执行Put的操作非常频繁,建议使用该接口来执行导入数据。 |
1.1.2 Memstore相关配置
参数 | 描述 | 默认值 | 调优建议 |
hbase.hregion.memstore.flush.size | 在RegionServer中,当写操作内存中存在超过memstore.flush.size大小的memstore,则MemStoreFlusher就启动flush操作将该memstore以hfile的形式写入对应的store中。 | 128M | 如果RegionServer的内存充足,而且活跃Region数量也不是很多的时候,可以适当增大该值,可以减少compaction的次数,有助于提升系统性能。 这种flush产生的时候,并不是紧急的flush,flush操作可能会有一定延迟,在延迟期间,写操作还可以进行,Memstore还会继续增大,最大值 = “memstore.flush.size” * “hbase.hregion.memstore.block.multiplier”。 当超过最大值时,将会阻塞写操作。适当增大“hbase.hregion.memstore.block.multiplier”可以减少阻塞,减少性能波动。 |
hbase.regionserver.global.memstore.size | RegionServer中,负责flush操作的是MemStoreFlusher线程。该线程定期检查写操作内存,当写操作占用内存总量达到阈值,MemStoreFlusher将启动flush操作,按照从大到小的顺序,flush若干相对较大的memstore,直到所占用内存小于阈值。 阈值 = “hbase.regionserver.global.memstore.size” * “hbase.regionserver.global.memstore.size.lower.limit” * “HBase_HEAPSIZE” | 0.4 | 该配置与“hfile.block.cache.size”的和不能超过0.8,也就是写和读操作的内存不能超过HeapSize的80%,这样可以保证除读和写外其它操作的正常运行。 |
hbase.hstore.blockingStoreFiles | 在region flush前首先判断file文件个数,是否大于hbase.hstore.blockingStoreFiles。 如果大于需要先compation 并且让flush延时90s(这个值可以通过hbase.hstore.blockingWaitTime进行配置),在延时过程中,将会继续写从而使得Memstore还会继续增大超过阈值(“memstore.flush.size” * “hbase.hregion.memstore.block.multiplier”),导致写操作阻塞。当完成compation后,可能就会产生大量写入。这样就导致性能激烈震荡。 | 15 | 增加hbase.hstore.blockingStoreFiles,可以减低BLOCK几率。 |
1.1.3 HFile相关配置
可以对Hfile的相关配置型进行调整来提高写入效率。
参数 | 描述 | 默认值 | 调优建议 |
hbase.regionserver.hfile.durable.sync | 控制HFile文件在写入到HDFS时的同步程度。如果为true,HDFS在把数据写入到硬盘后才返回;如果为false,HDFS在把数据写入OS的缓存后就返回。 | true | 把该值设置为false比true在写入性能上会更优。 |
1.1.4 Compaction相关配置
Compact会大大降低写入的性能,但是Compact本身对于HBase是不可或缺的过程,可以通过调整相关的参数来控制Compact的触发条件。
参数 | 描述 | 默认值 | 调优建议 |
hbase.regionserver.thread.compaction.throttle | 控制一次Minor Compaction时,进行compation的文件总大小的阈值。 | 1.5G | Compaction时的文件总大小会影响这一次compaction的执行时间,如果太大,可能会阻塞其它的compaction或flush操作。 |
hbase.hstore.compaction.min | 当一个Store中文件超过该值时,会进行compact。 | 6 | 适当增大该值,可以减少文件被重复执行compaction。但是如果过大,会导致Store中文件数过多而影响读取的性能 |
hbase.hstore.compaction.max | 控制一次compaction操作时的文件数量的最大值。 | 10 | 与“hbase.hstore.compaction.max.size”的作用基本相同,主要是控制一次compaction操作的时间不要太长。 |
hbase.hstore.compaction.max.size | 如果一个HFile文件的大小大于该值,那么在Minor Compaction操作中不会选择这个文件进行compaction操作,除非进行Major Compaction操作。 | 2.5G | 这个值可以防止较大的HFile参与compaction操作。在禁止Major Compaction后,一个Store中可能存在几个HFile,而不会合并成为一个HFile,这样不会对数据读取造成太大的性能影响。 |
hbase.hregion.majorcompaction | 由于执行Major Compaction会占用较多的系统资源,如果正在处于系统繁忙时期,会影响系统的性能。 | 604800000 | 如果业务没有较多的更新、删除、回收过期数据空间时,建议设置为0,以禁止Major Compaction。 如果必须要执行Major Compaction,以回收更多的空间,可以适当增加该值,同时配置参数“hbase.offpeak.end.hour”和“hbase.offpeak.start.hour”以控制Major Compaction发生在业务空闲的时期。 |
1.1.5 HLog相关配置
RegionServer上有一个 Write-ahead Log (以下简称WAL),数据会持续的默认写到这个文件中。它包含了所有已经提交到RS的,已经保留在memstore中但是尚未flush到storefile的数据编辑历史。在数据写入的过程中,默认也会将所有的相关操作同步到WAL里面,可以调整相关参数来提高写入速度。
参数 | 描述 | 默认值 | 调优建议 |
hbase.regionserver.wal.durable.sync | 控制HLog文件在写入到HDFS时的同步程度。如果为true,HDFS在把数据写入到硬盘后才返回;如果为false,HDFS在把数据写入OS的缓存后就返回。 | true | 把该值设置为false比true在写入性能上会更优。 |
setWriteToWAL | 在执行Put的时候可以指定是否将这条数据写入时同步到WAL里面。 | true | 如果对数据写入的速度要求极高,并且可以接受HBase节点出现异常后的数据丢失,可以把这个关闭,可以极大地提高写入速度。 |
1.1.6 表设计相关配置
参数 | 描述 | 默认值 | 调优建议 |
COMPRESSION | 配置数据的压缩算法,这里的压缩是HFile中Block级别的压缩。对于可以压缩的数据,配置压缩算法可以有效减少磁盘的IO,从而达到提高性能的目的。 | None | 并非所有数据都可以进行有效压缩。例如一张图片的数据,因为图片一般已经是压缩后的数据,所以压缩效果有限。推荐使用SNAPPY,因为它有较好的Encoding/Decoding速度和可以接受的压缩率。 Eg: create 'test_table',{NAME => 'cf1', COMPRESSION => 'SNAPPY'} |
BLOCKSIZE | 配置HFile中Block块的大小,不同的Block块大小,可以影响HBase读写数据的效率。越大的Block块,配合压缩算法,压缩的效率就越好;但是由于HBase的读取数据是以Blcok块为单位的,所以越大的Block块,对于随机读的情况,性能可能会比较差。 | 64K | 如果要提升写入的性能,一般扩大到128KB或者256KB,可以提升写数据的效率,也不会影响太大的随机读性能。 Eg: create 'test_table',{NAME => 'cf1', BLOCKSIZE => '32768'} |
IN_MEMORY | 配置这个表的数据优先缓存在内存中,这样可以有效提升读取的性能。 | false | 对于一些小表,而且需要频繁进行读取操作的,可以设置此配置项。 Eg: create 'test_table',{NAME => 'cf1', IN_MEMORY => 'true'} |
1.2 提升读效率
1.2.1 客户端相关配置
在使用客户端读取HBase的数据时,可以通过在代码使用上进行配置和优化,做到读取速度的提高。
参数 | 描述 | 默认值 | 调优建议 |
hbase.client.scanner.caching | 客户端默认缓存的数据大小,调用Scanner.next的时候会先从缓存中取数据,如果缓存中数据取完后才向regionserver进行scan请求。 | 100(条) | 增大该值可以提高客户端读取数据的速度,并且大大降低对regionserver的请求个数。 |
hbase.client.scanner.max.result.size | client请求rs上每次返回结果的最大大小。 | 2MB | 可以增大该数值来增加每次请求regionserver上得到数据量,从而降低到regionserver的请求。 |
1.2.2 缓存相关配置
在RegionServer端可以配置Block的缓存区大小,一定程度提高查询效率。
参数 | 描述 | 默认值 | 调优建议 |
hfile.block.cache.size | HBase 缓存区大小,主要影响查询性能。根据查询模式以及查询记录分布情况来决定缓存区的大小。 | 0.25 | 如果采用随机查询使得缓存区的命中率较低,此时缓存区的性价比其实并不高,这种情况下可以适当降低缓存区大小。 |
1.2.3 HDFS相关配置
参数 | 描述 | 默认值 | 调优建议 |
dfs.client.read.shortcircuit | 是否启动shortcircuit读功能。HDFS shortcircuit读允许直接读HDFS的DataNode。 | true | 把该值设置为true比false在读取性能上会更优。 |
1.3 其他常用配置参数调整
1.3.1 WAL split
当HBase中的某一个RegionServer意外故障或者HMaster重启时,在HMaster侧会进行WAL文件的split,当集群中单个RegionServer的负载比较高(region个数太多)或者访问HDFS比较缓慢时,会影响WAL split的速度,甚至失败。
参数说明
参数 | 描述 | 默认值 | 调优建议 |
hbase.splitlog.manager.timeout | HMaster在执行分布式WAL split的时候,会在ZK上创建和发布task,之后所有的Worker会抢占此task再执行,此参数控制hmaster在Worker抢占task后执行WAL split的超时时间,如果超时,将重新发布task。 | 600000ms | 如果集群中的region个数比较多,或者访问和写入HDFS的速度缓慢,可适当调整此参数来保证WAL split能够正常完成。 |
hbase.regionserver.hlog.splitlog.writer.threads | 在Worker执行WAL split的task的时候,会对该WAL文件相关的所有region分别创建rocover-edit文件,此参数控制同时写入HDFS的线程个数。 | 3 | 如果集群中的region个数特别多,需要保证WAL split的速度(如果WAL split太慢会直接导致hmaster失败),可以适当地加大此线程数。但是如果当前HDFS上的负载已经很高,加大此参数并不能改善WAL split的速度。 |
2 二次开发业务应用指导
2.1 RowKey设计
Rowkey作用:
l 每个Key值被用来唯一的识别一行记录。
l 用来快速的检索一条用户数据。
l 用户数据是基于Key值全局排序的。
设计Rowkey考虑因素:
l 用户最有价值/频率最高的查询场景是基于哪个字段进行的。
l 查询时是否需要按照某个字段进行排序。
l 被选定作为RowKey的字段,是否能够唯一的识别一行记录。
2.2 预分区
默认情况下,在创建HBase表的时候会自动创建一个region分区,当导入数据的时候,所有的HBase客户端都向这一个region写数据,直到这个region足够大了才进行切分。一种可以加快批量写入速度的方法是通过预先创建一些空的regions,这样当数据写入HBase时,会按照region分区情况,在集群内做数据的负载均衡。
Region预分的目标:
1. 在表数据量不断增长的情况下,Region自动分裂期间会有很短暂的时间该Region不能提供读写服务。因此,预分Region可以尽量减少或避免在线系统的Region自动分裂。
2. 提高数据写入性能。如果采用BulkLoad方式进行数据导入时,Reduce的个数等于用户表的Region个数(主索引的Region个数+二级索引的Region个数)。Reduce的个数也很大的影响着BulkLoad的性能。如果采用Java接口进行实时数据的写入,Region分布在多个物理节点上也可以提高写入性能。
3. 提高数据读取性能。每个Region管理的数据是根据Rowkey范围确定的,因此该范围内的数据读取则必然经过该Region,因此当该多个Rowkey预分成多个Region之后,通过该Rowkey读取请求则可以由多台机器节点来分担,从而提高读取性能。
4. 使得数据尽可能的均匀分布在各个Region中,从而使读写请求能够比较均匀的分布在各个物理节点上。