etcd、Zookeeper和Consul一致键值数据存储的性能对比

这篇博文是探索三个分布式、一致性键值数据存储软件性能的系列文章中的第一篇:etcd、Zookeeper和Consul,由etcd团队所写,可让咱们全面地了解如何评估三个分布式一致存储软件的性能。翻译过程当中不免有偏差,还请你们谅解html

一致性键值存储的用处

许多现代分布式应用程序都创建在分布式一致键值存储之上。Hadoop生态系统中的应用程序和“Netflix栈”的许多部分都使用ZookeeperConsul公开了服务发现和运行情况检查API,并支持Nomad等集群工具。Kubernetes容器编排系统,MySQLVitess水平扩展,Google Key Transparency项目以及许多其余系统都是基于etcd构建的。有了这么多关键任务集群,服务发现和基于这些一致键值存储的数据库应用程序,测量可靠性和性能是相当重要的。java

知足写性能须要的条件

理想的键值存储每秒摄取许多键,快速持久并确认每次写入,并保存大量数据。若是存储没法跟上写入,那么请求将超时,可能会触发故障转移和停机。若是写入速度很慢,那么应用程序看起来很慢。若是数据过多,存储系统可能会爬行甚至没法运行。git

咱们使用dbtester来模拟写入,并发现etcd在这些基准测试中优于相似的一致分布式键值存储软件。在较低的层面上,背后的架构决策能够更加统一和有效地利用资源,这些决策转化为在合理的工做负载和规模下可靠的良好吞吐量、延迟和总容量。这反过来又有助于使用etd的应用程序,如Kubernetes,可靠、易于监控和高效。github

性能有不少方面,本文将深刻介绍键的建立,键值的填充和存储,来讲明底层的机制。数据库

资源利用

在跳到高级性能以前,首先经过资源利用率和并发性突出键值存储行为的差别是有帮助的,写操做为验证这个问题提供了一个很好的例子。写操做必须和磁盘关联起来,由于写操做会持久键值到媒体。而后,这些数据必须跨服务器进行复制(replicate across machines),从而致使集群间大量网络流量。这些流量构成了处理写的所有开销的一部分,这会消耗CPU。最后,将键放入存储区直接利用内存获取键用户数据,并间接用于簿记(book-keeping)。apache

根据最近的一项用户调查,大多数etcd部署都使用虚拟机。为了遵照最多见的平台配置,全部的测试都在谷歌云平台计算引擎虚拟机(Google Cloud Platform Compute Engine virtual machines)上运行,而且使用Linux OS(全部虚拟机都有Ubuntu 16.10, Linux内核4.8.0-37-genericext4文件系统。咱们选择Ubuntu做为一个中立的Linux操做系统,而不是像Container Linux那样的CoreOS项目,以说明这些结果应该适用于任何类型的Linux发行版。可是,在容器Linux上收集这些基准测试将获得很是类似的结果)。每一个集群使用三个VM,足以容忍单个节点故障。每一个VM都有16个专用的vcpu30GB内存和300GB SSD,能够达到150 MB/s的持续写操做。这个配置足够强大,能够模拟来自1000个客户机的流量,这对于etcd的用例和如下资源度量所选择的目标来讲是最小的。全部的测试都进行了屡次试验,在运行之间的误差相对较小,不影响任何通常结论。etcd的使用以下图所示:后端

键值存储基准测试设置缓存

全部基准测试都使用如下软件配置:服务器

软件名称 版本 编译语言版本
etcd v3.1.0 Go 1.7.5
Zookeeper r3.4.9 Java 8 (JRE build 1.8.0_121-b13)
Consul v0.7.4 Go 1.7.5

每一个资源利用率测试都会建立一百万个具备1024字节值的惟一256字节键(one million unique 256-byte keys with 1024-byte values)。选择键长度以使用共同的最大路径长度对存储软件施加压力,选择值长度是由于它是protobuf编码的Kubernetes值的预期平均大小。虽然精确的平均键长度和值长度是与工做负载相关的,但长度表明极端之间的权衡。更精确的敏感性研究将为每一个存储软件提供更多关于最佳案例表现特征的看法,但风险更大。网络

磁盘带宽

写操做必须持久化到磁盘,他们记录共识提案(consensus proposals),压缩旧数据,并保存存储快照。在大多数状况下,写入应该以记录共识提案为主。etcd的日志(log)将protobuf编码的提议流转换为一系列预分配文件,在页面边界处同步,每一个条目都有滚动的CRC32校验和。 Zookeeper的事务日志(transaction log)相似,可是使用Adler32进行jute编码和校验和。Consul采用不一样的方法,而是记录到boltdb/bolt后端,raft-boltdb

下图显示了扩展客户端并发性如何影响磁盘写入。正如预期的那样,当并发性增长时,ext4文件系统上/proc/diskstats上的磁盘带宽会增长,以应对请求压力的增长。etcd的磁盘带宽稳定增加,它写的数据比Zookeeper还多,由于除了日志外,它还必须写boltDB。另外一方面,Zookeeper会由于写入完整的状态快照而丢失数据速率,这些完整的快照与etcd的增量和并发提交相反,后者只写入更新,而不会中止全部正在进行的操做(stopping the world)。Consul的数据率最初大于etcd,这多是因为在B+树中删除了提交的raft协议(raft proposals)而致使的写放大,而后因为花了几秒钟写快照而出现波动。

建立一百万个键时的平均服务器磁盘写入吞吐量

网络

网络是分布式键值存储的中心。客户端与键值存储集群的服务器进行通讯,集群中的服务器相互通讯。每一个键值存储都有本身的客户端协议,etcd客户端使用创建在HTTP/2之上的Protocol Buffer v3 gRPC协议,Zookeeper客户端使用自定义的流式TCP协议JuteConsul使用JSON。一样,每一个协议都有本身的TCP服务器协议。etcd peer stream protobuf编码的raft RPC提议,Zookeeper将TCP流用于有序的双向jute编码ZAB通道,Consul发布用MsgPack编码的raft RPC。

下表显示了全部服务器和客户端的总网络利用率。在大多数状况下,etcd具备最低的网络使用率,除了Consul客户端接收的数据略少。这能够经过etcdPut响应来解释,其中包含带有修订数据的标题,而Consul只是以明文true响应。ZookeeperConsul的服务器间流量多是因为传输大型快照和节省空间的协议编码较少。

使用1,000个客户端建立一百万个键时传输的总数据量

CPU

即便存储和网络速度很快,集群也必须当心处理开销。浪费CPU的机会比比皆是:许多消息必须被编码和解码,糟糕的并发控制能够对抗锁定,系统调用能够以惊人的频率进行,而且内存堆能够捶打。 因为etcdZookeeperConsul都但愿leader服务器节点处理写入,所以较差的CPU利用率能够轻松下降性能。

下图显示了在扩展客户端时使用top -b -d 1测量的服务器CPU利用率。etcd CPU利用率按预期平均和最大负载进行扩展,随着更多链接的增长,CPU负载依次增长。最引人注目的是Zookeeper的平均跌幅为700,但客户端数量增长了1000,日志报告太忙以捕捉,跳过其SyncRequestProcessor,而后建立新的日志文件,从1,073%利用率到230%。 这种降低也发生在1,000个客户端,但从平均值来看不太明显,利用率从894%上升到321%。一样,处理快照时Consul CPU利用率降低10秒,从389% CPU降至16%

用于在客户端扩展时建立一百万个键的服务器CPU使用

内存

当键值存储设计为仅管理元数据大小的数据时,大多数数据能够缓存在内存中。维护内存数据库能够提升速度,但代价是过多的内存占用可能会致使频繁的垃圾回收和磁盘交换,从而下降总体性能。当ZookeeperConsul在内存中加载全部键值数据时,etcd只保留一个小的驻留内存索引,直接经过boltdb中的内存映射文件支持其大部分数据,仅将数据保存在boltDB中会因请求分页而致使磁盘访问,但整体而言,etcd更好地考虑操做系统设施。

下图显示了在集群总内存占用量中向集群添加更多键的效果。最值得注意的是,一旦存储系统中有大量的键,etcd使用的内存量不到ZookeeperConsul的一半。Zookeeper位居第二,占据了四倍的内存,这符合仔细调整JVM堆设置的建议(recommendation)。最后,尽管Consul使用了etcd所用的boltDB,但它的内存存储(in-memory store)否认了etcd中的占用空间优点,消耗了三者中最大的内存。

建立一百万个键时的服务器内存占用

存储爆炸

随着物理资源的肯定,重点能够回归到聚合基准测试。首先,为了找到最大键提取率,系统并发性可扩展到一千个客户端。这些最佳摄取率为测量负载下的延迟提供了基础,从而衡量总的等待时间。一样,每一个系统客户端以最佳摄取速率计数,当密钥从一百万个键扩展到三百万个键时,能够经过测量吞吐量的降低来强调总容量。

吞吐量变化

随着愈来愈多的客户端同时写入集群,理想状况下,在提高以前,提取率应该稳定上升。可是,下图显示在写出一百万个键时缩放客户端数量时不是这种状况。 相反,Zookeeper(最大速率为43,458 req/sec)波动很大,这并不奇怪,由于它必须明确配置为容许大量链接。Consul的吞吐量(最大速率16,486 req/sec)能够很好地扩展,但在并发压力下会下降到低速率。etcd的吞吐量(最大速率34,747 req/sec)整体稳定,随着并发性而缓慢上升。最后,尽管ConsulZookeeper使用了更多的CPU,但最大吞吐量仍然落后于etcd

随客户端规模建立一百万个键的平均吞吐量

延迟分布

鉴于存储系统的最佳吞吐量,延迟应该是局部最小且稳定,排队效应将延迟其余并发操做。一样,理想状况下,随着键总数的增长,延迟会保持低且稳定,若是请求变得不可预测,则可能存在级联超时,抖动监视警报或故障。然而,经过下面显示的延迟测量来判断,只有etcd具备最低的平均等待时间和规模上的紧密、稳定的界限。

etcd,Zookeeper和Consul键建立延迟位数和范围

Zookeeper努力为并发客户提供最佳吞吐量,一旦它触发快照,客户端请求就会开始失败。服务器记录列表错误,例如Too busy to snap, skipping, fsync-ing the write ahead logfsync-ing the write ahead log in SyncThread: 1 took 1,038 ms which will adversely effect operation latency,最终致使leader节点丢失,Exception when following the leader。客户端请求偶尔会失败,包括zk等错误,例如zk: could not connect to a serverzk: connection closed错误。Consul报告没有错误,尽管可能应该,它经历了普遍的差别降级性能,多是因为其大量写入放大。

键总数

凭借最佳平均吞吐量达到100万个键的最大并发性,能够在容量扩展时测试吞吐量。下图显示了时间序列延迟,以及延迟峰值的对数标度,由于键被添加到存储中,最多可达300万个键。在大约50万个键以后,ZookeeperConsul延迟峰值都会增加。因为高效的并发快照,etcd没有出现尖峰,可是在一百万个键以前略有延迟。

特别值得注意的是,就在两百万个键以前,Zookeeper彻底失败了。其追随者落后,未能及时收到快照,这代表领导者选举须要长达20秒才能锁定集群。

建立300万个键时的延迟

下一步是什么

在建立一百万个或更多键时,etcd能够比ZookeeperConsul稳定地提供更好的吞吐量和延迟。此外,它实现了这一目标,只有一半的内存,显示出更高的效率。可是,还有一些改进的余地,Zookeeper设法经过etcd提供更好的最小延迟,代价是不可预测的平均延迟。

全部基准测试都是使用etcd的开源dbtester生成的。任何但愿重现结果的人均可以得到上述测试的测试用例参数。对于更简单,仅限etcd的基准测试,请尝试使用etcd3基准测试工具

编译自:Exploring Performance of etcd, Zookeeper and Consul Consistent Key-value Datastores

相关文章
相关标签/搜索