阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

NoSQL性能测试工具YCSB-Running a Workload

191次阅读
没有评论

共计 7944 个字符,预计需要花费 20 分钟才能阅读完成。

写在前面

目前,在系统设计中引入了越来越多的 NoSQL 产品,例如 Redis/ MongoDB/ HBase 等,其中性能指标往往会成为权衡不同 NoSQL 产品的关键因素。对这些产品在性能表现和产品选择上的争论,Ivan 碰到不止一次。虽然通过对系统架构原理方面的分析可以大致判断出其在不同读写场景下的表现,但一是对受众有较高的要求,也来的不那么直接。这时候,没有什么比一次性能测试更有说服力。有什么好的性能测试工具呢?这就是今天的主角 YCSB。YCSB 是 Yahoo 开源的一套分布式性能测试工具,方便易用,拓展性强。Ivan 最近研究 HBase 二级索引时用它来做性能测试,感觉还是非常顺手的。虽然网上已经有很多 YCSB 的介绍文章,但用来指导实际操作还是有些不便。Ivan 会用两三篇文章来介绍一下 YCSB 的实际使用。本文是官方文章的译文,选择这篇文章是因为其与具体操作的关系比较紧密,感兴趣的同学可以了解一下。

正文

运行 workload 有六个步骤

  1. 安装待测试的数据库系统
  2. 选择适当的 DB 接口层
  3. 选择适当的工作负载
  4. 选择适当的运行参数(客户端线程数量,目标吞吐等)
  5. 加载数据
  6. 执行工作负载(workload)

这些步骤描述都假定你运行一个单客户端。这可以满足中小规模集群(10 台左右)的测试需要。对于更大规模的集群,你必须在不同的服务器上运行多个客户端来生成足够的负载。类似地,在某些场景下,多客户机加载数据库可能更快。多客户端并行运行的更多细节,可以查看 Running a Workload in Parallel

Setp 1. 安装待测试的数据库

第一步是安装你希望测试的数据库。可能是单机或者集群,依赖于你要测试的配置。
你必须 create 或 set up tables/keyspaces/storage buckkets 用于存储记录。这些细节对于每个数据库都不同,依赖于希望运行的负载情况。在 YCSB 客户端运行前,数据表必须被创建,因为客户端自身是不会请求创建数据库表的。这是因为对于某些系统创建表一个手工操作,而对于其他系统,表必须在集群启动前被创建。
workload 所依赖的 table 必须被创建。对于核心负载,YCSB 客户端将假定存在一个名为 ’usertable’ 的 table,且具有灵活的 schema:运行时可以根据需要增加列。’usertable’ 可以被映射为适当的存储容器。例如,在 MySQL 中,你可以 create table,在 Cassandra 你可以在配置中定义 keyspace。数据库接口层(Step 2 描述)会收到读写 usertable 的请求,将其转换为你所指定的实际存储的请求。这意味着你必须提供数据库接口层帮助它理解下层存储的结构。例如,在 Cassandra 中,你必须定义在 keyspace 中定义列族 column families。这样,必须创建一个列族并命名(例如,你可以使用 values)。然后,数据库访问层需要理解指向 values 列族,或者将字符串“values”设置为一个属性,或者在数据库接口层中硬编码。

Step 2. 选择适当的数据库接口层

数据库接口层是一个可执行的 java 类,实现 read、write、update、delete 和 scan 调用,它由 YCSB 客户端生成,调用你的数据库 API。这个类是 com.yahoo.ycsb 包下抽象类 DB 的子类。在运行 YCSB 客户端时,你要通过命令行指定类名,客户端会动态加载你的接口类。命令行中指定的任何属性或指定的参数文件,将会传递给数据库接口层实例,用于配置该层(例如,告诉它你要测试的数据库主机名 hostname)

YCSB 客户端自带一个简单的虚拟接口层,com.yahoo.ycsb.BasicDB。这层会把执行的操作通过 System.out 打印。这可以用于确认客户端在正常运行,用于 debug 你的 workload。

如何使用 YCSB 客户端的细节可以查看 Using the Database Libraries。更多实现数据库接口层的细节,可以查看 Adding a Database

你可以使用 YCSB 命令,直接运行数据库命令。客户端使用 DB 接口层发送命令给数据库。你可以使用客户端确定 DB 层运行正常,你的数据库正确安装,DB 层可以连接到数据库等等。它为大量的数据库提供了命令行接口,可以用于检验数据库的数据。运行命令行:

$ ./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

Step 3 选择适当的工作负载

工作负载定义了在 loading 阶段将被加载进数据库的数据,在 transaction 阶段在数据集上执行的操作。
典型的工作负载包括以下内容:

  • Workload java class(com.yahoo.ycsb.Workload 的子类)
  • Parameter file(Java Properties 格式)

因为数据集的参数属性必须在两个阶段被获得,在 loading 阶段用于构造和插入适当类型的记录,在 transaction 阶段用于指定正确的记录 id 和 field,所以参数文件在两个阶段都会使用。workload java class 使用这些属性插入记录(loading phase)或操作那些记录(transaction phase)。选择哪个阶段要看你运行 YCSB 命令行时指定的参数。

在运行 YCSB 客户端的命令行时,你可以指定 java class 和参数文件。客户端将动态加载你的 workload class,从参数文件解析参数(和任何命令行的附加参数)并执行 workload。在 loading 和 transaction 两个阶段,需要同样的属性和 workload 逻辑应用。例如,如果 loading 阶段创建 10 个 field 的记录,而后在 transaction 阶段必须知道有 10 个 field 可以被查询和修改。

YCSB 自带的 CoreWorkload 是标准 workload 包可以直接使用。CoreWorkload 定义了简单的 read/insert/update/scan 操作组合。在参数文件中定义了每种操作的相应频率,以及其他 workload 属性。这样,修改参数文件可以执行不同的 workload。更多 CoreWorkload 的细节,可以查看 Core Workloads

如果 CoreWorkload 不能满足你的需求,你可以基于 com.yahoo.ycsb.Workload 定义自己的 workload 子类。细节可以查看 Implementing New Workloads

Step 4 选择适当的运行参数

虽然 workload class 和参数文件定义了具体的 workload,还有一些在运行特定测试时,你可能希望指定附加的设置。这些设置可以通过 YCSB 客户端命令行实现。设置包括

  • -threads: 客户端线程数量。默认,YCSB 客户端使用一个 worker 线程,但可以指定。这通常用来根据数据库增加负载数量。
  • -target: 每秒操作目标数量。默认,YCSB 客户端会尝试尽可能多的操作。例如,每个操作平均花费 100ms, 客户端将在每个线程中每秒执行 10 个操作。然而,你可以限流每秒操作的数量。例如,产生一个延迟与吞吐量的曲线,你可以尝试不同的目标吞吐量,衡量每次产生的延迟。
  • -s :status. 对于一个长时间运行的 workload,它是有用的,可以获得客户端状态报告,判断他是否崩溃并给你一些过程中的信息。通过命令行指定 ”-s”,客户端可以每 10 秒报告状态到 stderr。

Step 5. 加载数据

Workload 有两个执行阶段:loading 阶段(定义待插入的数据)和 transaction 阶段(定义数据集上的操作)。为了加载数据,你要运行 YCSB 客户端并告诉它执行 loading 阶段。
例如,考虑 workload A 的 benchmark(更多标准 workloads 细节在 Core Workloads)。加载标准数据集

$ ./bin/ycsb load basic -P workloads/workloada

这个命令的关注点

  • load 参数告诉客户端执行 loading 阶段

  • basic 参数告诉客户端使用 BasicDB 层。你可以在参数文件中指定这个属性,使用 ’db’ 属性(例如 db=com.yahoo.ycsb.BasicDB)
    - P 参数用来加载 property 文件。这个例子中,我们用来加载 workload 参数文件。

加载 HBase 数据集:

$ ./bin/ycsb load hbase -P workloads/workloada -p columnfamily=family

这个命令的关注点

  • load 参数是告诉 Client 执行 loading 阶段操作。
  • hbase 参数是告诉 Client 使用 HBase layer
  • -P 参数是用来加载参数文件,例子中我们用来加载 workload 参数文件
  • -p 参数用于设置参数,在这个 HBase 例子中,我们用来设置数据库的列。你数据库中存在 usertable 带有 family 列,以执行这个命令。而后所有数据被加载到数据库 usertable 带有 family 列。
  • 执行命令前,确定你已经启动了 Hadoop 和 HBase

如果你使用 BasicDB,你将看到数据库的 insert 语句。如果是你用一个实际的 DB 接口层,记录会被加载到数据库中。

标准 workload 参数文件创建很小的数据库,例如,workload 仅创建 1000 条记录。这用于调试你的安装。然而,运行一个实际的 benchmark 你需要创建一个更大的数据库。例如,想象你需要加载 100 百万记录。然后,你需要修改 workload 文件中默认的“recordcount”属性。有两个办法实现。

指定一个新的属性文件,包含 recordcount 的新值。在命令行中,如果这个文件在 workload 文件后被指定,它会覆盖 workload 的任何属性。例如创建 ”large.dat” 文件,仅有一行内容

recordcount=100000000

然后,client 执行以下内容

$ ./bin/ycsb load basic -P workloads/workloada -P large.dat

Client 会加载所有的属性文件,但使用最后加载的一个文件 large.dat 中的 recordcount 值,

通过命令行指定 recordcount 属性的新值。在命令行指定的任何属性都会覆盖配置文件中的属性。如下执行

$ ./bin/ycsb load basic -P workloads/workloada -p recordcount=100000000

一般来说,好的实践是在新的参数文件中存储任何重要的参数,代替通过命令行指定它们。这使得你的 benchmark 结果可以被复现。不用必须重建你使用的命令行,你重用参数文件即可。注意,当它开始执行时,YCSB Client 会打印处他的命令行,所以如果你将 Client 的输出存储到一个数据文件,你可以很容易重新执行命令行。
因为一个大数据库加载需要很长时间,你可能希望 1. 需要 Client 输出状态,2. 直接将输出写入数据文件。这样,你可以执行以下命令加载数据库。

$ ./bin/ycsb load basic -P workloads/workloada -P large.dat -s > load.dat

-s 参数将要求 Client 向 stderr 输出状态报告。这样命令行的输出可能是这样

$ ./bin/ycsb load basic -P workloads/workloada -P large.dat -s > load.dat
Loading workload… (might take a few minutes in some cases for large data sets)
Starting test.
0 sec: 0 operations
10 sec: 61731 operations; 6170.6317473010795 operations/sec
20 sec: 129054 operations; 6450.76477056883 operations/sec

这个状态输出会帮助你看到加载操作执行得多快(这样你可以估计加载的完成时间),确认 load 正在执行。当 load 完成时,Client 会报告 load 的性能统计数据。这些统计与 transaction 阶段一样,所以看后续介绍

Step 6 执行 workload

一旦数据被加载,你就可以执行 workload。告诉 Client 执行 transaction 操作。执行 workload,可以使用以下命令

$ ./bin/ycsb run basic -P workloads/workloada -P large.dat -s > transactions.dat

主要差别是我们使用 run 参数时,告诉 Client 执行 transaction 阶段而不是 loading 阶段。如果你使用 BasicDB,检查结果文件 transactions.dat,你会看到一个 read 和 update 混合的请求,与统计数据一致。

典型情况下,你会希望使用 -threads 和 -target 参数控制负荷量。例如,你可能希望 10 个线程每秒总数 100 个操作。平均操作延时不高于 100ms,每个线程能够携带每秒 10 此操作。一般来说,你需要足够的线程因为没有线程尝试每秒更多的操作,否则你达到的吞吐量将小于指定的目标吞吐量。
这个例子,我们可以执行

$ ./bin/ycsb run basic -P workloads/workloada -P large.dat -s -threads 10 -target 100 > transactions.dat

注意这个例子,我们使用 -threads 10 命令参数指定 10 个线程,-target 100 命令参数指定每秒 100 次操作。否则,两个值可以设置在你的参数文件中,使用 threadcount 和 target 属性代替。例如

threadcount=10
target=100

run 的结尾,Client 会向 stdout 报告性能统计数据。上面的例子,统计数据会写入 transaction.dat 文件。默认包括每个操作类型延时的 average,min,max,95th,99th。每次操作返回代码的统计,每类操作的直方图。返回值被你的 DB 接口层定义,允许你看到 workload 过程中的任何错误。上述例子中,我们可以得到输出:

[OVERALL],RunTime(ms), 10110
[OVERALL],Throughput(ops/sec), 98.91196834817013
[UPDATE], Operations, 491
[UPDATE], AverageLatency(ms), 0.054989816700611
[UPDATE], MinLatency(ms), 0
[UPDATE], MaxLatency(ms), 1
[UPDATE], 95thPercentileLatency(ms), 1
[UPDATE], 99thPercentileLatency(ms), 1
[UPDATE], Return=0, 491
[UPDATE], 0, 464
[UPDATE], 1, 27
[UPDATE], 2, 0
[UPDATE], 3, 0
[UPDATE], 4, 0

这个输出指标

  • 总体执行时间为 10.11 秒

  • 平均吞吐量 98.9 ops(所有线程)
  • 491 次修改操作,附带 average,min,max,95th,99th % 延迟情况
  • 所有 491 次修改操作都返回 0(成功)
  • 464 次操作在 1ms 内完成,27 次在 1 至 2ms 内完成。

读操作有与之接近的统计数值

延时信息的直方图通常是有用的,时序图的形式有时更有用。请求一个时序,需要在 Client 命令行或在属性文件指定 ”measureenttype=timeseries” 属性。默认情况下,Client 会每间隔 1000ms,报告一次平均延时。你可以对报告指定不同的间隔粒度,使用 timeseries.granularity 属性,例如。

$ ./bin/ycsb run basic -P workloads/workloada -P large.dat -s -threads 10 -target 100 -p \measurementtype=timeseries -p timeseries.granularity=2000 > transactions.dat

将会报告一个时序,间隔 2000ms 读一次,结果将是。

[OVERALL],RunTime(ms), 10077
[OVERALL],Throughput(ops/sec), 9923.58836955443
[UPDATE], Operations, 50396
[UPDATE], AverageLatency(ms), 0.04339630129375347
[UPDATE], MinLatency(ms), 0
[UPDATE], MaxLatency(ms), 338
[UPDATE], Return=0, 50396
[UPDATE], 0, 0.10264765784114054
[UPDATE], 2000, 0.026989343690867442
[UPDATE], 4000, 0.0352882703777336
[UPDATE], 6000, 0.004238958990536277
[UPDATE], 8000, 0.052813085033008175
[UPDATE], 10000, 0.0
[READ], Operations, 49604
[READ], AverageLatency(ms), 0.038242883638416256
[READ], MinLatency(ms), 0
[READ], MaxLatency(ms), 230
[READ], Return=0, 49604
[READ], 0, 0.08997245741099663
[READ], 2000, 0.02207505518763797
[READ], 4000, 0.03188493260913297
[READ], 6000, 0.004869141813755326
[READ], 8000, 0.04355329949238579
[READ], 10000, 0.005405405405405406

这个输出分开显示了 update 和 read 操作的时间序列,每 2000ms 的数据。数据报告的时点是仅包括前一个 2000ms 的均值。(这个例子,我们做了 100,000 次操作,目标是每秒 10,000 次操作)。一个关于延时度量的关注点:Client 度量,特定操作对数据库的端到端的执行延时。那样,它在调用 DB 接口层 class 适当方法前会启动启动一个时钟,方法返回时会停止时钟。延时包括:执行包括接口层,到数据库服务器的网络延迟,数据库的执行时间。不包括用于控制吞吐量的延迟。就是说,如果你指定目标是每秒 10 次操作(单线程)Client 会在每 100ms 仅执行 1 次操作。如果操作耗费了 12ms,Client 会在下一次操作前额外等待 88ms。然而,报告延时不会包括这个等待时间,报告会显示延迟是 12ms 而不是 100.

英文原文:YCSB

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-22发表,共计7944字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中