HBase_HBase自带压测工具PerformanceEvaluation改造与应用实战
1.背景
由于数据产品业务需求增长迅速,各种各样的看数需求和面板被提出,同时低频使用的页面关停并转又不能被各级领导写到汇报ppt中去,那么存量加增量数据看版所需要的HBase存储资源自然就迅速增长。但是在降本增效和技术升级的大背景下,平台也不再对HBase物理集群进行扩容支持,并不断推动物理集群的迁移和下线,推动使用存算分离的HBase容器集群,支持更加快捷的动态扩缩容和灵活的计算存储资源比例。但是部门领导对于存算分离HBase集群的性能存疑,但是想要使用业务请求数据进行压测需要相同的集群规模和等量业务历史数据,数据回溯耗时较长且直接申请与线上集群相同规划的大集群不太现实。那么就需要寻找一种不依赖业务数据的测试方式,能够测试出不同规格或者不同实现架构HBase集群的性能差异,这时我查询资料发现了HBase开源代码中自带了一个压测工具PerformanceEvaluation。
2.PerformanceEvaluation原理
在HBase中,自带了一个benchmark工具PerformanceEvaluation,可以非常方便地对HBase的Put、Get、Scan等API进行性能测试,并提供了非常丰富的参数来模拟各种场景。PerformanceEvaluation的全名是org.apache.hadoop.hbase.PerformanceEvaluation,已经集成在了bin/hbase工具集中,在安装好HBase的机器上,在HBase的安装路径的bin目录下执行hbase pe,加上相应参数,即可运行PE工具。执行命令格式和相关参数如下:
1 | [root@xxxxxx ~]# hbase pe |
其中几个比较重要的全局参数如下:
- nomapred:采用MapReduce的方式启动多线程测试还是通过多线程的方式,如果没有安装MapReduce,或者不想用MapReduce,通常我们采用多线程的方式,因此一般在命令中加上–nomapred来表示不使用MapReduce。
- oneCon:多线程运行测试时,底层使用一个还是多个连接。这个参数默认值为false,每个thread都会启一个Connection,建议把这个参数设为True,至于原因,后面的章节会讲。
- valueSize:写入HBase的value的size,单位是Byte,大家可以根据自己实际的场景设置这个Value的大小。
- blockEncoding:PE工具会自动建表,这个参数用来指定表的block encoding。关于encoding后面会有专门的文章介绍,这里不再讲。
- table:测试表的名字,如果不设,默认为TestTable。
- rows:总共测试的行数。注意这里的行数是指单线程的行数,如果rows=100, 线程数为10,那么在写测试中,写入HBase的将是 100 x 10 行。
- size:总测试的数据大小,单位为GB,这个参数与上面的size是互斥的,不要两个参数一起设。在使用randomReads和randomSeekScans测试时,这个size可以用来指定读取的数据范围。这个值在Read时非常重要,如果设的不好,会产生很多返回值为空的读,影响测试结果,下面会详细介绍。
- compress:设置表的compress算法,根据自己选择,默认是None,即不做压缩。
- presplit:表的预分裂region个数,在做性能测试时一定要设置region个数,不然所有的读写会落在一个region上,严重影响性能
- autoFlush:默认为false,即PE默认用的是BufferedMutator,BufferedMutator会把数据攒在内存里,达到一定的大小再向服务器发送,如果想明确测单行Put的写入性能,建议设置为true。个人觉得PE中引入autoFlush会影响统计的准确性,因为在没有攒够足够的数据时,put操作会立马返回,根本没产生RPC,但是相应的时间和次数也会被统计在最终结果里。
3.PerformanceEvaluation源码改写与实战
我们部门是HBase集群的使用方,只能使用平台封装好的基本api进行调用,并没有到集群节点上直接执行CMD命令的权限;并且原版PerformanceEvaluation参数和功能较复杂,我们这里只是想看看HBase容器集群的极限读写QPS能不能满足要求,与物理集群有多大区别,我并不想去研究这么多配置参数并全部使用。
那么既然它是官方支持的封装工具,而HBase本身也是开源的,那问题就能好解了,直接扒工具源码,自己大概复刻一个简易版本就行了。这里也体现处理平时遇到问题或者疑问多看开源工程源码的好处了,有这种熟悉度和自信,之前其实我还是挺常看源码的,尤其是HBase源码,还进行过一些改造和使用,遇到疑问或者想参考解决方案看开源项目源码也是非常好的。就是最近业务需求比较紧也比较繁杂,搞得没太多时间和沉得下来的心思来看,这一点确实要反思一下自己。
看了一下源码,其实这个PerformanceEvaluation工具本质就是自己伪造一些数据,然后开多线程按目标qps去请求集群就好了,如从0-10000的顺序rowkey写入、0-10000的随机rowkey写入、先从0-10000的顺序rowkey写入再顺序读出、先从0-10000的顺序rowkey写入再随机读出等等。
1.测试参数初始化类:
1 | public class TestOptions { |
2.指标统计工具类,后续会有一篇博文专门记录java中的指标统计工具:
1 | .Private |
3.计算结果类:
1 | public class RunResult implements Comparable<RunResult> { |
4.测试实例抽象类,主要封装了一些测试实例的公共方法,如触发开始、记录状态、计时等功能,上述提到的如从0-10000的顺序rowkey写入、0-10000的随机rowkey写入等就是测试实例的实现类型,都需要实现该抽象类:
1 | public abstract class TestBase { |
5.测试实例实现类,如下分别是随机写、顺序写、顺序读的实例:
1 | public class RandomdReadTest extends TestBase { |
6.最后是启动类:
1 | public class PerformanceEvaluationJava { |
4.测试结果
| 测试场景 | 单线程数据量 | 并发线程数 | min(ms) | max(ms) | tp95(ms) | tp99(ms) | avg(ms) | TPS |
|---|---|---|---|---|---|---|---|---|
| 容器集群顺序写 | 10000 | 40 | 1.00 | 1207.00 | 1.00 | 101.00 | 2 | 16758 |
| 物理集群顺序写 | 10000 | 40 | 1.00 | 664.00 | 2.00 | 5.00 | 2 | 17311 |
| 容器集群随机读 | 10000 | 20 | 1.00 | 959.00 | 1.00 | 1.00 | 1 | 16535 |
| 物理集群随机读 | 10000 | 20 | 1.00 | 559.00 | 1.00 | 2.00 | 1 | 16720 |
在配额放开到一致的情况下,存算分离容器集群与物理集群读写性能相近,均能达到17000QPS。而且QPS达到峰值之后,CPU也远没有达到性能瓶颈,可见限制HBase集群QPS的并不是CPU计算能力。
物理集群40并发顺序写场景下cpu使用率如下,从日常34%升高至48%:

容器集群40并发顺序写场景下cpu使用率如下,从日常0%升高至6%:
