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 Cassandra的简明方式——MCAC

    点击这里在GitHub上访问我们,以便深入了解DataStax的开源项目--Apache Cassandra指标收集器(Metric Collector for Apache Cassandra, o ...

  3. 技术基础 | 在Apache Cassandra中改变VNodes数量的影响

    Apache Cassandra中num_tokens的默认值在4.0版本中将会有变化!这看起来好像只是在CHANGES.txt文件中做了个小小的改动,但实际上这个改动将会对集群的日常运维有着深远的影 ...

  4. 技术基础 | 改进版的Apache Cassandra客户端请求路由

    最近我们在客户端的驱动程序中引入了一些变更,这些变更会影响传入的请求在Apache Cassandra集群内的分发方式.   新的默认负载均衡算法即将随驱动程序推出,这些算法将有助于缩短长尾延迟,并提 ...

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

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

  6. 技术基础 | 用JSON在抖音上发布动态——使用Stargate即可轻松实现

    Cassandra是世界上经受住最多实战考验的数据库,通过其快速且易于使用的数据API,让你的程序开发升级. 本文将介绍什么是Stargate以及Stargate的最新进展,如果您想快速浏览相关代码和 ...

  7. AOP技术基础

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

  8. AOP技术基础(转)

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

  9. Apache Cassandra——可扩展微服务应用程序的持久数据存储

    通过使用微服务,团队可以更快地响应变化,而无需改动整个应用程序.利用微服务,开发团队可以构建出具有鲁棒性和可扩展性的系统,从而适应当今应用程序的需求.   然而,使用微服务也带来了一系列挑战.在本文中 ...

随机推荐

  1. html 05-HTML标签图文详解(二)

    05-HTML标签图文详解(二) #本文主要内容 列表标签:<ul>.<ol>.<dl> 表格标签:<table> 框架标签及内嵌框架<ifram ...

  2. 【Tomcat】Tomcat原理与系统架构

    目录 版本: 一,目录说明 二,浏览器访问服务器的流程 三,Tomcat系统总体架构 3.1 Tomcat请求的大致流程 3.2 Servlet容器处理请求流程 3.3 Tomcat系统总体架构 四, ...

  3. 类818tu.c微信小说分销系统设计之定时模板消息源码

    近期将出个系列讲解开发过程,同时作为此系统的开发记录吧,万能的博客园,本边讲解如何发送模板消息,并且能够定时发送,下一篇讲解如何处理多个公众号的网页授权登录问题 [后台]http://xiaoshuo ...

  4. Winform 去掉 最大化 最小化 关闭按钮(不是关闭按钮变灰)终极解决办法

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  5. Gitlab + Jenkins 构建,发布一个基于Go的Gin测试项目

    部署Go项目简介 对于golang的发布,之前一直没有一套规范的发布流程,来看看之前发布流程: 方案一 • 开发者本地环境需要将环境变量文件改为正式环境配置 • 编译成可执行文件 • 发送给运维 • ...

  6. svn忽略idea生成的本地配置文件

    为根目录添加svn属性svn:global-ignores 值为 *.iml .idea 多个值之间用换行分隔

  7. 解决Idea中没有SVN标识,不能提交、更新代码

    使用idea也不久,今天从svn上down下来的项目导入idea,发现写的代码不能在idea里面更新,记录下解决方案. 步骤 1.点击VCS,然后Enable Version Control Inte ...

  8. java io 源码研究记录(一)

    Java IO 源码研究: 一.输入流 1  基类 InputStream 简介: 这是Java中所有输入流的基类,它是一个抽象类,下面我们简单来了解一下它的基本方法和抽象方法. 基本方法: publ ...

  9. device_create为何可以在/sys/class/具体类/属性文件?怎么实现的

    答案: 版本3.6.9: device_create -> device_register -> device_add -> device_add_attrs -> devic ...

  10. intellij IDEA Mybatis入门案例

    最近打算学习ssm框架  Mybatis 作为入门的第一个持久层框架,学习起来实在费劲.故写此文章作为入门案例. 先打开 IDEA建立一个Maven项目,目录结构如下: 源代码已经上传至GitHub ...