关于云计算:Apache-Kafka-基准测试每秒-200-万次写入在三台廉价机器上

45次阅读

共计 6402 个字符,预计需要花费 17 分钟才能阅读完成。

原文地址

翻译:sealos 是以 kubernetes 为内核的云操作系统发行版,3min 一键高可用装置自定义 kubernetes,500M,100 年证书,版本不要太全,生产环境稳如老狗。

我写了一篇对于 LinkedIn 如何应用 Apache Kafka 作为地方公布 - 订阅日志的博客文章,用于在应用程序、流解决和 Hadoop 数据摄取之间集成数据。

然而,要真正实现这项工作,这个“通用日志”必须是一种便宜的形象。如果您想将零碎用作地方数据中心,它必须疾速、可预测且易于扩大,以便您能够将所有数据转储到该零碎上。我的教训是,软弱或低廉的零碎不可避免地会造成一道爱护过程墙,以避免人们应用它们;易于扩大的零碎通常最终成为要害的架构构建块,因为应用它是构建事物的最简略办法。

我始终很喜爱 Cassandra 的基准测试,它显示它在 EC2 和 Google Compute Engine 上的三百台机器上每秒执行一百万次写入。我不晓得为什么,兴许这是邪恶博士的事件,但每秒做一百万件事件很乏味。

无论如何,Kafka 日志的长处之一是,正如咱们将看到的,它很便宜。每秒一百万次写入并不是什么特地大的事件。这是因为日志比数据库或键值存储要简略得多。事实上,咱们的生产集群全天每秒进行数千万次读取和写入,而且它们是在相当一般的硬件上实现的。

然而让咱们做一些基准测试并看看。

卡夫卡 30 秒

为了帮忙了解基准,让我疾速回顾一下 Kafka 是什么以及它如何工作的一些细节。Kafka 是一个分布式音讯零碎,最后是在 LinkedIn 构建的,当初是 Apache 软件基金会的一部分,并被各种公司应用。

个别设置非常简单。生产者将记录发送到保留这些记录并将它们分发给消费者的集群:

Kafka 的要害形象是主题。生产者将他们的记录公布到一个主题,消费者订阅一个或多个主题。Kafka 主题只是一个分片的预写日志。生产者将记录附加到这些日志中,消费者订阅更改。每条记录都是一个键 / 值对。密钥用于将记录调配给日志分区(除非发布者间接指定分区)。

这是一个简略的例子,一个生产者和消费者从两个分区的主题中读写。

这张图片显示了一个附加到两个分区的日志的生产者过程,以及一个从雷同日志中读取的消费者。日志中的每条记录都有一个关联的条目号,咱们称之为偏移量。消费者应用这个偏移量来形容它在每个日志中的地位。

这些分区散布在一组机器上,容许一个主题保留比任何一台机器都多的数据。

请留神,与大多数消息传递零碎不同,日志始终是长久的。收到音讯后会立刻将其写入文件系统。音讯在浏览时不会被删除,但会保留一些可配置的 SLA(比方几天或一周)。这容许在数据使用者可能须要从新加载数据的状况下应用。它还能够反对节俭空间的公布 - 订阅,因为无论有多少消费者,都有一个共享日志;在传统的消息传递零碎中,每个消费者通常都有一个队列,因而增加消费者会使数据大小翻倍。这使得 Kafka 非常适合惯例消息传递零碎范畴之外的事物,例如充当 Hadoop 等离线数据系统的管道。这些离线零碎可能仅作为周期性 ETL 周期的一部分每隔一段时间加载,

Kafka 还将其日志复制到多个服务器上以实现容错。与其余消息传递零碎相比,咱们的复制实现的一个重要架构方面是复制不是须要简单配置的外来附加组件,仅用于十分非凡的状况。相同,复制被假设为默认值:咱们将未复制的数据视为复制因子恰好为 1 的非凡状况。

生产者在公布蕴含记录偏移量的音讯时会收到确认。公布到分区的第一条记录的偏移量为 0,第二条记录的偏移量为 1,依此类推,以一直减少的程序。消费者从偏移指定的地位生产数据,并通过定期提交将其地位保留在日志中:保留此偏移以防消费者实例解体并且另一个实例须要从其地位复原。

好的,心愿这所有都有意义(如果没有,您能够在此处浏览更残缺的 Kafka 介绍)。

本基准

这个测试是针对骨干的,因为我对这个基准的性能测试做了一些改良。然而自上次残缺版本以来并没有太大变动,因而您应该会看到与 0.8.1 相似的后果。我还在应用咱们新重写的 Java producer,它比以前的 producer 客户端提供了更大的吞吐量。

我遵循了这个十分好的 RabbitMQ 基准测试的根本模板,但我涵盖了与 Kafka 更相干的场景和选项。

对于这个基准的一个疾速的哲学正文。对于将要公开报告的基准,我喜爱遵循一种我称之为“惰性基准”的格调。当您在一个零碎上工作时,您通常具备针对任何特定用例将其调整到完满的专业知识。这会导致一种基准测试,在这种测试中,您须要依据基准对配置进行大量调整,或者更糟的是,对您测试的每个场景进行不同的调整。我认为一个零碎的真正测试不是它在完满调整时的体现,而是它如何“现成”地体现。对于在具备数十个或数百个用例的多租户设置中运行的零碎尤其如此,其中为每个用例进行调整不仅不切实际而且不可能。后果,我简直保持应用服务器和客户端的默认设置。

我曾经公布了我的确切配置和命令,因而如果您有趣味,应该能够在您本人的设施上复制后果。

硬件设置

对于这些测试,我有六台机器,每台都有以下规格

六核 Intel Xeon 2.5 GHz 处理器
六个 7200 RPM SATA 驱动器
32GB 内存
1Gb 以太网
Kafka 集群设置在三台机器上。六个驱动器间接装置,没有 RAID(JBOD 款式)。其余三台机器我用于 Zookeeper 和生成负载。

三机集群不是很大,但因为咱们只测试最多三倍的复制因子,这就是咱们所须要的。应该很显著,咱们总是能够增加更多的分区并将数据分布到更多的机器上以程度扩大咱们的集群。

这个硬件实际上并不是 LinkedIn 的一般 Kafka 硬件。咱们的 Kafka 机器更靠近于运行 Kafka,但不太合乎我在这些测试中所谋求的“现成”精力。相同,我从咱们的一个 Hadoop 集群中借用了这些,它运行在咱们所有长久零碎中可能是最便宜的设施上。Hadoop 应用模式与 Kafka 十分类似,因而这是正当的做法。

好了,废话不多说,后果!

生产者吞吐量

这些测试将强调生产者的吞吐量。在这些测试期间没有运行消费者,因而所有音讯都被长久化但不被读取(稍后咱们将测试生产者和消费者的案例)。因为咱们最近重写了咱们的生产者,我正在测试这个新代码。

单生产者线程,无复制

821,557 条记录 / 秒
(78.3 MB/ 秒)
对于第一个测试,我创立了一个蕴含六个分区且没有复制的主题。而后我尽可能快地从单个线程中生成 5000 万条小(100 字节)记录。

在这些测试中关注小记录的起因是,对于消息传递零碎来说(通常)更难。如果音讯很大,很容易取得以 MB/sec 为单位的良好吞吐量,但当音讯较小时,要取得良好的吞吐量则要艰难得多,因为解决每条音讯的开销占主导地位。

在整个基准测试中,当我报告 MB/ 秒时,我只报告每秒申请的记录值大小,不包含申请的其余开销。所以理论的网络使用率比报告的要高。例如,对于一个 100 字节的音讯,咱们还将为每条音讯传输大概 22 个字节的开销(用于可选密钥、大小分隔、音讯 CRC、记录偏移量和属性标记),以及申请的一些开销(包含主题、分区、所需的确认等)。这使得咱们更难看出咱们在哪里达到了 NIC 的限度,但这仿佛比在吞吐量数字中包含咱们本人的开销字节更正当一些。因而,在上述后果中,咱们很可能使客户端机器上的 1 Gb NIC 饱和。

一个间接的察看后果是这里的原始数据比人们预期的要高得多,尤其是对于长久存储系统。如果您习惯于随机拜访数据系统,例如数据库或键值存储,您通常会冀望最大吞吐量约为每秒 5,000 到 50,000 个查问,因为这靠近于一个好的 RPC 层能够做到的速度近程申请。因为两个要害设计准则,咱们超过了这一点:

咱们致力确保咱们进行线性磁盘 I/O。这些服务器的六个便宜磁盘提供了 822 MB/ 秒的线性磁盘 I/O 总吞吐量。这实际上远远超出了咱们仅应用 1 Gb 网卡所能应用的能力。许多消息传递零碎将持久性视为会升高性能的低廉附加组件,因而应审慎应用,但这是因为它们无奈进行线性 I/O。
在每个阶段,咱们都致力于将大量数据批处理到更大的网络和磁盘 I/O 操作中。例如,在新的生产者中,咱们应用相似“组提交”的机制来确保在另一个 I/O 正在进行时发动的任何记录发送都被组合在一起。无关理解批处理重要性的更多信息,请查看 David Patterson 对于为什么“提早滞后带宽”的演示文稿。
如果您对细节感兴趣,您能够在咱们的设计文档中浏览更多相干信息。

单生产者线程,3x 异步复制

786,980 条记录 / 秒
(75.1 MB/ 秒)
这次测试和上一次齐全一样,只是当初每个分区都有三个正本(因而写入网络或磁盘的总数据是三倍)。每个服务器都在从生产者对它作为主的分区执行写入操作,以及为它作为隶属的分区获取和写入数据。

此测试中的复制是异步的。也就是说,服务器在将写入写入其本地日志后立刻确认写入,而无需期待其余正本也确认它。这意味着,如果主服务器解体,它可能会失落最初几条已写入但尚未复制的音讯。这使得音讯确认提早略微好一点,但在服务器故障的状况下会带来一些危险。

我心愿人们从中取得的要害是复制能够很快。集群的总写入容量当然要少 3 倍,复制 3 倍(因为每次写入实现 3 次),但每个客户端的吞吐量依然相当不错。高性能复制很大水平上来自咱们消费者的效率(正本实际上只不过是一个专门的消费者),我将在消费者局部探讨。

单生产者线程,3x 同步复制

421,823 条记录 / 秒
(40.2 MB/ 秒)
此测试与下面雷同,只是当初分区的主服务器在向生产者确认之前期待来自残缺同步正本集的确认。在这种模式下,咱们保障只有保留一个同步正本,音讯就不会失落。

Kafka 中的同步复制与异步复制没有实质上的区别。分区的领导者总是跟踪跟随者正本的进度以监控它们的活跃性,并且咱们永远不会向消费者收回音讯,直到它们被正本齐全确认。应用同步复制,咱们只需期待响应生产者申请,直到追随者复制它。

这种额定的提早仿佛的确会影响咱们的吞吐量。因为服务器上的代码门路十分类似,咱们能够通过将批处理调整为更踊跃一些并容许客户端缓冲更多未实现的申请来改善这种影响。然而,本着防止非凡状况调整的精力,我防止了这种状况。

三个生产者,3x 异步复制

2,024,032 条记录 / 秒
(193.0 MB/ 秒)
咱们的繁多生产者过程显然没有对咱们的三节点集群造成压力。为了减少一点负载,我当初将反复之前的异步复制测试,但当初应用在三台不同机器上运行的三个生产者负载生成器(在同一台机器上运行更多过程杯水车薪,因为咱们正在使 NIC 饱和)。而后咱们能够查看这三个生产者的总吞吐量,以更好地理解集群的总容量。

生产者吞吐量与存储数据

许多消息传递零碎的暗藏危险之一是,只有它们保留的数据适宜内存,它们就能够失常工作。当数据备份并且没有被耗费(因而须要存储在磁盘上)时,它们的吞吐量会降落一个数量级(或更多)。这意味着只有您的消费者跟上并且队列是空的,事件就可能运行良好,然而一旦它们滞后,整个消息传递层就会备份未应用的数据。备份导致数据进入磁盘,进而导致性能降落到一个速率,这意味着消息传递零碎无奈再跟上传入的数据,要么备份要么解体。这十分蹩脚,因为在许多状况下,队列的全副目标是优雅地解决这种状况。

因为 Kafka 总是长久化音讯,因而绝对于未耗费的数据量,性能是 O(1)。

为了进行试验测试,让咱们在较长时间内运行吞吐量测试,并随着存储数据集的增长绘制后果:

该图的确显示了性能上的一些差别,但因为数据大小没有影响:咱们在写入 TB 数据后的性能与前几百 MB 的性能一样好。

这种差别仿佛是因为 Linux 的 I/O 治理设施对数据进行批处理,而后定期刷新。这是咱们在咱们的生产 Kafka 设置中调整的更好一点。此处提供了无关调整 I/O 的一些阐明。

消费者吞吐量

好的,当初让咱们将注意力转向消费者吞吐量。

请留神,复制因子不会影响此测试的后果,因为无论复制因子如何,消费者都只会从一个正本中读取。同样,生产者的确认级别也无关紧要,因为消费者只读取齐全确认的音讯(即便生产者不期待齐全确认)。这是为了确保消费者看到的任何音讯在领导交接后始终存在(如果以后领导失败)。

繁多消费者

940,521 条记录 / 秒
(89.7 MB/ 秒)
对于第一个测试,咱们将在单个线程中从 6 个分区 3x 复制主题中耗费 5000 万条音讯。

Kafka 的消费者十分高效。它通过间接从文件系统获取日志块来工作。它应用 sendfile API 间接通过操作系统传输此数据,而无需通过应用程序复制此数据的开销。这个测试实际上是从日志的结尾开始的,所以它是在做真正的读 I/O。然而,在生产环境中,消费者简直齐全从操作系统页面缓存中读取,因为它正在读取刚刚由某个生产者写入的数据(因而它依然被缓存)。事实上,如果您在生产服务器上运行 I/O stat,您实际上会看到基本没有物理读取,即便正在耗费大量数据。

让消费者便宜对于咱们心愿 Kafka 做的事件很重要。一方面,复制品自身就是消费者,因而让消费者便宜会使复制品便宜。此外,这使得解决数据成为一种老本低廉的操作,因而出于可扩展性的起因,咱们不须要严格控制。

三个消费者

2,615,968 条记录 / 秒
(249.5 MB/ 秒)
让咱们反复雷同的测试,但运行三个并行的消费者过程,每个过程都在不同的机器上,并且都应用雷同的主题。

正如预期的那样,咱们看到了靠近线性的缩放(这并不奇怪,因为咱们模型中的耗费非常简单)。

生产者和消费者

795,064 条记录 / 秒
(75.8 MB/ 秒)
上述测试仅涵盖了独自运行的生产者和消费者。当初让咱们做天然的事件并将它们一起运行。实际上,咱们在技术上曾经这样做了,因为咱们的复制是通过让服务器自身充当消费者来工作的。

都一样,让咱们​​运行测试。对于这个测试,咱们将在开始为空的六个分区 3x 复制主题上运行一个生产者和一个消费者。生产者再次应用异步复制。报告的吞吐量是消费者吞吐量(显然,这是生产者吞吐量的下限)。

正如咱们所意料的那样,咱们失去的后果与咱们在仅生产者的状况下看到的基本相同——消费者相当便宜。

音讯大小的影响

我次要展现了小 100 字节音讯的性能。较小的音讯对于消息传递零碎来说是更难的问题,因为它们会放大零碎记账的开销。当咱们扭转记录大小时,咱们能够通过以记录 / 秒和 MB/ 秒为单位绘制吞吐量来显示这一点。

因而,正如咱们所料,这张图显示咱们每秒能够发送的原始记录数随着记录变大而缩小。然而,如果咱们查看 MB/ 秒,咱们会看到实在用户数据的总字节吞吐量随着音讯变大而减少:

咱们能够看到,对于 10 字节的音讯,咱们实际上是 CPU 绑定的,仅通过获取锁并将音讯排入队列以进行发送——咱们实际上无奈最大化网络。然而,从 100 字节开始,咱们实际上看到了网络饱和(只管 MB/sec 持续减少,因为咱们的固定大小的簿记字节在发送的总字节中所占的百分比越来越小)。

端到端提早
2 毫秒(中位数)
3 毫秒(第 99 个百分位)
14 毫秒(第 99.9 个百分位)
咱们曾经谈了很多对于吞吐量的问题,然而消息传递的提早是多少?也就是说,咱们发送的音讯须要多长时间能力传递给消费者?对于这个测试,咱们将创立生产者和消费者,并反复计算生产者向 kafka 集群发送音讯而后被消费者接管所需的工夫。

请留神,Kafka 仅在齐全同步的正本集确认音讯时才向消费者发送音讯。因而,无论咱们应用同步复制还是异步复制,此测试都会给出雷同的后果,因为该设置仅影响对生产者的确认。

复制此测试
如果您想在本人的机器上尝试这些基准测试,您能够。正如我所说,我大多只是应用 Kafka 附带的预打包性能测试工具,并且大多保持应用服务器和客户端的默认配置。然而,您能够在此处查看配置和命令的更多详细信息。
sealos 以 kubernetes 为内核的云操作系统发行版,让云原生简略遍及

laf 写代码像写博客一样简略,什么 docker kubernetes 通通不关怀,我只关怀写业务!

正文完
 0