CockroachDB与Scylla基准测试

2021-01-22 04:56:30

数据库空间一直是一个复杂的领域,引入了许多选项和折衷方案。在业界,最近有两类特殊的数据库NoSQL和NewSQL相互对立。但是,这两个术语是很久以前创造的。这两个数据库家族提供了超越传统数据库的扩展功能。它们也经常重叠,因此随着更多新数据库实现的诞生,今天的边界变得更加模糊。

在本文中,我们将在NoSQL中同类最佳的与在NewSQL中同类最佳的进行比较。诚然有偏见,我们选择了NoSQL。对于NewSQL,我们选择了CockroachDB。后者代表分布式SQL,该段不仅代表SQL API,而且代表分布式关系数据库模型。

显然,比较是苹果和橘子类型的。我们希望Scylla会更快-提供更低的延迟和更大的吞吐量-而CockroachDB应该具有更强的一致性并且更友好地与其SQL接口一起使用。我们的目标是提出合理的分析并为两个数据库可以解决的工作量差异定价。因此,我们不会涵盖仅由CockroachDB支持的SQL JOIN,也不会涵盖Scylla具有明显设计优势的时间序列工作负载。

CockroachDB(CRDB)是从头开始构建的,以支持全球OLTP工作负载,同时保持高可用性和强一致性。它基于Google Spanner的想法[白皮书] [2012-GDD] [2017-TT] [2017-SQL](和F1)。支持它的公司Cockroach Labs成立于2014年。

Scylla自2014年以来也一直在开发中。它以Apache Cassandra和Amazon DynamoDB为模型,支持两者的API兼容性。

Scylla是一个宽列的分布式NoSQL数据库,它使用最终的一致性模型来提供快速有效的读取和写入以及多数据中心的高可用性。

在Scylla中,所有节点都是相等的:没有领导者,关注者或副本集。而且没有单点故障。客户端应用程序可以与集群中的任何节点进行交互。这使Scylla可以线性扩展到许多节点,而不会降低性能和开销。

Scylla是用C ++进行的Cassandra重写,但是,性能的提高源于其激进的,异步的,按内核划分的设计以及对完全控制整个资源分配和执行的渴望。

计算模型与期货和承诺完全不同步,并且具有自己的任务切换机制,该机制的开发目的是每个内核每秒运行一百万个连续性(lambda函数)。在高性能数据库中,控制比效率甚至更重要。 Scylla使所有计算和IO操作都属于优先级类别。它的CPU和IO调度程序控制所有延续的执行。与诸如压缩,修复,流式传输等后台任务相比,对延迟敏感的类(如读写操作)具有更高的动态优先级。

Scylla通过将线程固定在核心上,将内存固定在分片上,或用超出其容量的IO重载文件系统/磁盘,来确保操作系统不会发挥其传统作用。压实控制器测量压实债务并动态设置压实优先级。因此,压缩控制使Log Structured Merge(LSM)树变得复杂,这是Scylla解决的问题。可以在这里以及我们的应用程序框架seastar.io上找到更多有关每核线程方法的信息。这些精确控制资源利用率的功能是Scylla另一个独特功能的背后:工作负载优先级,其中不同的工作负载可以具有不同的优先级,允许OLTP和OLAP(由Presto / Spark驱动)工作负载在服务器上同一集群中同时运行并存。相同的硬件。

Scylla使用最终的一致性模型。许多工作负载在需要可用性时并不需要强大的一致性保证。例如,在分区期间,隔离的数据中心应继续接受读取和写入。 Scylla具有使用轻量级事务(LWT)增强一致性的API。

Scylla甚至可以针对每个事务进行调整,以便您可以声明所需的一致性级别。您是否只希望即使一个节点也承认读或写(一致性级别为1或CL = 1),事务也能够成功?如果是这样,其余的节点将在适当的时间赶上。还是您想让大多数副本节点确认读或写(CL = QUORUM,LOCAL_QUORUM等)?还是希望每个副本节点都确认事务已成功完成(CL = ALL)?

在Scylla中,数据通过散列函数(分区器)尽可能均匀地分布在所有节点上,以便负载可以由群集中的所有核心平均分配并有效地进行处理。令牌环和群集拓扑配置与客户端共享。这使客户端知道数据实际所在的节点。他们可以有效地选择拥有数据的最近节点,甚至可以到达处理该节点内分区的特定cpu核心,从而最大程度地减少了额外的跃点并最大化了负载平衡。

客户可以随机选择或尽可能接近目标副本的操作协调器,然后发送其请求。存在多种策略来选择具有不同负载平衡选项的协调器。协调器将写入异步复制到多个副本。用户可以选择要读取的副本数据的数量。这使请求处理在隐式操作,IO和往返方面非常可预测。

Scylla使用了一个commitlog以及并行的memtable,SSTables等。您可以在本文中了解有关Scylla的行级缓存的更多阅读路径,以及文档中的write路径。

当数据被组织在宽列存储顶部的由行和列组成的表中时,Scylla提供了一种类似于RDBMS的自然模型。行键由分区键和可选的群集键组成。集群键定义分区内部的行顺序。分区键确定分区位置。

用户定义表模式,将数据插入行中,然后读取它。通常有一些概念,例如二级索引,物化视图,复杂数据类型,轻量级事务以及其他基于顶部的功能。

宽列数据模型与经典的RDBMS样式模型的不同之处在于,行不是一等公民,而是单元格。行由单元格组成。

尽管Scylla CQL用户语言在外观上可以与我们大多数人使用SQL时非常相似:

SELECT * FROM表; 更新表(a,b,c)值(1、2、3)Id = 0;

但是,Scylla并未为其操作提供完整的ACID语义。通常,ACID适用于交易,但让我们看一下为单个操作提供的功能:

从ACID的意义上讲,提供了一致性,如果操作保留了它们,它将保留应用程序不变式

从ACID角度来看,Scyla没有提供的是隔离。但是,如果您没有多语句跨分区事务,为什么还要隔离?如果您想对此问题进行详细的分析,可以在此处阅读Scylla的Jepsen分析—第3.4节“正常书写不孤立”,以及我们的随附文章。

数据排序禁止有效的顺序主键扫描,因为每个分区都有随机的位置。这限制了进行基于范围的JOIN操作的机会。尽管它允许顺序进行本地扫描,但这也是Scylla做出的权衡,以便从可用硬件中提供最大的性能。

基于单元的数据组织以及时间戳的非单调性阻止了LSM存储中级别的有效使用,并为行写入被撕毁提供了机会。

尽管Scylla中的所有节点都是同构的,并且集群大小调整很容易,但是通过对节点的关键范围分配来分片数据。分片不是事务性的,因此只能以串行方式完成,并且没有软件强制执行。此外,一旦设置了拓扑,这些范围就是静态的,并且可能导致碎片。我们最近宣布的Project Circe将解决这些限制。

CockroachDB是从头开始构建的分布式NewSQL数据库,以支持全球OLTP工作负载,同时保持高可用性和强一致性。

它建立在Google Spanner数据库背后的思想基础之上。 CockroachDB专注于在其高度一致的高度可用的分布式KV存储之上提供完全可序列化的ACID事务。默认情况下,它的事务从一开始就可序列化,而读取则可线性化。

它的设计与Scylla完全不同,并且可以有效地服务SQL请求。

CockroachDB的主要重点是一致性,拓扑灵活性和SQL兼容性。它提供了与Scylla相同的方式提供高可用性-具有冗余性,但在整个操作过程中保持副本的一致性。始终保持一致性意味着额外的开销。但是,CockroachDB使用不同的创新方法来提供高性能的服务质量,例如带租赁的Raft,免费的线性化,并行两阶段提交,创新的混合事务调度程序,向量化,内存中数据布局优化等等。 CockroachDB用Go语言编写,容易受到垃圾回收高峰的影响。

CockroachDB支持一致性而不是可用性。它提供了不同的选项来维持高可用性并构建混合集群拓扑。可用性基于冗余。由于可以使用Raft,所以每个ReplicaSet都需要一定数量的节点才能处于活动状态。这限制了可用性。

从结构上讲,它与Google Spanner非常相似:有序数据键空间被分为数据范围或平板电脑。数据范围副本被分组为ReplicaSet。每个ReplicaSet都有一个专用的领导者,该领导者由共识过程确定。为了达成共识,CockroachDB使用Raft进行了不同的优化。

在每个ReplicaSet中,只有一个专用节点为读取和写入提供服务。它被称为租赁者。只有租约持有人可以向ReplicaSet负责人写信。由于组中始终只有一个租约持有人,因此从中读取的内容可以线性化。

现在必须清楚,读取是廉价的并且可以线性化。反过来,写入是同步的-事务协调器始终等待,直到所有写入都将被复制,然后再提交事务。事务提交是异步的。

CockroachDB中的所有读取和写入都在事务上下文中执行。事务是关于ACID属性的交互式会话,在该会话中,客户端发送请求,然后使用commit或abort关键字完成请求。

CockroachDB提供了一个经典的关系数据模型,其中的表和行建立在基于LSM的键值存储之上。 CockroachDB与PostgreSQL有线兼容。

CockroachDB当前仅支持一种事务执行模式:SERIALIZABLE隔离。当用户需要强大的隔离保证而没有异常时,这很好。 CockroachDB不提供选择较弱的隔离模型以获得更高的性能。

为了序列化事务,CockroachDB提供了并行的两阶段提交变体和新颖的混合序列化调度程序。在最好的简单情况下,CockroachDB能够在1个往返时间(RTT)中提交事务。通常,尽管如此,它要求对每个读取和写入进行序列化检查,并等待所有写入被复制。为了自动切换数据可见性,CockroachDB在读取路径中使用间接寻址。

CockroachDB在数据放置策略上提供了最大的灵活性。用户可以控制如何在磁盘(系列)上组织数据以及如何在世界范围内拆分和分配数据。该模型支持独立的数据重新平衡(而不是环重新平衡),独立的隔离群集拓扑更改,甚至数据访问控制。

这种设计方法使CockroachDB可以灵活,无缝地控制集群成员资格。可以立即在群集中并行添加或删除节点,并且节点可以在复制第一个数据范围后立即开始提供数据。根据负载分配和资源利用率,数据拆分和重新平衡会在后台自动发生。

在数据建模中,用户具有很大的灵活性,可以按有序方式保留所有数据,或者根据其加载方式将其随机分布在键空间中。

数据副本始终保持一致状态。这提供了立即压缩LSM树中的删除逻辑删除的机会,并简化了许多操作。

在ReplicaSet中进行的写入需要共识协调,并且在这种意义上吞吐量受到限制。为了减轻这种情况,CockroachDB意味着动态数据范围的拆分和重新平衡。

初步阅读仅从租约节点提供,这意味着您不会利用其余副本。

错过负载分配并获取最新数据范围更容易。如果负载分布不均匀,那么热数据范围将影响性能。

可用性保证较弱。自动内存管理的语言隐含了开销。

总体而言,两个数据库都专注于不同的事物,并使用不同的方法来提供读写服务。但是,让我们看看他们的表现。

为了衡量性能差异,我们在AWS上为Scylla和CockroachDB运行了YCSB工作负载,其中包含两个数据集,大小分别为1B和100M密钥。所有群集均由3个i3.4xlarge AWS EC2节点(每个节点具有16个vCPU,122个GiB RAM,10GiB网络和2个1.9TiB NVMe SSD)组成,并分布在3个可用区中的单个区域(eu-north-1)( abc)具有标准复制因子(RF = 3)和几乎默认配置。

为了测量CockroachDB的性能,我们使用了带有PostgreNoSQL绑定的brianfrankcooper / YCSB 0.17.0基准测试以及将Goock编程语言的CockroachDB v20.1.6 YCSB端口提供给该数据库更好的支持。对于Scylla 4.2.0,我们使用了带有Scylla本机绑定和Token Aware平衡策略的brianfrankcooper / YCSB 0.18.0。

尽管CockroachDB官方文档指出存储容量限制为每个vCPU 150GiB,每个节点总计不超过2.5 TB,但我们并未管理[将#56362与20.1.6] [#38778与20.2.0]成功地加载1B密钥到CockroachDB群集-在大多数测试中,加载约3-5小时后,日志中出现一些严重错误,因此它没有响应。几次我们在持续30分钟的持续工作量中观察到了类似的行为。

另一个问题是负载吞吐量在3-5小时内从12K TPS下降到2.5K TPS。以每秒插入2.5K个密钥的速度加载1B密钥大约需要111个小时或4.5天。我们决定不等待它。 YugaByte也观察到类似的问题:[1B试用],[减速]和[结果]。

我们将CockroachDB的数据集大小减小到100M。加载过程耗时7个小时,最终产生了1.1TB的整体数据,后来压缩为450GiB。这7小时内的等待时间图表如下所示。

反过来,Scylla在使用1B密钥方面做得很好-Scylla在大约3个小时内加载了4.8 TB的数据(在大型压缩之前,在3.9 TB之后),并且表现出与较小数据集相同的性能。

关键观察:将数据加载到Scylla中的时间是10倍,不到使用CockroachDB所需时间的一半。 Scylla的初始数据加载效率提高了20倍以上。

来自YCSB的github:“此工作负载包含50/50的读写操作。一个应用示例是记录最近动作的会话存储。”

对于1B数据集大小,Scylla显示了在60%CPU使用率下产生120K TPS的能力,P99延迟<4.6ms,而P99 <12ms的150K TPS对于1B数据集大小。

在这个从Scylla Monitoring Stack仪表板获取的Grafana图中,您可以看到2个客户端的写入时延为600 µsec P99,读取时小于4ms P99时延,同时提供60k ops读取和60k ops写入;总计120K TPS。

在工作负载A的此示例中,CockroachDB最多产生16K TPS,P99为52ms,中间峰值达到200ms,利用率从50%到75%不等:

关键观察:Scylla处理了10倍的数据量,同时以1/4的延迟提供了9.3倍的吞吐量。

对于大型的1B关键数据集,Scylla成功地以75-80%的利用率和可观的延迟成功地为大多数工作负载提供了150K-200K TPS。 Scylla最好的结果之一是180K TPS,p99延迟小于5.5毫秒,平均负载7D的工作负载D为1B键。 200K TPS导致较小的过载,并且延迟时间约为20-60ms。

如这张Grafana图表所示,不仅性能更好,而且还显示了Scylla如何实现几乎最大的系统利用率。

例如,对于具有1B键数据集的工作负载D,Scylla展示了180K TPS,p99延迟小于5.5ms,CPU利用率仅为75%。对于大多数OSS分布式数据库系统而言,这种级别的性能可伸缩性是罕见的。

工作负载E产生的性能最差,只有10,000次运算。这是预期的,因为操作是短距离扫描而不是单个记录。在YCSB中:“应用示例:线程对话,其中每次扫描都是针对给定线程中的帖子(假定它们被线程ID聚类)”。

除非将工作负载E建模为聚类键,否则它是Scylla的反模式。 Scylla的范围分区扫描是基于令牌的,被随机放置在集群中,因此需要多个节点上的多次随机读取才能满足单个扫描请求。

即便如此,在范围扫描用例(E)中,Sylla的性能仍比CRDB高出5倍。

CockroachDB甚至在使用100M密钥数据集的情况下也证明了性能可伸缩性限制要早得多:对于工作负载A,它显示了16K TPS,p99小于52ms。最好的结果是D负载达到40K TPS,p99 <176ms,利用率为80%。负载的进一步增加不会导致任何吞吐量的增长,而只会导致等待时间及其方差的增长。

NoSQL和NewSQL模型正在相互接近,与传统的数据库产品相比,它们各自提供了更多的功能以及更好的性能和可用性。毫不奇怪,像Scylla这样的NoSQL数据库要比CockroachDB大得多地胜过分布式SQL数据库。结果并不意味着应该为每个工作负载选择Scylla / NoSQL。

借助1B密钥数据集,Scylla在处理10倍数据量的同时,吞吐量提高了5到10倍,并保持了低延迟。 CockroachDB展示了数据加载时吞吐量的下降,在YCSB工作负载期间,我们测量的吞吐量与CRDB白皮书非​​常接近,但延迟却越来越大。

许多现代工作负载并不需要强的一致性,也不能因对巨大规模的要求施加操作限制而受到束缚。这些工作负载是Scylla的理想选择。其他需要使用JOIN和排序键以及适量数据的,需要强一致性保证和事务处理或关系数据库模型的灵活性的工作负载,应考虑使用诸如CockroachDB之类的数据库。

最近在Scylla峰会上,我们宣布了Circe项目,这是一个为期12个月的路线图计划,其中包括添加了Raft共识协议,并允许对高度一致的工作负载进行重大改进。 CockroachDB最终结束了巨额融资,并改善了LSM性能。这两个数据库均受各自社区的欢迎

......