比较Apache Cassandra的压力测试工具
对Apache Cassandra进行基准测试和压力测试是操作人员和开发人员都定期进行的重要演习。
测试的方法五花八门,从“看看我的代码比其他人的代码好多少”,到“我需要什么条件才能运行这个?”, 以及“这将为我节省多少钱?”,以及我的最爱——“当我的集群被压测压死了时,会是什么样?”。
知道您想实现的目标以及如何解释测试的结果,这些都是巨大挑战的一部分。我们希望通过介绍以下这些可用的工具,会使您的工作变得容易一些。
这篇文章将研究并比较以下三种压测工具:
借助这三个工具,我们将介绍一些基本用例:
-
生成负载
-
使用真实集群
-
迭代和线程数
-
可观察性
-
批处理大小和重写操作
-
预定义的工作负载
-
自定义的工作负载
-
客户端并发竞争和服务器饱和
这些用例中所使用的工具的版本是:对于cassandra-stress是3.11.6,对于tlp-stress是4.0.0,对于nosqlbench是3.12.77。
01 生成负载
有时,您想要做的只是生成一些负载或数据。如果我们只是想看到一个Cassandra节点在正常运行某个任务,这种测试方法非常有用。我们可能只需要提高CPU负载或在磁盘上生成一些commitlog、memtables或sstables。
每个工具都会为这些测试生成稍微不同的负载配置:
$ cassandra-stress write
在初始的50k写入预热之后,执行超过一百万次的写入,从四个线程开始,迭代多次并增加客户端中使用的线程数。
$ tlp-stress run BasicTimeSeries -i 1M
精确地以9:1的读写比例执行一百万个的请求。
$ nb cql-iot write_cl=LOCAL_ONE
在预热阶段执行1千万次写入,然后以9:1的读写比例进行1千万次请求。
这些测试全部使用Java驱动程序和一致性级别LOCAL_ONE,来向一个本机(localhost)上的Cassandra节点执行写操作。
不过它们在数据模型上还是有所不同——Cassandra-stress使用简单的键值表,而tlp-stress和nosqlbench则使用时间序列的数据模型。
02 使用真实集群
这一部分与以上生成任何负载或数据的操作基本相同,不过现在您有一个具体的目标集群来进行测试。
$ cassandra-stress write -node cassandra1 $ tlp-stress run BasicTimeSeries --host cassandra1 $ nb cql-iot host=cassandra1
注意:使用这些压力工具中的任何一个时,您都无需指定多个主机。这些是传递给Java驱动程序的联系人主机(contact host),与编写的应用程序不同。
在编写的应用程序中,为了在部署和启动过程中的可靠性,您需要指定多个联系人主机。而在调用压力工具时,您一般会只会需要指定单个联系人主机来启动和运行。
03 迭代和线程数
下面展示了在不同的压测工具中,如何指定迭代数和线程数。
$ cassandra-stress write n=100000 -rate threads=16 $ tlp-stress run BasicTimeSeries -n 100k -t 16 $ nb cql-iot write_cl=LOCAL_ONE main-cycles=100k threads=16
04 可观测性
即使是有设计合理的工作负载,对于基准测试来说结果远不止是吞吐量那么简单。我们想看看随着时间的推移,集群究竟如何运作,这也许包括从流量峰值到Cassandra可能执行的许多后台操作。仔细研究Cassandra的性能将有助于长远规划一个健康而稳定的集群,这个时间将超出我们可以做基准测试的时间范围。
1)cassandra-stress
$ cassandra-stress write -graph file=example-benchmark.html title=example revision=benchmark-0
有关此的更多信息,请阅读这篇有关cassandra-Stress和Graphs的博客文章。
2)nosqlbench
$ nb cql-iot write_cl=LOCAL_ONE --docker-metrics
然后在浏览器中打开
http://localhost:3000
请注意,这仅适用于Linux,并且要求Docker在主机上运行。
有关更多信息,请参见nosqlb官方文档
3)tlp-stress
注意:tlp-stress没有类似的观察性功能,但会在端口9501上导出Prometheus指标。
cassandra-stress提供的开箱即用的图表生成功能相当不错。对于任何慎重严肃的基准测试,您都会希望将Cassandra的指标可视化并深入了解压测工具的表现,而不仅停留在性能数字上。
05 批处理大小和重写操作
下面的调用非常有意思,因为很多Cassandra-stress的用户为之感到痛苦。在Cassandra中,unlogged batch是不正常的且不被建议使用的,除非用于位于同一分区中的几小组数据行(10-20行)。
在默认情况下,cassandra-stress会将所有分区的写入都放进同一个的批处理中,这会导致不佳且不切实际的结果。要让cassandra-stress不使用批处理是不可能的,要让cassandra-stress使用只包含单个插入的批处理也相当麻烦。
更多信息请参见此JIRA里的讨论——CASSANDRA-11105。
在已发布的Cassandra基准测试中,我们不经常看到重写(overwrite)和删除,因为这些不太容易发生。通常来说这是有道理的,因为像键值和时间序列之类的工作负载不太可能会重写数据模型。
但是,目前有很多数据模型确实需要重写和删除,这也是为什么我们想要做一下这方面的基准测试。
1)cassandra-stress
首先,请下载batch_too_large.yaml
$ cassandra-stress user profile=batch_too_large.yaml ops\(insert=1\) -insert visits=FIXED\(10M\)
2)tlp-stress
在默认情况下,tlp-stress不会像cassandra-stress一样执行unlogged batch。如果需要unlogged batch,则需要编写自己的工作负载,请参阅下文“自定义工作负载”的部分。
tlp-stress确实使删除非常容易,因其以类似于读取率参数的方式处理删除动作。下面的命令行将使10%的操作删除以前写入的数据。
$ tlp-stress run KeyValue --deletes 0.1
tlp-stress的重写方式与cassandra-stress相似。它将在100个分区(partition)上写入10万次操作。如果没有聚类键,则每个分区上的重写量大约为1k。
$ tlp-stress run KeyValue -p 100 -n 100k
3)nosqlbench
通过提供比迭代计数小的分区数,nosqlbench可以以与cassandra-stress和tlp-stress相同的方式处理重写。nosqlbench当前不提供任何删除操作或unlogged batch的示例。
使用自定义工作负载可以实现logged batch,删除操作和unlogged batch可能也可以用自定义工作负载实现。
06 预定义的工作负载
1)Cassandra-stress
cassandra-stress没有内置的工作负载。如下一节所示,您需要指定user的模式并提供自己的配置。
2)tlp-stress
tlp-stress具有最广泛的工作负载类型。这些工作负载已在TLP中用于论证某些功能的实际局限性,并为推荐最佳生产方案提供了的实践方法。
$ tlp-stress list
Available Workloads:
AllowFiltering
BasicTimeSeries
CountersWide
KeyValue
LWT
Locking
Maps
MaterializedViews
RandomPartitionAccess
Sets
UdtTimeSeries
$ tlp-stress run CountersWide
3)nosqlbench
nosqlbench从其预定义的yaml工作负载文件中给出工作负载。在这些工作负载中,它列出了所使用的不同阶段,这些阶段可以组合在一起。这些让我们一窥工作负载可以被定义得多么复杂和细致。nosqlbench还列出了非基于cql驱动程序的sequences工作负载。
$ nb --list-workloads from: cql-keyvalue.yaml
… from: cql-iot.yaml
… from: cql-iot-dse.yaml
… from: cql-tabular.yaml
… from: sequences.yaml
…
$ nb cql-tabular
07 自定义工作负载
作为生产环境可行性计划或容量规划工作的一部分的基准测试,几乎总是需要自定义的工作负载。
1)cassandra-stress
关于cassandra-stress,Zipkin项目中有一个例子。点击这里访问GitHub上的代码文件。
cassandra-stress不能一次对多个表进行基准测试,因此每个表都有单独的工作负载yaml文件,而且它们必须单独地被调用。
这里我们看到cassandra-stress不支持Zipkin的原始模式(schema),特别是用户自定义数据类型(UDT)和集合(collection),因此上面链接中的文件夹还包含一些cql文件,来创建我们可以用做压力测试的模式(schema)。
创建zipkin测试的模式
cqlsh -f zipkin2-test-schema.cql
用些数据填充该模式,并适当调整
$ cassandra-stress user profile=span-stress.yaml ops\(insert=1\) no-warmup duration=1m -rate threads=4 throttle=50/s
现在对读写混合工作负载进行基准测试,然后再适当调整
$ cassandra-stress user profile=span-stress.yaml ops\(insert=1,by_trace=1,by_trace_ts_id=1,by_annotation=1\) duration=1m -rate threads=4 throttle=50/s
从上面可以看出,在cassandra-stress里创建自定义工作负载一直是一项艰巨困难的工作。但是tlp-stress和nosqlbench在这方面有所改进,因它们使用了其它的方式。
2)nosqlbench
nosqlbench通过yaml文件提供所有工作负载的配置。对于新手来说,理清这些文件的头绪无疑有些令人畏缩,但是,利用好已有的文档,并先直接使用或微调预定义的工作负载来进行练习,掌握这些的概念的机会就很大了。
3)tlp-stress
另一方面,tlp-stress专注于用代码编写工作负载。tlp-stress是用Kotlin编写的,因此,如果您喜欢Kotlin,您会发现编写工作负载是快捷而直观的。
这里有一些现成的工作负载,大概一扫您就会发现它们很容易编写。
08 客户端并发竞争和服务器饱和
哪个基准测试工具更快?这可能听起来像是一个奇怪的问题,但却带来了一些实际的担忧。不仅要选择运行客户端的硬件或需要多少客户端,还要在获得的毫无意义的结果时意识到问题。对于基准测试来说,了解要生成的负载和所需测量的指标与工作负载本身是同样重要的。
避免服务器饱和是很重要的。任何将吞吐量提高到极限的基准测试都是没有意义的。
现实世界中的(且非常之简化的)一个对比来自于联机分析处理(OLAP)集群。这些集群就像是与Apache Spark配对的那些集群,在没有适当阈值的spark-cassandra-connector上,其吞吐量出现了类似于溜溜球上下跳动的效果——当集群饱和时,吞吐量会被卡住,然后又重新开始接受写入。
长时间且可持续进行的高吞吐量可以通过适当的调优和对吞吐量阈值的设置来实现。而测试负载下响应速度(RUL)基准时,才是我们该限制吞吐量并观察响应速度的时候。
这些问题也扩展到了客户压力工具中。不像能自行在达到预定的吞吐量阈值时对负载进行阻隔或降低的服务器,客户端的操作吞吐量是需要限制或提前计划的。
这种差异很重要,但对其进行解释超出了本文章的范围。
对于那些有兴趣的人,建议阅读这篇的文章——《在Cassandra Stress中解决Coordinated Omission》。
1)cassandra-stress
$ cassandra-stress write -rate threads=4 fixed=50/s
2)nosqlbench
nosqlbench本身没有调度程序,但是可以通过异步请求和非固定的线程数来减少Coordinated Omission。
有关nosqlbench计时术语的更多信息,请参见此处。
$ nb cql-iot cyclerate=50 async=256 threads=auto
很少有生产集群能表现出这样恒定的吞吐量,因此基准测试时不稳定的突然输出是一件很有必要的事情。目前只有nosqlbench能在进程内执行此操作。
$ nb cql-iot cyclerate=50,1.5 async=256 threads=auto
这指定了每秒50次操作的速率阈值,突发输出最高可达50%。
有关突发(Burst)的更多信息,请参见此处。
3)tlp-stress
tlp-stress不能处理Coordinated Omission。其--rate参数依赖于Google的RateLimiter且限制了吞吐量,但它没有调度程序。
09 关于文档
通过浏览以上三种工具的文档,您会很容易看到nosqlbench提供了更多的功能。虽然tlp-stress还缺失在如何实现自定义工作负载方面(或tlp-stress所指的profile)的信息,但是tlp-stress文档优雅简洁,对于初学者而言易于使用。
10 总结
cassandra-stress只对于很小一部分的基于Cassandra的应用程序而言是高级工具。它的用户体验很笨拙,使用者通常需要理解一些奇奇怪怪的代码才能使其发挥预期的作用。
tlp-stress是为替代cassandra-stress而编写的。除了不处理Coordinated Omission之外,它在各方面都达到了这一目标:易用的文档、丰富的命令行用户界面,以及易于理解和改进的代码。
nosqlbench更进了一步,旨在替代雅虎云服务基准测试(YCSB, 即Yahoo! Cloud Serving Benchmark)。它就像一个高级用户的工具,而且它优越的特性和能力使其当之无愧。我们期待在NoSQL世界中,看到越来越多的可以用来测试许多不同技术的工作负载。
Reference:
https://thelastpickle.com/blog/2020/04/06/comparing-stress-tools.html