leveldb学习记录-YCSB测试

YCSB环境安装

昨天在服务器上安装YCSB的测试环境,用来测试leveldb的性能,跑一下实验。本篇博客主要做一个记录,方便日后查看。

ycsb英文全称为Yahoo! Cloud Serving Benchmark (YCSB) 。是Yahoo公司的一个用来对云服务进行基础测试的工具,leveldb的论文中实验测试评估这一章节,主要是采用提供的db_bench作为microbenchmark微基准测试工具,和YCSB作为macrobenchmarks宏基准测试工具,模仿实际的工作load。在运行YCSB的时候,可以配置不同的workload和DB,也可以指定线程数&并发数等其他参数。

主要参考博客:YCSB 测试 LevelDB 数据库

1.介绍

YCSB 是一种测试数据库的benchmark
它的使用原理是:

==A.== 目标数据库(待测试的数据库像Leveldb、Hbase等)作为服务端运行起来,并提供数据库操作相关的restful api,比如

1
2
3
http://localhost:8080/put    
http://localhost:8080/get
http://localhost:8080/del

==B.== YCSB Client 作为客户端,通过restful api调用数据库,从而测试数据库的性能。

将leveldb数据库作为服务端运行起来

由于leveldb是不具有服务端的功能的,也就是无法提供数据库操作相关的restful api的。

因此,我们需要借助一个工具,simplehttpsimpleleveldb

由于leveldb不提供restful api,此处借用的simpleleveldb却可以提供一套restful api与leveldb数据库连接起来。所以ycsb调用restful api就会首先调用simpleleveldb提供的相关操作,然后simpleleveldb再调用leveldb的put、get等操作。所以simpleleveldb就起到一个中间件的作用,将ycsb和leveldb连接起来。

先用git命令获得simplehttp

1
2
git clone https://github.com/bitly/simplehttp.git
cd simplehttp

接着安装simpleleveldb

首先进入你的leveldb数据库的源码文件夹,编译并拷贝至shared libraries folder

1
2
3
cd leveldb
make
sudo cp libleveldb.a /usr/local/lib/

其次安装依赖库 JSON :

1
sudo apt install libjson-c-dev

由于simplehttp/simpleleveldb源码中,include的路径有错误,需要稍微改动一下源码,把json改为json-c

1
2
3
4
打开 simplehttp/simpleleveldb/str_list_set.c修改 
#include <json/json.h> 为 #include <json-c/json.h>
打开 simplehttp/simpleleveldb/simpleleveldb.c修改
#include <json/json.h> 为 #include <json-c/json.h>

同时makefile文件中,对json库的引用也是错误的,-ljson应改为-ljson-c。

打开 makefile,将

LIBS = -L. -L$(LIBSIMPLEHTTP_LIB) -L$(LIBEVENT)/lib -L/usr/local/lib -L$(LIBLEVELDB)/lib -levent -ljson -lsimplehttp -lleveldb -lm -lstdc++ -lsnappy -lpthread

更改为

LIBS = -L. -L$(LIBSIMPLEHTTP_LIB) -L$(LIBEVENT)/lib -L/usr/local/lib -L$(LIBLEVELDB)/lib -levent -ljson-c -lsimplehttp -lleveldb -lm -lstdc++ -lsnappy -lpthread

其次安装依赖库Snappy
1
sudo apt install libsnappy-dev
安装依赖库Event

根据github的issure : https://github.com/bitly/simplehttp/issues/14

里面提到simplehttp目前仅与libevent 1.4兼容

所以libevent的版本必须是1.4版本!!!注意

进入网页下载 http://libevent.org/ 选择libevent 1.4.14b版本下载

tar解压之后输入以下命令

1
2
3
4
cd libevent-1.4.14b-stable
./configure && make
sudo make install
sudo ln -s /usr/local/lib/libevent-1.4.so.2 /usr/lib/libevent-1.4.so.2 (非必须,若出错可加)之前我没加此条软连接命令报错了,做好还是加上
安装依赖库simplehttp (进入到 simplehttp/simplehttp):
1
2
3
cd simplehttp
make
sudo make install
安装 simpleleveldb
1
2
3
cd simpleleveldb
env LIBLEVELDB=/usr/local make
sudo make install

simpleleveldb 试运行

打开终端,输入

simpleleveldb --address=localhost --port=8080 --db-file=test

image-20210107113625347

打开浏览器,地址栏输入
http://localhost:8080/put?key=name&value=Niko
然后会显示一段json,状态码是200

image-20210107113722258

再输入
http://localhost:8080/get?key=name
会显示一个json,状态码是200,并且返回 Niko

image-20210107145124950

至此,LevelDB的服务端就运行成功了!

后面就可以下载编译YCSB客户端,运行./ycsb做测试了

运行YCSB客户端

下载并编译YCSB客户端:

1
2
3
git clone https://github.com/jtsui/ycsb-leveldb.git
cd ycsb-leveldb
mvn -pl com.yahoo.ycsb:leveldb-binding -am clean package

在输入mvn -pl com.yahoo.ycsb:leveldb-binding -am clean package命令,由于需要使用jdk环境,而由于ubuntu16.04自带了开源版本openjdk8,不知道为什么还是会报错,找不到java的compiler。故我又重新安装了jdk8.

安装java开发环境jdk8

下载完安装包后解压得到jdk1.8.0_271文件夹,将其放在/opt目录下

在/bin目录下创建java软链接
1
2
cd /bin
sudo ln -s /opt/jdk1.8.0_271/bin/java java

验证软链接的正确性。

修改环境变量

输入下面的命令打开环境变量配置文件:

1
sudo vi ~/.bashrc

在最末尾添加如下内容(其中的jdk1.8.0_271是我安装的版本,如果你的版本不是jdk1.8.0_271,则需要修改一下):

1
2
3
4
export JAVA_HOME=/opt/jdk1.8.0_271
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH

保存并退出,使用source命令使之生效:

1
source ~/.bashrc
最后输入java -version查看是否安装成功

image-20210107150826458

至此,安装成功!

之后再输入mvn -pl com.yahoo.ycsb:leveldb-binding -am clean package就不会再报错啦!!!

现在就可以正式运行YCSB客户端测试数据库了,请注意,应该先启动LevelDB的服务端。

1
2
./ycsb load leveldb -P workloads/workloada
./ycsb run leveldb -P workloads/workloada

上面的实例是采用wordload a。ycsb还提供了workload a、b、c、d、e。

Running the ycsb command without any argument will print the usage.运行不带任何参数的ycsb命令可以打印用法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Usage: ./ycsb command database [options]

Commands:
load Execute the load phase
run Execute the transaction phase
shell Interactive mode

Databases:
basic https://github.com/brianfrankcooper/YCSB/tree/master/basic
cassandra-10 https://github.com/brianfrankcooper/YCSB/tree/master/cassandra
cassandra-7 https://github.com/brianfrankcooper/YCSB/tree/master/cassandra
cassandra-8 https://github.com/brianfrankcooper/YCSB/tree/master/cassandra
dynamodb https://github.com/brianfrankcooper/YCSB/tree/master/dynamodb
elasticsearch https://github.com/brianfrankcooper/YCSB/tree/master/elasticsearch
gemfire https://github.com/brianfrankcooper/YCSB/tree/master/gemfire
hbase https://github.com/brianfrankcooper/YCSB/tree/master/hbase
hypertable https://github.com/brianfrankcooper/YCSB/tree/master/hypertable
infinispan https://github.com/brianfrankcooper/YCSB/tree/master/infinispan
jdbc https://github.com/brianfrankcooper/YCSB/tree/master/jdbc
leveldb https://github.com/brianfrankcooper/YCSB/tree/master/leveldb
leveldbjni https://github.com/brianfrankcooper/YCSB/tree/master/leveldbjni
mapkeeper https://github.com/brianfrankcooper/YCSB/tree/master/mapkeeper
mongodb https://github.com/brianfrankcooper/YCSB/tree/master/mongodb
nosqldb https://github.com/brianfrankcooper/YCSB/tree/master/nosqldb
orientdb https://github.com/brianfrankcooper/YCSB/tree/master/orientdb
redis https://github.com/brianfrankcooper/YCSB/tree/master/redis
voldemort https://github.com/brianfrankcooper/YCSB/tree/master/voldemort

Options:
-P file Specify workload file 指定工作负载文件
-p key=value Override workload property 工作负载特征
-s Print status to stderr 打印状态到stderr
-target n Target ops/sec (default: unthrottled) 目标ops/sec,(默认值:无限制)
-threads n Number of client threads (default: 1) 客户端线程数(默认:单线程) 写入过程是单线程的

Workload Files:
There are various predefined workloads under workloads/ directory.
See https://github.com/brianfrankcooper/YCSB/wiki/Core-Properties
for the list of workload properties.

有关如何运行工作负载的详细文档,请参阅https://github.com/brianfrankcooper/YCSB/wiki/Running-a-Workload。

运行工作负载有6个步骤:

1、设置要测试的数据库

2、选择合适的DB接口层

3、选择合适的工作负载

4、选择合适的运行时参数(客户机线程数、目标吞吐量等)

5、load 数据

6、执行工作负载

这里描述的步骤假设您运行的是单个客户机服务器。这对于小型到中型集群(例如10台左右的机器)应该足够了。

step1、设置要测试的数据库

我们采用的就是LevelDB

step2、选择合适的DB接口层

DB接口层是一个java类,它将YCSB客户机生成的读、插入、更新、删除和扫描调用执行到针对数据库API的调用中。这个类是com.yahoo中的抽象DB类的子类。ycsb包。您将在运行YCSB客户机时在命令行上指定层的类名,客户机将动态加载您的接口类。命令行上或命令行上指定的参数文件中指定的任何属性都将传递给DB接口实例,并可用于配置层(例如,告诉它您正在进行基准测试的数据库的主机名)。

YCSB客户端带有一个简单的虚拟接口层com.yahoo.ycsb.BasicDB。这一层只是将它将要执行的操作打印到System.out。它对于确保客户机正常运行和调试工作负载非常有用。

您可以使用ycsb命令直接对数据库运行命令。这个客户端使用DB接口层向数据库发送命令。您可以使用这个客户机来确保DB层正常工作,数据库设置正确,DB层可以连接到数据库,等等。它还为各种数据库提供了一个公共接口,并可用于检查数据库中的数据。

image-20210107161336539

1
2
3
4
5
6
7
8
9
10
$ ./bin/ycsb shell basic
> help
Commands:
read key [field1 field2 ...] - Read a record
scan key recordcount [field1 field2 ...] - Scan starting at key
insert key name1=value1 [name2=value2 ...] - Insert a new record
update key name1=value1 [name2=value2 ...] - Update a record
delete key - Delete a record
table [tablename] - Get or [set] the name of the table
quit - Quit

step3、选择合适的工作负载

工作负载定义在load阶段将load到数据库中的数据,以及在事务transaction阶段将对数据集执行的操作。

a workload is a combination of:

  • Workload java类(com.yahoo.ycsb.Workload的子类)
  • 参数文件(Java属性格式)

在运行ycsb命令时指定的参数 是load还是run,确定是load阶段还是run阶段

step4、选择合适的运行时参数(客户机线程数、目标吞吐量等)

尽管workload类和参数文件定义了特定的工作负载,但是您可能希望为基准测试的特定运行指定其他设置。当您运行YCSB客户端时,这些设置在命令行中提供。包括以下选项:

  • -threads:客户端线程数,ycsb客户端默认是使用单个工作线程。
  • -target:每秒的目标操作数。默认情况下,YCSB客户端将尝试执行尽可能多的操作。例如,如果每个操作平均花费100毫秒,客户端将在每个工作线程上每秒执行10个操作。但是,您可以限制每秒操作的目标数量。例如,要生成延迟与吞吐量曲线,您可以尝试不同的目标吞吐量,并测量每个目标吞吐量的结果延迟。
  • -s:status,对于长期运行的工作负载,让客户机报告状态可能是有用的,这只是为了确保它没有崩溃,并让您了解它的进度。通过在命令行中指定“-s”,客户端将每10秒向stderr报告一次状态。

step5、load数据

工作负载有两个可执行阶段:load阶段(定义要插入的数据)和事务阶段(定义要对数据集执行的操作)。要加载数据,您需要运行YCSB客户机并告诉它执行加载部分。

输入以下命令./ycsb load leveldb -P workloads/workloada

-p参数是用来load属性文件的,此处使用它来加载workload参数文件

step6、执行工作负载

./ycsb run leveldb -P workloads/workloada

运行结束时,客户机将报告stdout上的性能统计数据。默认情况下,为每个操作类型(读取、更新等)生成平均、最小、最大、第95和99百分位延迟,每个操作的返回代码计数,以及每个操作的延迟柱状图。返回代码由数据库接口层定义,允许您查看工作负载期间是否有任何错误。

运行图

这个输出显示:

  • 总的执行时间是3.799s
  • 平均吞吐为263.2ops/s
  • 有491个update操作,以及相关的平均、最小、最大、95和99百分位延迟
  • 所有491次update操作的返回码都为0(在本例中是成功的)
  • xxx个操作在不到1毫秒内完成,xx个操作在1至2毫秒内完成。

YCSB的核心属性

所有工作负载文件都可以指定以下属性:

  • workload: 要使用的工作负载类别(例如com.yahoo.ycsb.workloads.CoreWorkload)
  • recordcount: 工作负载开始时数据集 中的record数量。默认1000
  • operationcount: 工作负载中要执行的操作数量 (default: 1000)
  • db: 使用的数据库,也可以在命令行上指定 (default: com.yahoo.ycsb.BasicDB)
  • exporter: measurements exporter class to use要使用的测量结果的输出类 (default: com.yahoo.ycsb.measurements.exporter.TextMeasurementsExporter)
  • exportfile: path to a file where output should be written instead of to stdout 用于替代stdout的输出文件路径(default: undefined/write to stdout)
  • threadcount: YCSB客户端线程数. Alternatively this may be specified on the command line. (default: 1)
  • measurementtype: supported measurement types are hdrhistogram, 支持的测量结果类型有直方图和时间序列 (default: hdrhistogram)

核心工作负载包属性

  • fieldcount: the number of fields in a record (default: 10)
  • fieldlength: the size of each field (default: 100)
  • minfieldlength: the minimum size of each field (default: 1)
  • readallfields: should reads read all fields (true) or just one (false) (default: true)
  • writeallfields: should updates and read/modify/writes update all fields (true) or just one (false) (default: false)
  • readproportion: 读操作的比例 (default: 0.95)
  • updateproportion: 更新操作的比例 (default: 0.05)
  • insertproportion: 插入操作的比例 (default: 0)
  • scanproportion: scan操作的比例(default: 0)
  • readmodifywriteproportion: 读-修改-写一条记录的操作比例 (default: 0)
  • requestdistribution: 选择要操作的记录的分布– uniform(均匀), zipfian, hotspot, sequential, exponential or latest (default: uniform)
  • minscanlength: for scans, what is the minimum number of records to scan (default: 1)
  • maxscanlength: scan操作遍历的最大记录数,for scans, what is the maximum number of records to scan (default: 1000)
  • scanlengthdistribution: 对于scan,应该使用哪个分布来选择要scan的记录数量, for each scan, between 1 and maxscanlength (default: uniform)
  • insertstart: for parallel loads and runs, defines the starting record for this YCSB instance (default: 0)
  • insertcount: for parallel loads and runs, defines the number of records for this YCSB instance (default: recordcount)
  • zeropadding: for generating a record sequence compatible with string sort order by 0 padding the record number. Controls the number of 0s to use for padding. (default: 1)
    For example for row 5, with zeropadding=1 you get ‘user5’ key and with zeropading=8 you get ‘user00000005’ key. In order to see its impact, zeropadding needs to be bigger than number of digits in the record number.
  • insertorder: 记录是否应该有序插入(ordered),或者是哈希顺序(hashed) (default: hashed)
  • fieldnameprefix: what should be a prefix for field names, the shorter may decrease the required storage size (default: “field”)

测量结果属性

这些属性被应用于每一个测量结果类型:

直方图

  • histogram.buckets:直方图输出的区间数(默认:1000)

时间序列

  • timeseries.granularity:时间序列输出的粒度(默认:1000)

YCSB六个核心工作负载

Workload Description
YCSB A write-intensive: 50% updates, 50% reads
YCSB B read-intensive: 5% updates, 95% reads
YCSB C read-only: 100% reads
YCSB D read-latest: 5% updates, 95% reads
YCSB E scan-intensive: 5% updates, 95% scans; average scan length 50 elements
YCSB F 50% read-modify-write, 50% reads