YCSB介绍
YCSB,全称为“Yahoo! Cloud Serving Benchmark”,是雅虎开发的用来对云服务进行基础测试的工具,其内部涵盖了常见的NoSQL数据库产品,如HBase、Cassandra、Couchbase、MongoDB、Redis、DynamoDB等。
HBase在企业生产环境中使用比较普遍,笔者做过的项目包括,企业级分布式对象存储服务系统、用户标签画像数据、订单明细数据查询等等。
但是HBase提供生产服务之前,针对HBase的基准测试也是一个必不可少的环节,今天笔者借助YCSB对HBase集群进行基准性能测试。
压测前
对HBase进行压测后,我们想要获取一些信息:
HBase集群在目前软硬件环境下的性能指标,比如平均以及最大吞吐量、平均以及最大读写延迟等。利用这些指标,可以为业务应用提供参考。
HBase分布式集群环境在不同负载下的性能瓶颈的原因
明确系统核心参数对HBase系统性能的影响
本次压测的环境是软件混合部署,基于CDH的全家桶。真正提供生产级别的环境,HBase最好单独部署,提供最佳的性能。
下载和安装YCSB
> 1. 由于HBase版本为1.2,下载对应的YCSB版本部署包:
https://github.com/brianfrankcooper/YCSB/releases/download/0.17.0/ycsb-hbase12-binding-0.17.0.tar.gz
> 2. 解压部署以及配置环境变量
## 解压
tar zxvf ycsb-hbase12-binding-0.17.0.tar.gz
## 配置环境变量(~/.bashrc)
export YCSB_HOME=/home/jason/ycsb/ycsb-hbase12-binding-0.17.0
export PATH=$PATH:$YCSB_HOME/bin
YCSB性能压测步骤
1. 创建 HBase 表
HBase集群开启了Kerberos以及ACL权限认证,为了本次压测,笔者使用HBase管理员创建namespace并赋值给测试账号jason:
# kinit -kt hbase.keytab hbase
hbase(main):002:0> create_namespace 'ycsb_hbase_ns'
0 row(s) in 0.3770 seconds
hbase(main):003:0> grant 'jason','RWXCA','@ycsb_hbase_ns'
0 row(s) in 0.7130 seconds
然后我们就使用普通用户创建测试的表:
$ kinit -kt jason.keytab jason
hbase(main):001:0> list_namespace
NAMESPACE
ycsb_hbase_ns
hbase(main):002:0> n_splits = 450 # HBase recommends (10 * number of regionservers)
=> 450
hbase(main):003:0> create 'ycsb_hbase_ns:usertable', 'family', {SPLITS => (1..n_splits).map {|i| "user#{1000+i*(9999-1000)/n_splits}"}}
0 row(s) in 18.5540 seconds
=> Hbase::Table - ycsb_hbase_ns:usertable
2. 设置HBase配置文件
在$YCSB_HOME中创建conf目录,并在其中建立hbase-site.xml软链接或拷贝hbase-site.xml文件到$YCSB_HOME/conf目录。
$ mkdir $YCSB_HOME/conf
ln -s /etc/hbase/conf/hbase-site.xml $YCSB_HOME/conf/hbase-site.xml
为了避免如下错误(其实不影响ycsb测试):
util.DynamicClassLoader: Failed to identify the fs of dir hdfs://idc-nn/hbase/lib, ignored
java.io.IOException: No FileSystem for scheme: hdfs
把core-site.xml和hbase-site.xml也拷贝到$YCSB_HOME/conf目录下
$ tree $YCSB_HOME/conf
...
├── core-site.xml
├── hbase-site.xml
└── hdfs-site.xml
java.io.IOException: No FileSystem for scheme: hdfs
3. 选择合适的workload
YCSB提供了很多的workloads文件,每个workload文件都定义了具体的测试负载的相关配置以及标准测试数据,如下:
$ tree workloads
workloads
├── tsworkloada
├── tsworkload_template
├── workloada
├── workloadb
├── workloadc
├── workloadd
├── workloade
├── workloadf
└── workload_template
在正式介绍workload之前,先来看一下YCSB支持的数据分布方式:
Uniform:等概论随机选择记录
Zipfian:随机选择记录,存在热记录
Latest:近期写入的记录为热记录
笔者在这里给大家具体说明一下每个workload的具体含义。
workloada
读取-更新均衡型:50% Read,50% Update
zipfian分布,随机选择记录,存在热记录
典型应用场景为session存储系统记录最近的操作
workloadb
读多写少型:95% Read,5% Update
zipfian分布,随机选择记录,存在热记录
典型应用场景为标签存储系统,更新较少,大部分都是读取操作
workloadc
只读型:100% Read
zipfian分布,随机选择记录,存在热记录
典型应用场景为历史订单明细查询,几乎全部是查询操作
workloadd
最近数据随机读取型:95% Read,5% Insert
latest分布,近期写入的记录为热记录
workloade
区间扫描读取型:95% Scan,5% Insert
scan长度分布:uniform,等概论随机选择记录
scan的最大长度为100
zipfian分布,随机选择记录,存在热记录
除了上面YCSB提供的workload外,用户可以根据实际情况,自己定制化测试workload。
具体参数的含义可以参考workload_template模版文件,里面给出了非常详细的解释说明。
4. ycsb客户端的命令行参数设置
$ ycsb
Commands:
load Execute the load phase
run Execute the transaction phase
shell Interactive mode
......
Options:
-P file Specify workload file
-cp path Additional Java classpath entries
-jvm-args args Additional arguments to the JVM
-p key=value Override workload property
-s Print status to stderr
-target n Target ops/sec (default: unthrottled)
-threads n Number of client threads (default: 1)
笔者简单说明几个比较重要的参数:
-target n
每秒的目标操作吞吐量。默认情况下,客户端会以能达到的最大吞吐量运行,用户可以设置target参数throttle操作吞吐量,用来观察对应的操作延迟变化。
-threads n
客户端线程数。默认情况下,如果不指定该参数,客户端线程数为1,用户可以增大该参数模拟真实线上的线程数量。
-s
控制台打印状态结果的输出,设置后,默认每隔10s输出一次到控制台,方便用户及时了解当前的测试情况。
5. 加载数据
万事俱备,接下来正式加载测试数据并进行压测。YCSB测试阶段分为load和run(transaction)两个阶段。
笔者使用workloadb来进行测试,为了测出实际服务器集群读写性能,开启6个YCSB客户端并发进行测试,最终Throughput是6个客户端的总和,AverageLatency取6个客户端延迟的平均值。
本次压测,我们生成数据集为2亿,由于单个YCSB客户端压测存在瓶颈,所以使用6个ycsb客户端进行并发提交:
recordcount=200000000
load数据:
$ ycsb load hbase12 -P workloads/workloadb -cp $YCSB_HOME/conf -p table=ycsb_hbase_ns:usertable -p columnfamily=family -threads 50 -s
| YCSB客户端 | 吞吐量(ops/sec) | Insert平均延时(us) |
|---|---|---|
| 客户端A | 12858 | 4423 |
| 客户端B | 13014 | 4500 |
| 客户端C | 13207 | 4595 |
| 客户端D | 13317 | 4533 |
| 客户端E | 12835 | 4535 |
| 客户端F | 12834 | 4571 |
分析:
这里我只是开启6个YCSB客户端,共300个线程数,根据实际观察,还可以增加线程数,提高吞吐量,比如增加线程数到500
根据写入延迟的结果,写入延迟平均为5ms左右
对于写操作,集群吞吐量可以达到70000+(ops/sec),平均延时为4.5ms左右。
补充:
单个YCSB客户端提高线程数测试:
ycsb load hbase12 -P workloads/workloadb -cp $YCSBHOME/conf -p table=ycsbhbase_ns:usertable -p columnfamily=family -threads 150 -s
写入吞吐量可以达到27000+(ops/sec)
执行workload测试
笔者在生产环境进行了完备的验证测试,笔者在这里只简单举两个例子说明一下,大家针对自己的环境,还是需要进行充分的测试,包括不同线程的压测以及不同负载的测试。
> 1. workloadb测试(读多写少型:95% Read,5% Update)
ycsb run hbase12 -P workloads/workloadb -threads 150 -p operationcount=20000000 -p table=ycsb_hbase_ns:usertable -p columnfamily=family -p measurementtype=timeseries -p timeseries.granularity=2000 -s
对几个新增的参数说明:
-p measurementtype=timeseries
测量类型采用时间序列方式
-p timeseries.granularity=2000
按照时间序列汇总结果的时间粒度,即YCSB客户端多长时间汇总一次结果,单位为ms。
测试结果:
Throughput(ops/sec), 78679.44420840612
[READ], AverageLatency(us), 1550.1748030920548
[UPDATE], AverageLatency(us), 7304.554698390556
> 2. workloadb测试(只读型:100% Read)
ycsb run hbase12 -P workloads/workloadc -threads 150 -p operationcount=20000000 -p table=ycsb_hbase_ns:usertable -p columnfamily=family -p measurementtype=timeseries -p timeseries.granularity=2000 -s
测试结果:
[OVERALL], Throughput(ops/sec), 40541.71844181959
[READ], AverageLatency(us), 3623.9933210963445
可以看出,HBase读性能也是不错的,虽然比写性能差些。读的平均延时也比较低,但是如果增加线程数,延时就会增加。
总结
目前笔者的HBase生产环境已经应用过好几个项目,还是比较稳定的。但是由于整个集群内存等资源比较紧张,HBase做了一些优化,比如BucketCache使用File存储,而非heap或offheap。其实关于HBase的优化,google里面一堆,后面有空笔者也会结合自己的生产环境,整理出来。
笔者没有抽时间把YCSB压测的完整记录整理出来,包括使用图形化展示压测结果数据,望谅解。但是把整个压测思路和过程都说明了,希望大家根据自己的生产环境压测即可。说句正常的废话,压测不是最终目的,根据压测结果去发现问题,进行优化HBase集群并提升读写性能以及系统稳定性,将HBase应用到更多的场景中才王道。




