孟亚斌:压测利器NoSQLBench实用指南

点击查看演讲视频:https://www.bilibili.com/video/BV1Vt4y1D749/

-------------------

我今天向大家介绍的这个工具虽然并非是Cassandra原生包括的,但是也是一个非常有用的工具,叫做NoSQLBench。这个工具一直被DataStax内部用来做压力测试和性能测试。从今年开始,NoSQLBench变成了开源工具,可以供社区使用。这个工具最早用于Cassandra的测试,但是时至今日,其应用范围已经慢慢扩展到更多的NoSQL数据库。

今天我们会先简单介绍我个人和DataStax公司,接着我们会介绍怎么在Cassandra数据库环境下做压力测试,然后我们会详细讨论NoSQLBench的特性以及使用方法。最后如果时间允许我们可以做一个现场演示,你会更直观地看到这是一个简单高效的工具。最后我们也会有问答时间。

首先是自我介绍。我现在在美国达拉斯地区,在DataStax做主创架构师。我加入DataStax大约有三年半的时间,在这之前我也一直从事于Cassandra咨询工作。最近的五六年,我主要从事NoSQL数据库以及相关的大数据平台,比如Spark、Apache Solr、Kafka、Graph Database等等的咨询工作,这也是我一直以来的兴趣。我觉得数据库这个领域需要不断学习和钻研,这是非常有意思的。

接下来简单介绍一下Cassandra以及DataStax。

Cassandra数据库最早是由Facebook开发的,并且在2008年开源。2009年,Cassandra成为Apache基金会的孵化器项目(incubator project);2010年成为顶层项目 (top level project)。同样在2010年,DataStax现任CTO Jonathan Ellis和他在Rackspace的同事Matt Pfeil共同成立了DataStax。在Cassandra发展初期,Jonathan Ellis凭一己之力贡献了许多Cassandra项目代码,DataStax公司早期也贡献了超过80%的代码。

最近几年,一些知名公司也参与到Cassandra的发展进程中来,包括Apple和Netflix等,他们也贡献了很多代码。但是DataStax一直都是Cassandra主要的开发和支持力量。

DataStax公司提供Cassandra数据库的商用版——DataStax Enterprise,即DataStax企业数据库,简称DSE。总的来讲,DSE是一个统一的、多功能的集成平台。这个程序的核心是基于Apache Cassandra。但在此基础之上,我们有一些高级的安全管理功能、Graph Database的功能,并且结合Apache Solr实现了文本检索功能,以及结合Apache Spark实现了分析功能。

从去年下半年到今年年初,DataStax又有一些新的产品发布,比如最近上线的产品——DataStax Astra。这是一个Cassandra-as-a-service平台,即Cassandra数据库服务云平台。这是一个基于k8s的容器化的管理平台,用户无需自行创建和管理集群,只需要网页上简单的点击几下即可拥有和使用自己的Cassandra集群。

数据库作为service(服务)是一个发展方向,不只是NoSQL,包括MySQL这样的传统技术也在向这个方向发展。这种方式能够简化开发人员的工作,同时通过API gateway尽量降低开发人员管理和使用Cassandra数据库的难度。

​​

接下来我来简单介绍一下Cassandra数据库压力测试工具。

为什么要做压力测试呢?从数据库的角度来讲,主要是有三个原因——

一是评估数据库和相关系统的基准特性。在平时和高峰工作量时是否能满足性能指标,并验证系统在压力情况下的稳定性和响应时间。

二是系统容量规划。根据我个人在咨询工作中的经验,直至今日很多公司的Cassandra数据库并非在云平台上,而是在自己内部的数据中心(自己买的硬件、自己安装建立的Cassandra数据库)。在这种情况下,从一开始就要把容量规划做好。因为作为内部数据中心,无法像云平台一样灵活,无法在需要增容时现买硬件,而硬件的购买和运输通常需要数月。如果一开始容量规划没有做好,当需要扩容时并不能快速拿到硬件,这样的情况下应用程序和数据库的性能就会受到影响。如果数据库是部署在云平台,这个问题会减轻很多,但是容量规划问题也还是需要考虑的。比如逢年过节,可能会有大幅的临时的工作量的增长。在快到这个时间之前,我需要估算好需要多少额外的云平台的计算能力才能满足我的系统要求。这一点也非常重要。

最后一点是我需要评估Cassandra数据库的模型本身是否设计合理。对于Cassandra来讲,很关键的一点就是数据模型要合理,这个在我们所接触的Cassandra用户中是第一位的问题。如果Cassandra数据库的模型没有设计好,之后的应用可以说会是举步维艰。

Cassandra这个系统也有自己的挑战。

比如修理repair和压实compaction,这些与应用程序完全无关,而是Cassandra的后台操作,而这些操作会影响应用程序的性能。如何评估这些操作的对性能的影响以及如何优化相关参数来调整性能,这些都需要一个定量的评估方式,这也是为什么我们需要压力测试。

同样的,我们也需要考虑墓碑的影响。在Cassandra的数据被删除之后,它其实是软删除,会生成墓碑,而墓碑则会占用系统资源(比如增加修理和压实操作的工作量)。因为墓碑很消耗系统资源,我们也需要评估它带来的影响。

针对Cassandra数据模型本身,我们需要考虑定义的数据模型是否有不平衡的数据分区以及是否会造成过大的数据分区。如果有不平衡或过大的数据分区,整体的稳定性会变差,系统的性能也会受到影响。

除此之外还需要考虑的包括是否有轻量级事务、用户自定义数据类型UDT等等,这些都需要压力测试工具的评估,才能得到具体的数据。

传统来讲,Cassandra自带一个压力测试工具,叫做cassandra-stress。对于很多使用cassandra-stress的人来说,这个工具让他们爱恨交加。很长一段时间里,这是大家唯一可以选择的工具。当然也可以自己写压力测试工具,但是绝大多数客户都不会采用这个方式,而是希望有一个标准化的工具,而这个工具就是cassandra-stress。

cassandra-stress有两种模式。第一种是标准模式。在这种模式下,系统会自动创建一个键空间和一个表,然后它会根据用户要求按一定的模式写入数据。但是用户基本上不可以测试自己定义的数据模型。后来cassandra-stress做了一定的改进,提供了用户模式。在这种模式下,用户可以使用定制的查询语句和数据表定义。但是这种模式还是有很多限制,比如cassandra-stress只能对一个数据表进行性能测试。在很多情况下,用户会同时处理好几张数据表,但是这种情况cassandra-stress就无能为力了。另外cassandra-stress也不能处理自定义数据类型和Map映射数据类型。

 

当然,社区一直在改进cassandra-stress。但总的来讲,我认为用cassandra-stress模拟实际工作场景可能会变得非常困难。

另外一个经常被提及的压力测试工具叫做Gatling stress。Gatling stress本身是一个框架程序,它并非只面向于Cassandra,而是可以通过插件应用于各种场景。

 

Gatling stress所有的测试场景是用Scala语言代码化的,也就是说所有的测试场景都是代码,需要做什么测试就写相应的代码。而Gatling stress这个框架就会把用户写的代码运行起来。像是一些测试工具标准的操作,比如模拟有多少个并发用户或模拟多长的测试时间,插件是由框架提供的,但是测试场景本身的代码需要用户自行完成。这样的好处很明显,如果你很擅长写代码,那你的测试场景可能非常灵活非常强大。但是可能很多人对Scala语言并不熟悉,这样的话入门门槛就较高。这样就导致如果程序本身写得不是太好以至于效率不高,那么对于测试的结果也会有影响。到底是程序写得不太好还是系统性能有问题,很难清楚界定。

最后一个工具是NoSQLBench,这是一个起源于DataStax内部的压力测试工具。DataStax也用过Gatling stress插件,叫做Gatling DSE plugin。但是我个人认为NoSQLBench现在功能越来越强大,所以今天我主要介绍NoSQLBench。

NoSQLBench不仅仅是用于对Cassandra数据库进行压力测试的工具,而是一个专门用来对NoSQL生态系统进行系统性能测试的工具。

在图中,我们可以看到现在NoSQLBench支持的系统。当然,NoSQLBench可以支持的系统一直在发展,可能过几个月我们就会看到新的系统加入到这张图中。

在已经支持的系统中,核心的就是开源的Cassandra数据库和DataStax Enterprise系统,以及我们新上线的Cassandra-as-a-service的Astra云平台。同时,NoSQLBench还支持Kafka、MongoDB、基本的TCP/IP网络流量。可以说NoSQLBench是一个非常强大的工具。

我们为什么要使用NoSQLBench呢?像我们前面讲的,社区中已经有不同的压力测试工具,但是NoSQLBench提供的一些功能是其它工具没有的。

首先是基于配方的程序化的数据生成和决定性的负载行为,我后面会用图表具体解释一下。在很多情况下,如果我要做压力测试,我并不希望每次测试的数据都是随机的。如果数据完完全全是随机的,有可能造成两次测试的负载是不一样的。有时我们需要在多次测试中的负载是完全一样的,这样我们才能评估不同的参数的影响并作出相应的调整。在这点上别的工具都不是很容易实现。

另外NoSQLBench不需要用户写程序,它是基于非常直观的脚本语言,所以没有太高的入门门槛。经过我今天的介绍,我相信大家基本上可以直接拿来用了。

NoSQLBench的核心概念是什么呢?它的核心概念主要分两部分:场景定义和场景执行。

在场景定义层面,所有的场景定义其实是一个yaml文件,在这个文件中需要定义几个核心概念。

一是绑定(bindings),这是核心的数据生成的部分。二是声明(statements),这是定义核心执行语句的部分。在Cassandra的环境下,就是CQL statements。如果你了解prepared statement,这个和CQL prepared statement非常类似。三是区块(blocks),它将一些绑定和声明组合在一起,是一个用于逻辑组合的部分。另外还有执行参数(parameters)和标记(tags),能够帮助用户在运行测试时简化测试的一些元素。

在场景执行层面,我们关注的一是驱动程序/协议(driver/protocol),比如是面向Kafka的、开源版的Cassandra,或是DataStax Enterprise的。这些就是由驱动程序和协议来定义的。另外一个关键概念是周期(cycles)。简单来讲,如果我想测试一些数据写入,cycle定义了写入数据的量,比如100万、200万或是1000万。最后是线程(threads),它定义了有多少线程来执行测试场景。

下面我们给出一个例子。这是一个yaml文件的一部分,这部分用于数据表定义。这几行按照blocks, tags, phase来组织,下面接着的就是声明模版。你可以看到,这里面的一部分完全就是CQL statements。这里你可以创建多个Keyspace,多个表,都完全没有问题。

前面的一部分是用于创建数据模型,接下来这部分包括用于数据生成的bindings,我们这一页的例子里描述的是一个物联网的典型负载。简单理解,在bindings里面定义了一个key,它的value就是一个函数流,这个key是可以用到后面blocks中的CQL statements里面的。每写入一条数据,key所对应的值由函数流来生成。这是NoSQLBench最核心的部分。比如这里的sensor_name和time就是由不同的函数流来定义的。简单的讲,bindings的目的就是以一种可控的形式生成数据。

前一页可以看到phase: rampup,这是一个热身阶段。在测试开始时,memory和I/O可能都是cold冷却的。为了达到最符合实际情况的状态,我们就先做一个热身阶段,比如说先插入1万条数据,之后再过渡到主阶段。主阶段中可以定义比如100万条数据,也可以定义写和读的比例。而且这些是非常直观的、非常容易理解的。

总结一下。第一步,我们需要一个场景文件,这里面包括三个phases:模型定义、热身阶段、主负载阶段。命令行像这个幻灯片里显示的这样。比如热身阶段,你想写入一百万条记录,就把cycles设成1M (one million);在主负载阶段,如果你想写一亿条数据,可以设成一百条线程去写;当然,这个是在你的客户端执行的,如果你的客户端的CPU强大到可以支持一百条线程,那是最好的了,如果一个客户端没法负担这么大量的数据,可以用多个客户端来完成。

NoSQLBench现在已经开源,可以在GitHub下载。需要注意的是它分为两个版本,一个是针对Linux的版本(因为已经把Java运行环境打包在二进制文件里,下载后直接运行即可),另一个是在Mac和Windows环境下运行的版本(需要安装Java JDK 12+才能运行这个JAR文件)。

NoSQLBench本身有一些预定义的场景和负载,基本上用户不需要写场景文件,因为工具本身已经包含了常用的场景。比如物联网IoT场景,用户可以在命令行中直接使用copy命令,就会直接得到一个yaml文件,里面包括了常见的IoT场景的定义。用户可以在预定义场景的基础上进行调整,这样降低了用户的入门难度。

针对运行场景,用户需要指定driver,比如Kafka、Cassandra、DSE或是HTTPS。Workload就是前面定义的场景文件,host是Cassandra数据节点的IP地址或是host name。这里列举的是主要参数,还有一些别的功能强大的参数,可以在文档中查阅。

关于驱动程序类型,用户可以使用 --list-drivers 命令来查阅目前支持的驱动程序。另外像是CQL,其实它支持非常多的次级选项,用户可以根据需求进行选择。比如,pooling, socketoptions,还有,如果你的Cassandra集群是开启了用户名和密码保护的,你可以使用username/password次级选项。另外,用户也可以指定负载均衡的策略。基本上用Java应用程序直接连接Cassandra数据库时有的选项,NoSQLBench都可以提供。

下面要展开讲一下NoSQLBench最核心的部分,就是数据绑定。每一条绑定由一个绑定名和一个绑定配方组成。数据绑定是基于一个叫做虚拟数据集(virtual data)的项目。虚拟数据集也是DataStax开发的,它能保证每次绑定都是程序化的(procedural)、决定性的(deterministic),即每次测试的数据都可以保证是一致的。

对于PPT中的machine_id来说,它的输入流永远都是cycle_number(cycles命令行参数定义了数据的写入总量,假设有1万条数据,则每条数据会有一个cycle_number编号,编号会从1一直到1万)。每次这个cycle_number会做一个mod,再经过一个hash函数生成一个UUID。

在我们的例子中,如果cycles等于10,因为mod 5,则生成的数据每五个cycle一重复。也就是说,这个数据集是有确定性的、可以精准控制的。如果用以前的工具比如cassandra-stress,其实是没有办法做这样的控制的。每一次测试的数据不完全一致是会对参数和性能的调优产生影响的,这是让很多人头痛的一点。而NoSQLBench没有这样的问题。

NoSQLBench有一些命令行输出,比如在进行压力测试时可以显示进度条,方便用户知道测试的进展状况,交互性更好。另外还可以看压力测试生成的日志文件的位置和级别,以及其中包含的错误、警告或是信息。

NoSQLBench支持不同的输出方式,有很丰富的输出指标以及选项。

我个人认为,drivermetrics是最有用的选项之一,它会对连接数据库后的各种错误进行统计,包括Cassandra数据库的not available exception或是不能达到要求的consistency level。这些错误有助于用户了解Cassandra集群的工作状况。有时我们只能看到server端的指标,但是没法看到客户端的指标,而NoSQLBench可以帮助我们看到。

我们有很多现成的在线资源可以帮助大家学习和练习,包括DataStax Academy GitHub以及Katacoda NoSQL Learning Series,大家有时间可以查看一下。

原文地址:https://www.cnblogs.com/datastax/p/13450200.html