根据 Gartner 的预测,预计在 2021 年,全球终端用户在公共云服务上的支出将在 2020 年的 2700 亿美元基础上增长 23%,达到 3320 亿美元。
Kafka 的市场增长趋势也是一样的。世界各地的组织都在使用 Kafka 作为主要的流处理平台来大规模收集、处理和分析数据。随着组织的发展和壮大,数据规模也在增长,随之而来的云成本同样日益上升。
所以我们能做些什么呢?为了削减成本,我们是否可以实施一些容易实现的策略?
本文就此主题列举了一些可能会有所帮助的提示和 KIP(Kafka 改进建议)!
免责声明
这篇文章不会涵盖那些旨在降本的托管服务方法。在某些用例中,像 Confluent Cloud 这样的托管服务可能会起到作用。要获取更多信息,你可以参考 Confluent 网站上的成本效益页面。
在开始之前,我们先来了解一些基础知识。
我可以试着列出我们在使用各种云服务时花钱购买的所有组件,但这样还不如来看 Gwen Shapira 在她的文章“Apache Kafka 的成本:为 DIY 运维定价的工程师指南”中总结的内容。
我们从一些相当明显且易于量化的费用开始分析。如果你打算在 AWS 上运行 Kafka,你需要为 EC2 machines 支付费用来运行你的 broker。如果你使用像 EKS 这样的 Kubernetes 服务,你要为 节点 和服务本身(Kubernetes 主节点)付费。大多数相关的 EC2 类型都是 EBS 存储,Kubernetes 仅支持 EBS 作为一等磁盘选项,这意味着 除了 EBS 数据卷之外,你还需要为 EBS 根卷付费。还要记得,在合并 KIP-500 之前 Kafka 不只有 broker——我们还需要运行 Apache ZooKeeper,给它 算上三到五个节点及其存储的费用。我们的 Kafka 是在一个 负载均衡器(部分充当一个 NAT 层)之后运行的,并且由于每个 broker 都需要单独寻址,因此你需要 为“引导”路由和每个 broker 的路由付费。
所有这些都是固定成本,你一个字节都不向 Kafka 发送也得花这些钱。
除此之外还有网络成本。将数据导入 EC2 需要花钱,并且根据你的网络设置(VPC、私有链接或公共互联网),你可能在发送和接收数据时都要付费。如果你在不同地区或区域之间复制数据,请一定要考虑到这些成本。如果你通过 ELB 路由流量,你将为此流量支付额外费用。不要忘了算上入口和出口,并且要记住,使用 Kafka 时,你读取的数据往往是写入量的 3-5 倍。
现在我们算上了运行软件、摄取数据、存储和读取数据的成本,我们就快完成了。你还需要监控 Kafka,对吧?一定要考虑到监控(Kafka 有许多重要的指标)——无论是使用服务还是自托管,你还需要一种收集日志 并搜索它们的方法。最后这些可能成为系统中最昂贵的部分,特别是如果你有许多分区的时候,这会显著增加指标的数量。
我加粗了帖子中的要点,还有来自 Kafka 生态系统的其他一些组件在文中没有直接提到,如 Schema Registry、Connect workers,以及 CMAK 或 Cruise-Control 等工具,但这些都适用于同样的三个要素——机器、存储和网络。
虽然有更多要素是难以衡量的,例如员工工资、停机时间,甚至处理中断(也就是将系统维持在可用状态所必须完成的工作),但上面这三点是我们在使用云提供商时花钱购买的主要要素。
除了适用于几乎所有分布式系统的一些基本概念之外,随着时间的推移,Kafka 的提交者引入了一些直接或间接影响 Kafka TCO 的 KIP 和特性。
但我们还是会从显而易见的东西开始分析——
AWS 上有很多实例类型可供选择(当然,这里提到的方法也可以用在其他云提供商上)。
Kafka 可以在廉价的货架硬件上轻松运行,并且不会出什么显眼的问题。如果你在谷歌上搜索生产级 Kafka 集群的推荐实例类型,你会发现人们建议用 r4、d2 甚至 c5 与 GP2/3 或 IO2 存储搭配用于一般用途。
每种组合都有自己的优点和缺点,你可能需要根据各种权衡来找到最适合自己的选项——这些权衡包括更长的恢复时间(HDD 磁盘)、存储性价比、网络吞吐量,甚至 EBS 在极端情况下的性能下降。
但随着时间的推移,i3 和 i3en 机器得到了人们的青睐;根据我的经验,它们是迄今为止获推荐最多的高回报率大规模部署实例类型,就算你考虑到了使用非永久存储器带来的运维开销也是如此。
使用 Kafka 时,i3 和 i3en 在无数基准测试中都提供了更好的性能,并充分利用了非永久驱动器的优势(10gbps 磁盘带宽,对比 EBS 优化的 C 级实例的 875mbps)。
ScyllaDB 的这篇很棒的文章,研究了在主要瓶颈因素是存储容量的系统上使用 i3en 机器带来的显著成本优势(稍后会详细介绍):
作为降低成本的第一步,你需要重新评估你的实例类型决策:你的集群是否饱和?在什么情况下饱和?是否存在其他实例类型,可能比你第一次创建集群时选择的类型更合适?EBS 优化实例与 GP2/3 或 IO2 驱动器的混合是否真的比 i3 或 i3en 机器(及其带来的优势)有更好的性价比?
如果你不熟悉这款工具,你应该了解一下。
压缩在 Kafka 中并不新鲜,大多数用户已经知道了自己可以在 GZIP、Snappy 和 LZ4 之间做出选择。但自从KIP-110被合并进 Kafka,并添加了用于 Zstandard 压缩的压缩器后,它已实现了显著的性能改进,并且是降低网络成本的完美方式。
Zstandard 是 Facebook 的压缩算法;与其他压缩算法相比,它旨在实现更小、更快的数据压缩。
例如,使用 zstd(Zstandard)后,Shopify 获得了 4.28 倍的压缩率。关于 zstd 优势的另一个很好的例子是 Cloudflare 的“挤一挤 firehose:从 Kafka 压缩中获得最大收益”这篇文章。
这和降低成本又有什么关系呢?以生产者端略高的 CPU 使用率为代价,你将获得更高的压缩率并在线上“挤进”更多信息。
Amplitude 在他们的帖子中介绍,在切换到 Zstandard 后,他们的带宽使用量减少了三分之二,仅在处理管道上就可以节省每月数万美元的数据传输成本。
毕竟你还要支付数据传输费用,记得吗?
为了容错需求,在同一 AWS 区域内的几个可用区上分布集群是很常见的做法。
遗憾的是,我们无法通过协调让消费者的分布与他们需要消费的分区 leader 完美对齐,以避免跨区域流量和成本。参阅 KIP-392。
2015 年的 KIP-36 合并之后,机架感知就可以启用了,并且只需在配置文件中添加一行代码就可以轻松完成:
broker.rack=<rack ID as string> # For example, AWS AZ ID
在实现 KIP-392 之前,此设置仅控制副本位置(将 AZ 视为机架)。而这个 KIP 正好解决了这个麻烦,并允许你利用局部性来减少昂贵的跨 dc 流量。
一些客户端已经实现了这一更改,如果你的客户端还不支持它,这里有一个开源项目适合你周末来研究!
这一点可能看起来没那么明显,但如果你的集群不平衡,也可能会影响集群成本。
不平衡的集群可能会损害集群性能,导致某些 borker 比其他 broker 的负载更大,让响应延迟更高,并且在某些情况下会导致这些 broker 的资源饱和,从而导致不必要的扩容。
不平衡集群面临的另一个风险是在一个 broker 出故障后出现更高的 MTTR(例如当该 broker 不必要地持有更多分区时),以及更高的数据丢失风险(想象一个复制因子为 2 的主题,其中一个节点由于启动时要加载的 segment 过多,于是难以启动)。
不要让这个相对容易完成的任务去浪费金钱。你可以使用 CMAK、Kafka-Kit 等工具,更好的是 Cruise-Control,它允许你根据多个目标(容量违规、副本计数违规、流量分布等)自动执行这些任务。
听起来很明显吧?其实在友好的 Kafka 集群幕后,你可以启用或更改大量设置。
这些设置会极大地影响集群的工作方式:资源利用率、集群可用性、保证、延迟等等。
例如,行为不端的客户端会影响你的 broker 资源利用率(CPU、磁盘等)。更改你的客户端 batch.size 和 linger.ms(与业务逻辑相适应)可以显著降低集群 LoadAvg 和 CPU 使用率。
消息转换会带来处理开销,因为 Kafka 客户端和 broker 之间的消息需要转换才能被双方理解,从而导致更高的 CPU 使用率。升级你的生产者和消费者可以解决这一问题,将本来不需要用在这上面的资源释放出来。
这样的例子数不胜数。
通过适当的微调,你可以让集群更好地运作、提供更多服务、增加吞吐量、释放资源,从而避免不必要的扩容,甚至可以将集群缩小到适合你需求的大小。
阅读和处理每一行文档是一项不可能完成的任务,因此你可以先阅读其中一篇关于调整客户端和 broker 的帖子。我会推荐 Strimzi 的系列相关文章——Broker、生产者和消费者。
如前所述,使用某种压缩算法(最好是 zstd)可以极大地提高性能并节省数据传输费用。
处理压缩时,你需要面对一种新的权衡决策——CPU vs IO(压缩后文件的大小)。大多数算法提供了一些压缩级别可供选择,这会影响所需的处理能力和压缩后的数据集大小。
压缩器支持的压缩级别
到目前为止,Kafka 仅支持每种压缩器的默认压缩级别。这个问题将在 KIP-390 上得到解决,KIP-390 将随 Kafka3.0.0 一起提供。
实现这个 KIP 后,我们将能在配置中添加一行,将压缩级别设置得更高(设置到合适的级别。记住更高的级别对应更多的资源开销)
compression.type=gzip
compression.level=4 # NEW: Compression level to be used.
这个新特性针对真实世界的一个数据集(29218 个 JSON 文件,平均大小为 55.25kb)进行了测试,结果可能因编码、压缩级别的不同和由此产生的延迟而异,如下所示
分层存储
集群上所需的总存储量与主题和分区的数量、消息速率以及最重要的保留期限成正比。集群上的每个 Kafka broker 通常都有大量磁盘,于是单个集群上一般会有数十 TB 的磁盘存储。Kafka 已经成为组织中所有数据的主要入口点,让客户端不仅可以消费最近的事件,还可以根据主题保留来使用较旧的数据。
人们很可能会添加更多 broker 或磁盘,以便根据客户的需求在集群上保存更多数据。
另一种常见模式是将你的数据管道拆分为一些更小的集群,并在上游集群上设置更长的保留期限,以便在发生故障时进行数据恢复。使用这种方法时,你能完全“停止”管道,修复管道中的错误,然后流回所有“丢失”的事件,而不会丢失任何数据。
这两种情况都需要你为集群增加容量,而且通常还会向集群添加不必要的内存和 CPU,于是与将旧数据存储在外部存储的方案相比,它们的总体存储成本效率较低。具有更多节点的更大集群也增加了部署的复杂性并增加了运营成本。
为了解决这个问题,KIP-405 分层存储应运而生。
使用分层存储时,Kafka 集群配置有两层存储:本地和远程。本地层和现在是一样的,也就是使用本地磁盘——而新的远程层会使用外部存储层(如 AWS S3 或 HDFS)来存储完整的日志 segment,这会比本地磁盘便宜得多。
你能为每一层设置多个保留期限,因此对延迟更敏感且使用实时数据的服务可以从本地磁盘提供,而需要旧数据进行回填,或在事故后恢复的服务可以经济地从外部层加载数周甚至数月时间。
除了明显的磁盘成本下降(gp3 每 GB 约 0.08 美元,S3 约 0.023 美元)之外,你还可以根据服务需求(主要基于计算能力而非存储)进行更准确的容量规划,独立于内存和 CPU 来扩展存储,并节省不必要的 broker 和磁盘的费用。
节省的成本是非常可观的。
你的 broker 恢复速度会更快,因为它们在启动时需要加载的本地数据要少得多。
分层存储已在 Confluent Platform 6.0.0 上可用,并将添加到 Kafka3.0 版本中。
可能你还没有听说过,在未来的版本中,Kafka 将移除其对 ZooKeeper 管理集群元数据的依赖,并移至基于 Raft 的治理模式。
这不仅将提供一种更具扩展性和健壮性的元数据管理方式,还能简化 Kafka 的部署和配置(去除外部组件),而且还消除了 Zookeeper 部署的成本。
如前所述,Kafka 不仅仅是一堆 broker,我们需要为 Zookeeper 运行三五个节点;除了实例之外,你还需要算上它们的存储和网络的成本,以及难以衡量的运营开销(例如监控、警报、升级、事件和关注)。
要降低云成本可以有很多方法。其中一些是可以在几分钟内实现的唾手可得的成果,而另一些则需要更深入的理解、尝试和试错。
这篇文章仅涵盖了降低成本的一小部分方法,但更重要的是它试图强调一个事实,即了解在云上运行 Kafka 时我们需要支付哪些费用是很重要的。
我们需要意识到,有时云成本可能会超出人们的想象。
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8