Apache Cassandra 4.0已经发布了Beta版,这是第一个支持JDK 11及更高JDK版本的Cassandra版本。

 
时延对于Apache Cassandra用户来说是个显而易见的关注点,所以大家对JDK 11中引入的全新低时延垃圾收集器ZGC(Z Garbage Collector)寄予厚望。
 
我们将看到Cassandra 4.0带来了强大的性能改进,而一些新的垃圾收集器(ZGC、尤其是Shenandoah)的上线很大程度上加强了这些提升改进的效果。
 
经作者测试,Cassandra 4.0在吞吐量和时延方面都有25%到30%的提升。所以在使用相同的垃圾收集器时,Cassandra 4.0可以很轻易地打败Cassandra 3.11.6。

 
01 测试方法
 
下面进行的基准测试是用tlp-cluster在AWS中生成并配置Apache Cassandra集群的,并用tlp-stress来进行负载生成和指标收集工作的。
 
所有在本测试中用到的工具都是开源的,并且只要拥有一个AWS账号,任何人都可以很容易地复现本次测试的过程和结果。
 
本测试中的集群中有三个r3.2xlarge实例作为节点,另有一个c3.2xlarge实例作为压测节点。
 
除了垃圾收集和堆内存设置外,我们使用了Apache Cassandra的默认设置。
 
集群的生成和配置是由最新版本的tlp-cluster完成的。除此之外,我们还添加了一些辅助脚本(helper script),从而可以将Reaper和Medusa的集群生成和安装过程自动化。
 
在根据文档安装并配置好tlp-cluster工具之后,你就可以随时创建跟我们一样的 用来做基准测试的Cassandra集群了。
 
# 3.11.6 CMS JDK8
build_cluster.sh -n CMS_3-11-6_jdk8 -v 3.11.6 --heap=16 --gc=CMS -s 1 -i r3.2xlarge --jdk=8 --cores=8 # 3.11.6 G1 JDK8
build_cluster.sh -n G1_3-11-6_jdk8 -v 3.11.6 --heap=31 --gc=G1 -s 1 -i r3.2xlarge --jdk=8 --cores=8 # 4.0 CMS JDK11
build_cluster.sh -n CMS_4-0_jdk11 -v 4.0~alpha4 --heap=16 --gc=CMS -s 1 -i r3.2xlarge --jdk=11 --cores=8 # 4.0 G1 JDK14
build_cluster.sh -n G1_4-0_jdk14 -v 4.0~alpha4 --heap=31 --gc=G1 -s 1 -i r3.2xlarge --jdk=14 --cores=8 # 4.0 ZGC JDK11
build_cluster.sh -n ZGC_4-0_jdk11 -v 4.0~alpha4 --heap=31 --gc=ZGC -s 1 -i r3.2xlarge --jdk=11 --cores=8 # 4.0 ZGC JDK14
build_cluster.sh -n ZGC_4-0_jdk14 -v 4.0~alpha4 --heap=31 --gc=ZGC -s 1 -i r3.2xlarge --jdk=14 --cores=8 # 4.0 Shenandoah JDK11
build_cluster.sh -n Shenandoah_4-0_jdk11 -v 4.0~alpha4 --heap=31 --gc=Shenandoah -s 1 -i r3.2xlarge --jdk=11 --cores=8  
注意:为了在基准测试中控制变量,整个测试中我们会同用一组EC2实例进行测试。
 
适当地使用下面的脚本,就可以完成Cassandra 3.11.6到Cassandra 4.0~alpha4的升级以及不同版本JDK的置换:
#!/usr/bin/env bash

OLD=$1
NEW=$2
curl -sL https://github.com/shyiko/jabba/raw/master/install.sh | bash
. ~/.jabba/jabba.sh
jabba uninstall $OLD
jabba install $NEW
jabba alias default $NEW
sudo update-alternatives --install /usr/bin/java java ${JAVA_HOME%*/}/bin/java 20000
sudo update-alternatives --install /usr/bin/javac javac ${JAVA_HOME%*/}/bin/java

  

在调用JDK版本管理工具jabba时,可以使用以下JDK值:
  • openjdk@1.11.0-2
  • openjdk@1.14.0
  • openjdk-shenandoah@1.8.0
  • openjdk-shenandoah@1.11.0
OpenJDK 8已经用Ubuntu的apt工具安装完成。
 
下面是在基准测试中,在不同的JDK版本下,java -version的输出结果:
  • jdk8
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (build 1.8.0_252-8u252-b09-1~18.04-b09)
OpenJDK 64-Bit Server VM (build 25.252-b09, mixed mode)
  • jdk8 with Shenandoah
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)
  • jdk11 with Shenandoah
openjdk version "11.0.8-testing" 2020-07-14
OpenJDK Runtime Environment (build 11.0.8-testing+0-builds.shipilev.net-openjdk-shenandoah-jdk11-b277-20200624)
OpenJDK 64-Bit Server VM (build 11.0.8-testing+0-builds.shipilev.net-openjdk-shenandoah-jdk11-b277-20200624, mixed mode)
  • jdk14
openjdk version "14.0.1" 2020-04-14
OpenJDK Runtime Environment (build 14.0.1+7)
OpenJDK 64-Bit Server VM (build 14.0.1+7, mixed mode, sharing)

 
02 CMS
 
CMS (Concurrent Mark Sweep)收集器是目前Apache Cassandra默认的垃圾收集器。由于它在JDK 14中被移除了,所以所有的测试都是基于JDK 8或JDK 11进行的。
 
下面的设置被用于CMS的基准测试:
 -XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:+CMSParallelRemarkEnabled
-XX:SurvivorRatio=8
-XX:MaxTenuringThreshold=1
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSWaitDuration=10000
-XX:+CMSParallelInitialMarkEnabled
-XX:+CMSEdenChunksRecordAlways
-XX:+CMSClassUnloadingEnabled
-XX:ParallelGCThreads=8
-XX:ConcGCThreads=8
-Xms16G
-Xmx16G
-Xmn8G

  

请注意, -XX:+UseParNewGC参数已经被从JDK 11中移除,在那之后它就变成了一个隐式参数(implicit parameter)。使用这个参数会阻止JVM的启动。
 
我们将CMS的最大堆内存(max heap)限制在16GB,否则它可能会引发major collection的长时间暂停。

 
03 G1
 
相比CMS收集器,G1GC(即Garbage-First Garbage Collector,垃圾优先型垃圾收集器)要容易配置一些,因为它可以动态调整年轻代的大小。
 
不过G1GC更适用于大型的堆内存(>=24GB)——这也就是为什么它没有成为Cassandra的默认垃圾收集器。另外,虽然它的吞吐量比CMS更好,但是它的时延比调试过的CMS要长。
 
下面的设置被用于G1的基准测试:
 -XX:+UseG1GC
-XX:G1RSetUpdatingPauseTimePercent=5
-XX:MaxGCPauseMillis=300
-XX:InitiatingHeapOccupancyPercent=70
-XX:ParallelGCThreads=8
-XX:ConcGCThreads=8
-Xms31G
-Xmx31G

  

为了对Cassandra 4.0进行基准测试,我们在运行G1测试时使用了JDK14。
 
我们使用31GB的堆内存大小,从而可以受益于压缩指针(compressed oops),并可以以最小的堆内存大小拥有最多的可寻址对象。

 
04 ZGC
 
ZGC(Z Garbage Collector)是JDK中最新的垃圾收集器,它主要的关注点是将让全世界暂停(stop-the-world)的时延缩小至10ms以内。ZGC还应该可以保证堆内存大小对暂停时间没有影响,这使得它的堆内存大小可以扩充至16TB。
 
如果这些令人期待的效果都能被满足,ZGC就使得使用堆外存储变得没有必要,而且还能简化Apache Cassandra的一些开发任务。
 
下面的设置被用于ZGC的基准测试:
 -XX:+UnlockExperimentalVMOptions
-XX:+UseZGC
-XX:ConcGCThreads=8
-XX:ParallelGCThreads=8
-XX:+UseTransparentHugePages
-verbose:gc
-Xms31G
-Xmx31G

  

我们需要用 - XX:+UseTransparentHugePages作为一种灵活变通的方式来避免在Linux里启用大内存页(page)。
 
尽管官方的ZGC文档称这可能会造成时延激增,从测试的结果来看似乎并没出现这种情况。我们也许可以使用大内存页来进行多次吞吐量测试,从而判断这种方法会对基准测试的结果有什么影响。
 
请注意,ZGC不能使用压缩指针,但是也不受“32GB阈值”的限制。我们在对ZGC的测试中,使用和在G1测试中一样的31GB的堆内存。这样,两种情况下系统空闲的内存大小就会是一样的。

 
05 Shenandoah
 
Shenandoah是一个由红帽(RedHat)开发的低时延垃圾收集器。在JDK 8和11中,它作为一个向后移植(backport)的版本存在。从Java 13开始,它就被包含在OpenJDK的主线版本里了。
 
与ZGC一样,在大多数情况下Shenandoah是个并发垃圾收集器。它的目标是让暂停时间不会随着堆内存的增大而线性增加。
 
下面的设置被用于Shenandoah的基准测试:
 
 -XX:+UnlockExperimentalVMOptions
-XX:+UseShenandoahGC
-XX:ConcGCThreads=8
-XX:ParallelGCThreads=8
-XX:+UseTransparentHugePages
-Xms31G
-Xmx31G

  

Shenandoah应该可以使用压缩指针,因此可以受益于使用比32GB稍小一些的堆。

 
06 Cassandra 4.0的JVM配置
 
Cassandra 4.0版本分别为Java 8和Java 11推出了不同的jvm.options文件。它们是:
  • conf/jvm-server.options
  • conf/jvm8-server.options
  • conf/jvm11-server.options
如果将Cassandra从3.11版本升级到4.0版本,原先已有的 jvm.options文件依然可以沿用,只要它被重命名为 jvm-server.options,并且将 jvm8-server.optionsjvm11-server.options文件移除就好。不过,这并不是值得推荐的方式.
 
值得推荐的方式是将原来的 jvm.options文件里的设置,重新应用到新的 jvm-server.optionsjvm8-server.options文件上。这些特定的Java选项文件(option file)大多是和垃圾收集的参数相关的。
 
一旦 jvm-server.optionsjvm8-server.options文件更新完毕并且就位,配置 jvm11-server.options文件以及从JDK 8转换到JDK 11就容易多了。

 
07 工作负载
 
本次基准测试中有8个线程,并将读写比例限制为80%写/20%读。tlp-stress大量使用异步的查询语句,这使得它只要有限的几个压测线程一不小心就可能会让Cassandra节点过载。在本次的负载测试中,每一个线程会一次并发地发送50个查询语句。
 
本次测试中的键空间(keyspace)的复制因子(replication factor)为3,并且所有的语句都以一致性级别LOCAL_ONE来执行。
 
对于所有垃圾收集器和Cassandra版本的测试,操作的数目都以每秒25k、40k、45k、50k的增长幅度进行,因而我们能够评估它们在不同压力水平下的性能表现。
 
下面的tlp-stress语句被使用在本测试中:
tlp-stress run BasicTimeSeries -d 30m -p 100M -c 50 --pg sequence -t 8 -r 0.2 --rate <desired rate> --populate 200000

  

所有的工作负载都运行30分钟,将5至16GB的数据装载到每个节点并考虑合理的压实负载。
 
请注意,这个测试的目的并非测评Cassandra的最优性能,因为对于不同的工作负载,可以通过很多方式进行调试出最优性能。
 
这个测试的目的也并非调试这些垃圾收集器,虽然它们其实已经暴露了很多可以针对特定工作负载提高性能的参数和选项。
 
这些基准测试想要达到的目的是:在使用大部分默认设置并且Cassandra产生同样的负载的情况下,提供一个针对不同垃圾收集器的公平比较。

 
 
08 基准测试结果
 
3.11.6 25k-40k ops/s
 
 
4.0 25k-40k ops/s
 
 
4.0 45k-50k ops/s
 
就吞吐量而言,Cassandra 3.11.6最高可达41k ops/s,而Cassandra 4.0则高达51k ops/s。两种版本都用了CMS作为垃圾收集器,而升级后的Cassandra 4.0的比Cassandra 3.11.6的提升达到了25%。
 
4.0版本中的大量性能提升都可以用来解释这个结果,尤其是关于压实(compaction)操作引发的堆内存压力问题(可查看CASSANDRA-14654作为例子)。
 
在Cassandra 3.11.6集群中的JDK 8的Shenandoah在40k ops/s的负载测试中,不仅没能实现最高的吞吐量,还出现了查询失败的情况。
 
而借助于Cassandra 4.0集群和JDK 11,Shenandoah的表现就好很多——它在这种情况下的最大吞吐量49.6k ops/s,几乎可以赶得上4.0在CMS下的吞吐量了。
 
使用JDK 8和Cassandra 3.11.6,G1和Shenandoah总体上的吞吐量都只能最高达到36k ops/s。
 
使用JDK 14和JDK 11,前者似乎让G1的表现也有些微提高——从47k/s提高到50k/s。
 
无论是使用JDK 14还是JDK 11,ZGC的吞吐量都无法与其它的垃圾回收器匹敌,最高只能到41k ops/s。
 
在Cassandra 3.11.6集群中,JDK 8的Shenandoah在中等程度的负载下,展现出了非常令人印象深刻的低时延。不过,它的性能会随着负载压力的提升而严重下降。
 
在使用CMS的情况下,Cassandra 4.0的平均p99(99百分位)值介于11ms到31ms之间,而吞吐量则高达50k ops/s。在中等程度的负载下,读操作的P99平均值在Cassandra 3.11.6中为17ms,而在Cassandra 4.0中则下降到了11.5ms。即相比之下,在时延方面Cassandra 4.0有30%的提升。
 
Cassandra 4.0在吞吐量和时延方面都有25%到30%的提升,所以在使用相同的垃圾收集器时,Cassandra 4.0可以很轻易地打败Cassandra 3.11.6。
 
值得一提的是,在Cassandra 3.11.6集群中,Shenandoah在中等程度的负载下的延迟非常低,不过它在压力下的表现使我们担心其处理突增负载的能力。
 
虽然ZGC在中等程度的负载下展现出了非常令人印象深刻的低时延,尤其是在使用JDK 14时,但是它的最高吞吐量并不能与Shenandoah相匹敌。
 
几乎在所有的负载测试中,Shenandoah的读操作时延和写操作时延的平均p99值都是最低的。Shenandoah这样低的时延再加上它在Cassandra 4.0中能达到的吞吐量,使它成为了在向Cassandra 4.0升级时,一个值得考虑的垃圾收集器。
 
在中等程度的负载下,读操作时延的平均p99值只有2.64ms本身已经是相当令人印象深刻的。在此基础上,如果你知道这些的数据是由客户端记录的,你就不得不对Shenandoah刮目相看了。
 
在大多数情况下,G1的最大p99值符合它所配置的最大暂停时间,即300ms。如果想要降低目标的暂停时间,则可能会在高负载的情况下出现不想看到的效果,甚至可能会触发更长时间的暂停。
 
在中等程度的负载下,Shenandoah的平均p99时延可以降低77%,即最高时延只有2.64ms。这对于时延敏感的用例来说会是一项重大的提升——相比使用Cassandra 3.11.6中的CMS,读操作的p99时延大幅降低了85%!
 
值得一提的是,JDK 14中的ZGC在中等程度的负载下有着良好的性能,但是遗憾的是它不能在更大的吞吐速率下保持同样的表现。我们乐观地认为ZGC会在未来的几个月内被改进,最终可能会足以与Shenandoah一较高下。

 
09 反思
 
G1通过移除对不同代的大小的调试需求得以提升Cassandra的易用性,但是 是以牺牲一定的性能为代价的。
 
新发行的Apache Cassandra 4.0带来了令人印象极为深刻的性能增强,它将会允许使用像是Shenandoah和ZGC这样的新一代垃圾收集器。这些收集器简单易用,无需太多细微精妙的调试,并且在时延问题上更为高效。
 
如果使用Cassandra 3.11.6,我们很难向你推荐Shenandoah,因为Cassandra节点在高负载情况下的表现并不如意。但是从JDK 11和Cassandra 4.0开始,Shenandoah在延迟方面有着惊人的改进,同时还能支持几乎是Cassandra数据库所能提供的最大吞吐量。
 
由于这次基准测试集中关注于特定的工作负载,你的测试结果可能会依情况而有所不同。但是对于时延敏感的用例来说,这次测试的结果让我们对Apache Cassandra的未来感到相当的乐观,因为它将为我们带来超过Cassandra 3.11.6的大幅改进。
 
下载最新的Apache 4并且自行尝试一番吧。如果你有任何反馈意见,记得通过社区邮件或是ASF Slack联系我们。 点击这里查看我们的联系方式。

技术基础 | Apache Cassandra 4.0基准测试的更多相关文章

  1. Apache Cassandra 4.0新特性介绍

    引言 大家好,我是蔡一凡,是Cassandra的贡献者之一.(虽然我不便透露我的公司名称),但目前我们公司Cassandra的部署是全世界最大的之一,Cassandra在我们公司也有很多的应用. Ca ...

  2. 【转】Apache Kylin 2.0为大数据带来交互式的BI

    本文转载自:[技术帖]Apache Kylin 2.0为大数据带来交互式的BI 编者注:Kyligence的联合创始人兼CEO Luke Han在上做题为“”的演讲. 基于Hadoop的SQL一直在被 ...

  3. AOP技术基础

    1.引言 2.AOP技术基础 3.Java平台AOP技术研究 4..Net平台AOP技术研究 2.1 AOP技术起源 AOP技术的诞生并不算晚,早在1990年开始,来自Xerox Palo Alto ...

  4. AOP技术基础(转)

    1.引言 2.AOP技术基础 3.Java平台AOP技术研究 4..Net平台AOP技术研究 2.1 AOP技术起源 AOP技术的诞生并不算晚,早在1990年开始,来自Xerox Palo Alto ...

  5. JNI技术基础(2)——从零开始编写JNI代码

    书接上文: <JNI技术基础(1)——从零开始编写JNI代码> 2.编译源程序HelloWorld.java并生成HelloWorld.class 3.生成头文件HelloWorld.h ...

  6. 《C#语言和数据库技术基础》单词必备

    <C#语言和数据库技术基础> 第一章1..NET Framework   框架2.sharp            尖锐,强烈的3.application      应用程序4.devel ...

  7. JavaWeb开发技术基础概念回顾篇

    JavaWeb开发技术基础概念回顾篇 第一章 动态网页开发技术概述 1.JSP技术:JSP是Java Server Page的缩写,指的是基于Java服务器端动态网页. 2.JSP的运行原理:当用户第 ...

  8. ajax技术基础详解

    一.概述 1.什么是ajax 可以与服务器进行[异步]交互的技术,浏览器无需刷新 2.什么时候出现ajax? -- XMLHttp 微软 1999年微软公司发布IE5版本,内嵌了ajax技术 什么时候 ...

  9. Hadoop基础-Apache Avro串行化的与反串行化

    Hadoop基础-Apache Avro串行化的与反串行化 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Apache Avro简介 1>.Apache Avro的来源 ...

  10. 现代前端技术解析:Web前端技术基础

    ​ 最近几年,越来越多的人投入到前端大军中:时至至今,前端工程师的数量仍然不能满足企业的发展需求:与此同时,互联网应用场景的复杂化提高了对前端工程师能力的要求,一部分初期前端工程师并不能胜任企业的工作 ...

随机推荐

  1. CSS3魔法堂:认识@font-face和Font Icon

    一.前言 过去我们总通过图片来美化站点的LOGO.标题.图标等,而现在我们可以通过@font-face获取另一种更灵活的美化方式. 二.看看例子 /* 定义 */ @font-face { font- ...

  2. 使用cjson进行对象的嵌套封装

    共分两个部分,1)创建json.2)解析json 1)创建嵌套json的代码 char * makeJson() { cJSON * pRoot = NULL; cJSON * pSub_1 = NU ...

  3. python 遗传算法精简版

    精简版遗传算法,算法中仅采用变异算子而没有使用交叉算子,但是进化依然很有效 from string import ascii_lowercase from random import choice, ...

  4. SSH_框架整合1

    1 WEB环境下配置Spring   因为是在WEB环境中应用Spring,所以要先配置web.xml: (1)WebContent-WEB-INF-lib包中,加入Spring包下的required ...

  5. solr5.5教程-tomcat布署

    tomcat和solr在各自官网下载,版本如下: tomcat版本:8.0.24 solr版本:5.5.0 1.solr解压后,目录结构如下: 2.tomcat的webapps里新建solr目录, 把 ...

  6. thinkphp 5.0 命名空间

    命名空间 命名空间 ThinkPHP5采用命名空间方式定义和自动加载类库文件,有效的解决了多模块和Composer类库之间的命名空间冲突问题,并且实现了更加高效的类库自动加载机制. 如果不清楚命名空间 ...

  7. nginx root、alias、location指令使用方法

    一.nginx root指令 1. Nginx配置 相关配置如下图: 通过配置root目录到"/wwwroot/html/"位置 在用虚拟主机方法,主机名称是test,需要大家配置 ...

  8. 一些遇到的Qt程序在Windows平台间移植问题整理

    今天尝试把Qt程序移植到各种虚拟机中测试,由于Qt的依赖库报告往往不能显示出全部依赖库.结果频频出现问题,好不容易全部解决了,这里给出一些套路. 首先对于Qt版本,我用过很多,最终表示现阶段推荐Min ...

  9. dos3章

    FOR命令中有一些变量,他们的用法许多新手朋友还不太了解,今天给大家讲解他们的用法! 先把FOR的变量全部列出来: ~I          - 删除任何引号("),扩展 %I     %~f ...

  10. linux关于 文件/文件夹的操作 中

    说一个关于stat函数 stat函数 表头文件:    #include <sys/stat.h> 函数定义:    int stat(const char *file_name, str ...