在本文中,我将介绍一项针对 Apache Kafka 环境的比较研究。最终目标是找到最有效的设置并实现最佳性价比。
我们的数据平台提供托管服务,用于构建大型数据集的分析平台,与其他市场解决方案竞争。为了保持竞争力,我们定期进行内部研究,以确定和改进我们的优势,确保获得更好的交易。本文展示了一项这样的研究。目前,我们的平台支持 AWS 和 GCP 作为云提供商。两者都提供多代计算和两种 CPU 架构(英特尔和 AMD 的 x86 以及 ARM)。我使用各种 Java 虚拟机 (JVM) 比较这些设置,以评估新版本在较新处理器上的性能。
如果您想要 TL;DR:ARM 很棒。现代昂贵的架构并不总是意味着“更好”。您可以直接跳到结果或继续了解有关方法和设置的更多信息。
我考虑过使用我们自己的服务来测试性能,但想在我们尚未支持的不同环境中进行比较。我想检查新的虚拟机、区域,甚至其他云提供商。因此,我首先实施了一个使用基线 Kafka 和不同基础容器映像的玩具项目。这样,我就可以在特定硬件上运行基准测试工具并测量性能。
我的目标是测试各种配置以确定最有趣的结果。为此,我使用测试矩阵的思想来过滤初步发现。我将使用 perf 和 eBPF 等工具深入分析这些发现,以进一步优化性能。
首先,让我们描述一下测试目标。我对 OpenJDK JVM 有丰富的经验,但如今,微软、亚马逊和其他公司提供了许多替代方案。例如,Amazon Correto 包含针对 AWS 优化的额外功能和补丁。由于我们的大多数客户都使用 AWS,因此我想将 Amazon Correto 纳入测试中,以查看这些 JVM 在该平台上的表现。
我选择了这些版本进行第一次比较:
定义版本后,我准备了一些脚本来使用Amazon Correto和OpenJDK构建 Kafka 镜像。
对于基准测试,我更改了 Kafka 设置以关注特定的性能指标。我想测试[JVM] x [instance_type] x [architecture] x [cloud_provider]的不同组合,因此尽量减少网络连接和磁盘性能的影响非常重要。我通过运行带有 tmpfs 的容器进行数据存储来实现这一点:
podman run -ti \ --network=host \ --mount type=tmpfs,destination=/tmp \ kfbench:3.6.1-21.0.2-amzn-arm64
当然,此设置不适用于生产,但隔离 CPU 和内存瓶颈是必要的。最好的方法是从测试中消除网络和磁盘影响。否则,这些因素会使结果产生偏差。
我在同一实例上使用基准测试工具来确保最小延迟和更高的可重复性。我还尝试了没有主机网络配置和使用 cgroup 隔离的虚拟网络的测试,但这些只会增加不必要的延迟并增加数据包转发的 CPU 使用率。
虽然 tmpfs 会动态分配内存,可能会导致碎片和延迟,但它足以满足我们的测试要求。我本可以使用 ramdisk,它可以静态分配内存并避免这些问题,但 tmpfs 更容易实现,并且仍能提供我们想要的见解。对于我们的目的而言,它达到了正确的平衡。
此外,我还应用了一些额外的 Kafka 设置来更频繁地从内存中清除数据:
############################# Benchmark Options ############################# # https://kafka.apache.org/documentation/#brokerconfigs_log.segment.bytes # Chaged from 1GB to 256MB to rotate files faster log.segment.bytes = 268435456 # https://kafka.apache.org/documentation/#brokerconfigs_log.retention.bytes # Changed from -1 (unlimited) to 1GB evict them because we run in tmpfs log.retention.bytes = 1073741824 # Changed from 5 minutes (300000ms) to delete outdated data faster log.retention.check.interval.ms=1000 # Evict all data after 15 seconds (default is -1 and log.retention.hours=168 which is ~7 days) log.retention.ms=15000 # https://kafka.apache.org/documentation/#brokerconfigs_log.segment.delete.delay.ms # Changed from 60 seconds delay to small value to prevent memory overflows log.segment.delete.delay.ms = 0
以下是变更的摘要:
此配置不适合生产用途,但对于我们的基准测试来说很重要,因为它可以减少不相关因素的影响。
在 DoubleCloud,截至撰写本文时,我们支持以下主要几代计算资源:
对于 Graviton 处理器,我们支持:
此外,我在 GCP 上测试了 t2a 实例,作为 Ampere Altra 上 Graviton 的替代方案。由于 AWS 的区域支持有限,我们不向客户提供这些实例,但我将它们包含在基准测试中以比较性能。如果您位于“正确”区域之一,这些实例可能是一个不错的选择。
为了进行基准测试,我开发了一个基于franz-go 库和示例的轻量级工具。此工具可以有效地饱和 Kafka,而不会成为瓶颈。
尽管librdkafka以其可靠性和流行度而闻名,但由于 cgo 存在潜在问题,我还是避免使用它。
Kafka 以其可扩展性而闻名,它允许将主题划分为多个分区,从而有效地在代理之间水平分配工作负载。然而,我专注于评估单核性能,因为我们特别关注性价比。
因此,测试利用具有单个分区的主题来充分利用各个核心功能。
每个测试用例包括两种类型:
我使用了 8 KB 的消息(比一般客户的情况要大)来完全饱和主题分区线程。
我展示了一系列图表,比较了不同的测试用例,并使用综合效率指标来评估不同的架构。该指标量化了我们可以提取到 Kafka 代理中的数百万行数据,从而直接评估了架构的成本效益。
需要注意的是,实际结果可能会因云提供商的额外折扣而有所不同。只要有可能,测试都会在法兰克福针对两家云提供商进行(如果实例类型选项受到限制,则在荷兰进行)。
在所有图表中,我都使用与提供商相同的常规名称来命名实例。实例首先按云提供商(AWS,然后是 GCP)排序,然后按代数排序:从旧到新。
完整的结果(尽管是原始形式)可在我的综合基准测试表中找到。在那里,您可以找到比我在本文中提供的更多的数据,包括延迟和带宽数字,以及不同 JVM 的比较性能。
基于 m5a 代、配备 AMD EPYC 7571 的“第一代”s1 实例可追溯到 2019 年第三季度,是我们的传统选择。它们是我们在法兰克福的选择中效率最低、速度最慢的,按需成本约为 ~0.2080 欧元/小时。过渡到较新的 s2 系列,成本约为 ~0.2070 欧元/小时,以基本相同的价格获得两倍的效率。我们鼓励客户迁移到这些更具成本效益和性能的选项,以缩短分析应用程序的查询时间和提取速度。
g1 系列基于 Graviton 2,一直以来都具有良好的性价比,但采用 AMD 处理器的较新的 s2 系列现在已能与 Apache Kafka 相媲美。尽管 g1 系列的带宽略低,价格优势也略有优势,但与较新的选项相比,它现在已被认为过时了。
搭载 Graviton 3 的 g2 系列因其卓越的效率而成为我们的首选推荐。在某些情况下,它的性能比 s2 和 i2 系列高出 39%,为几乎所有地区提供了经济高效的解决方案,使其成为大多数 Apache Kafka 用例的理想选择。鉴于 Kafka 典型的 IO 绑定特性,优化计算效率对于节省成本至关重要。我观察到采用 arm64 架构的趋势日益增长,我们近一半的集群已经利用了这项新技术。
测试表明,每款新的 AMD 或 Intel 处理器在整体吞吐量和延迟方面都有所改善。尽管如此,较新的 m6 和 m7 代产品的效率提升已趋于稳定。根据我们的测试,即使是 m7 代产品,虽然在某些地区可能提供较低的延迟,但与 g2 系列相比,其效率仍不高。
m7a 系列在低延迟应用中表现出色,在吞吐量和延迟方面超越了英特尔和前几代 AMD 产品。虽然这种架构并非普遍可用,但它反映了 AMD 在增强性能方面的进步。如果您所在地区有售,请考虑使用 m7a 以获得更出色的效果。
GCP 实例的效率通常低于 AWS 替代方案。这对我来说是一个很好的见解,因为客户通常更喜欢 GCP,因为它在分析应用中具有成本效益,从而降低了费用。我们的 sg1 系列采用 n2 标准代,与 AWS s2 系列相当。然而,我尝试将此比较扩展到其他实例类型时,受到区域可用性的限制,尤其是对于 c3 和 n2 代。
使用 GCP 的 Tau 处理器的 Arm 实例比 Graviton 2 的效率提高了 5-7%,如果您所在地区可用,它们将是一个合理的成本节省选项。尽管 GCP 对 arm 实例的支持仅限于四个区域,但它提供了与 g1 系列相当的性能和效率。
由于 Apache Kafka 集群持续使用 VM,因此利用持续使用折扣可获得高达 20% 的折扣。这使得 Ampere Altra 等较旧的计算能力在效率方面与 Graviton 3 相媲美。不过,由于可能还适用额外的 AWS 折扣,因此直接比较在这里很棘手。
我以为在 ARM 架构上使用较新的 JVM 版本会看到显著的改进。然而,看起来 openjdk-11 和 corretto-11 已经针对 ARM 进行了相当优化。由于较新版本的 Kafka 需要 Java 17 及更高版本,因此我切换到了 Java 17,这导致我们的基准测试性能提高了大约 4-8%。
此外,21.0.2-amzn 看起来很有前景,为较新的实例类型提供了额外的 10-20% 的性能提升。
我会不时进行内部研究,为我们的生产集群寻找最佳解决方案并收集有用的见解。转向 ARM 架构对托管服务有利,因为它可以节省资金并减少能源消耗。
事实证明,使用 ARM 大有裨益,它提高了 Apache Kafka 托管服务和 ClickHouse 托管服务的性能和成本效率。这项研究有助于完善我们的测试矩阵,确定最有效的环境和需要进一步优化的领域。我们一直在努力:在幕后进行调整和改进,我很乐意与社区分享我们的知识。敬请期待!