我们正在升级FutureStack的注册,仅到4月30日。条款和条件适用。 现在注册

使用Apache Kafka的20个最佳实践

10分钟读

Apache卡夫卡是一个广受欢迎的、成千上万的公司喜欢的分布式流媒体平台吗New Relic,超级,广场用于构建可扩展、高吞吐量和可靠的实时流媒体系统。例如,New Relic的Kafka集群每秒处理超过1500万条消息,聚合数据速率接近1 Tbps。

Kafka在应用程序开发人员和数据管理专家中很受欢迎,因为它极大地简化了数据流的处理。但是卡夫卡可以在规模上变得复杂。如果您的用户无法跟上您的数据流,并且消息在出现之前就消失了,那么具有自动数据保留限制的高吞吐量发布-订阅(pub/sub)模式不会给您带来太多好处。同样,如果系统承载数据流,您也不会有太多睡眠规模无法满足需求,或者在其他方面不可靠

为了降低复杂性,我想分享New Relic的20个用于操作可伸缩、高吞吐量Kafka集群的最佳实践。我们将这些技巧分为四类:

  1. 分区
  2. 消费者
  3. 生产商
  4. 经纪人

参见:使用Apache Kafka在New Relic进行实时事件处理

但首先,快速纲要卡夫卡和它的架构

Kafka是一个高效的分布式消息传递系统,提供内置的数据冗余和弹性,同时保持高吞吐量和可伸缩性。它包括自动数据保留限制,这使得它非常适合将数据视为流的应用程序,它还支持“压缩”流,该流为键-值对的映射建模。

要理解这些最佳实践,您需要熟悉一些关键术语:

信息:Kafka中的一种记录或数据单元。每个消息都有一个键和一个值,以及可选的头信息。

制作人:生产者发布消息到Kafka主题。生产者决定向哪个主题分区发布,是随机(轮询)还是使用基于消息密钥的分区算法。

代理:Kafka运行在分布式系统或集群。集群中的每个节点称为一个代理。

主题:主题是发布数据记录(或消息)的类别。消费者订阅主题,以便读取写入到他们的数据。

主题分区:主题被划分为多个分区,每个消息被给出一个抵消。每个分区通常至少复制一到两次。每个分区都有一个leader和一个或多个副本(数据的副本),这些副本存在于follower上,提供了防止代理失败的保护。集群中的所有broker都是leader和追随者,但是一个代理最多有一个主题分区的副本。leader用于所有的读和写。

偏移量:分区内的每条消息都被分配一个偏移量,这是一个单调递增的整数,作为分区内消息的唯一标识符。

消费者:消费者通过订阅主题分区来读取来自Kafka主题的消息。消费应用程序然后处理消息以完成所需的任何工作。

消费者群体:消费者可以被组织成逻辑消费者组。主题分区的分配是为了平衡组中所有使用者之间的分配。在一个消费者组中,所有消费者都以负载均衡模式工作;换句话说,每条消息将被组中的一个消费者看到。如果一个消费者离开了,分区将被分配给组中的另一个消费者。这被称为平衡。如果组中的消费者多于分区,则有些消费者将处于空闲状态。如果组中消费者的数量少于分区,那么一些消费者将使用来自多个分区的消息。

延迟:当使用者不能以产生消息的速度从分区读取时,它就会延迟。延迟表示为分区头后面的偏移量。从延迟(“赶上”)中恢复所需的时间取决于消费者每秒能够多快地使用消息:

时间=消息/(每秒消耗率-每秒产生率)

使用分区的最佳实践

1.了解分区的数据速率,以确保拥有正确的保留空间。分区的数据速率是向它产生数据的速率;换句话说,它是平均消息大小乘以每秒消息数。数据速率决定了需要多少保留空间(以字节为单位)来保证给定时间内的保留。如果你不知道数据率,你就不能正确计算满足基于时间的留存目标所需的留存空间。数据速率还指定了单个使用者在不延迟的情况下需要支持的最低性能。

2.除非有架构上的需要,否则在写主题时使用随机分区。当您进行大规模操作时,分区之间不均衡的数据速率可能很难管理。这有三个主要原因:首先,“热”(更高吞吐量)分区的消费者将不得不比消费者组中的其他消费者处理更多的消息,这可能导致处理和网络瓶颈。其次,必须为具有最高数据速率的分区调整主题保留的大小,这可能导致主题中其他分区的磁盘使用量增加。第三,在分区领导权方面达到最佳平衡比简单地将领导权分散到所有代理上要复杂得多。一个“热”分区的重量可能是相同主题中另一个分区的10倍。

有关如何使用主题分区的详细信息,请参见Kafka主题划分的有效策略

与消费者合作的最佳实践

3.如果您的用户运行的Kafka版本超过0.10,请升级它们。在0.8版本中。x,消费者使用Apache管理员对于消费者组协调,许多已知的bug可能导致长时间的重新平衡,甚至是重新平衡算法的失败。(我们称之为“再平衡风暴”)。在重新平衡期间,一个或多个分区被分配给消费者组中的每个消费者。在再平衡风暴中,分区所有权在消费者之间不断洗牌,阻止任何消费者在消费上取得真正的进展。

4.调整您的消费者插座缓冲高速摄取。

在卡夫卡0.10。X,参数为receive.buffer.bytes,默认为64kB。在卡夫卡0.8。X,参数为socket.receive.buffer.bytes,默认为100kB。

这两个默认值对于高吞吐量环境来说都太小了,特别是在网络的带宽延迟产品代理和消费者之间的网络比局域网(LAN)还要大。对于延迟为1毫秒或以上的高带宽网络(10gbps或更高),请考虑将套接字缓冲区设置为8或16mb。如果内存不足,请考虑1mb。您还可以使用1,它允许底层操作系统根据网络条件调整缓冲区大小。然而,对于需要“热”启动的用户来说,自动调优的速度可能不够快。

5.设计高吞吐量的消费者,在必要时实现背压;最好只消费您能够有效处理的东西,而不要消费太多以至于进程停止,然后退出消费组。消费者应该在固定大小的缓冲区中消费(参见粉碎机模式),如果运行在Java虚拟机(JVM)中,最好是堆外的。固定大小的缓冲区将防止使用者将太多的数据拉入堆,以至于JVM将所有的时间用于执行垃圾收集,而不是您想要完成的工作(即处理消息)。

6.当在JVM上运行消费者时,要注意它的影响垃圾收集可以在你的消费者身上。例如,长时间的垃圾收集暂停可能导致ZooKeeper会话丢失或消费者组重新平衡。对于代理也是如此,如果垃圾收集暂停时间太长,代理就有退出集群的风险。

与制作人合作的最佳实践

7.将生产者配置为等待确认;这就是生产者如何知道消息实际上已经到达代理上的分区。在卡夫卡0.10。X,设置为ack;在0.8。x,它的request.required.acks。Kafka通过复制提供容错,因此单个节点的故障或分区领导权的改变不会影响可用性。如果您在配置生产者时没有使用ack(也称为“立即删除”),消息可能会悄无声息地丢失。

8.配置重试在你的生产商。默认值为3.,这往往太低了。正确的值取决于你的应用程序;对于不能容忍数据丢失的应用程序,请考虑整数。MAX_VALUE(实际上,无穷)。这可以防止导致分区的代理不能立即响应生成请求的情况。

9.对于高吞吐量的生产者,调优缓冲区大小,特别是buffer.memorybatch.size(以字节计数)。因为batch.size是逐分区设置,生产者性能和内存使用可以与主题中的分区数量相关联。这里的值取决于几个因素:生产者数据速率(消息的大小和数量)、正在生成的分区的数量以及可用的内存量。请记住,更大的缓冲区并不总是更好的,因为如果生产者出于某些原因(比如,一个leader响应确认的速度较慢),在堆上缓冲更多的数据可能会导致更多的垃圾收集。

10.使用你的应用程序来跟踪指标例如产生的消息数量、平均产生的消息大小和使用的消息数量。

与代理合作的最佳实践

11.压缩主题需要代理上的内存和CPU资源。日志压实需要代理上的堆(内存)和CPU周期才能成功完成,而失败的日志压缩会使代理面临分区增长无界的风险。您可以调整log.cleaner.dedupe.buffer.sizelog.cleaner.threads但请记住,这些值会影响代理上的堆使用。如果经纪人抛出OutOfMemoryError异常时,它将关闭并可能丢失数据。缓冲区大小和线程数将取决于要清理的主题分区的数量以及这些分区中消息的数据速率和键大小。从Kafka版本0.10.2.1开始,监控log-cleaner日志文件错误条目是使用日志清理线程检测问题的最可靠的方法。

12.监视代理的网络吞吐量-发送(TX)和接收(RX) -以及磁盘I/O,磁盘空间和CPU使用。容量规划是维护集群性能的关键部分。

13.在集群中的代理之间分配分区领导。领导需要大量的网络I/O资源。例如,当使用复制因子3运行时,leader必须接收分区数据,将两个副本传输给多个副本,再传输给任何希望使用该数据的消费者。所以,在这个例子中,作为一个领导者在网络I/O使用方面的花费至少是作为一个追随者的4倍。先导可能也必须从磁盘读取;追随者只写。

14.不要忽视监视代理的同步副本(ISR)收缩、复制不足的分区和非首选的leader。这些都是集群中潜在问题的迹象。例如,单个分区的频繁ISR收缩可能表明该分区的数据速率超过了leader为消费者和副本线程提供服务的能力。

15.修改ApacheLog4j根据需要的属性;Kafka代理日志记录可能会使用过多的磁盘空间。但是,不要完全放弃日志记录——代理日志可能是最好的,有时是唯一的——在事件之后重构事件序列的方法。

16.要么禁用自动主题创建,要么建立一个关于清理未使用主题的明确策略。例如,如果x天内没有看到任何消息,则考虑停用该主题并将其从集群中删除。这将避免在集群中创建必须管理的额外元数据。

17.对于持续的、高吞吐量代理,应提供足够的内存以避免从磁盘子系统读取数据。分区数据应该尽可能直接从操作系统的文件系统缓存中提供。然而,这意味着你必须确保你的消费者能够跟上你的步伐;滞后的使用者将强制代理从磁盘读取数据。

18.对于具有高吞吐量服务级别目标(sslos)的大型集群,可以考虑将主题隔离到代理的子集。如何确定要隔离哪些主题将取决于您的业务需求。例如,如果有多个在线事务处理(OLTP)系统使用同一个集群,那么将每个系统的主题隔离到不同的代理子集可以帮助限制事件的潜在爆炸半径。

19.使用带有较新的主题消息格式的旧客户机(反之亦然)会给代理增加额外的负载当它们代表客户端转换格式时。尽可能避免这种情况。

2 o。不要认为在本地桌面机器上测试代理就能代表您在生产中看到的性能。通过使用复制因子1的环回接口对分区进行测试与大多数生产环境的拓扑结构非常不同。通过环回,网络延迟可以忽略不计,当不涉及复制时,接收leader确认所需的时间可以变化很大。

额外的资源

希望这些技巧能让你思考如何更有效地使用Kafka。如果你想增加你的Kafka专业知识,回顾操作Kafka文档的一部分,它包含了关于操作集群的有用信息,并借鉴了Kafka开发的LinkedIn的经验。此外,融合性的定期进行和公布网上谈判这对于学习更多关于Kafka的知识是很有帮助的。

最后,如果你对监控Kafka系统中的留存和复制、吞吐量和消费者延迟感兴趣,看看我们的主机集成。