在规模上使用Apache Kafka的20个最佳实践
Apache Kafka是一种广受欢迎的分布式流媒体平台,New Relic,Uber和Square等数千家公司使用它来构建可扩展,高吞吐量,可靠的实时流媒体系统。例如,New Relic的生产Kafka集群每秒处理超过1500万条消息,总数据速率接近1 Tbps。
Kafka在应用程序开发人员和数据管理专家中受到欢迎,因为它极大地简化了数据流的处理。但卡夫卡可以大规模复杂化。具有自动数据保留限制的高吞吐量发布 - 订阅(发布/订阅)模式如果您的消费者无法跟上您的数据流并且消息在他们看到之前消失,那么这对您没有多大帮助。同样,如果托管数据流的系统无法扩展以满足需求或者不可靠,那么您将无法入睡。
为了降低这种复杂性,我想分享20个New Relic运营可扩展,高吞吐量Kafka集群的最佳实践。
Kafka是一种高效的分布式消息传递系统,可提供内置的数据冗余和弹性,同时保留高吞吐量和可扩展性。它包括自动数据保留限制,使其非常适合将数据视为流的应用程序,并且还支持模拟键值对映射的“压缩”流。
要了解这些最佳实践,您需要熟悉一些关键术语:
- 消息: Kafka中的记录或数据单元。每条消息都有一个键和一个值,以及可选的标题。
- 制作人:制作人向Kafka 主题发布消息。生产者决定要发布哪个主题分区,可以随机(循环)或使用基于消息密钥的分区算法。
- 经纪人: Kafka在分布式系统或集群中运行。集群中的每个节点都称为代理。
- 主题:主题是发布数据记录或消息的类别。消费者订阅主题以读取写入其中的数据。
- 主题分区:主题分为多个分区,每个消息都有一个偏移量。每个分区通常至少复制一次或两次。每个分区都有一个领导者和一个或多个副本(数据的副本),这些副本存在于关注者上,可以防止代理失败。集群中的所有代理都是领导者和追随者,但是代理最多只有一个主题分区的副本。领导者用于所有读写。
- 偏移:分区内的每条消息都分配了一个偏移量,这是一个单调递增的整数,用作分区内消息的唯一标识符。
- 消费者:消费者通过订阅主题分区来读取Kafka主题的消息。消费应用程序然后处理消息以完成所需的任何工作。
- 消费者群体:消费者可以组织成逻辑消费者群体。分配主题分区以平衡组中所有使用者的分配。在消费者群体中,所有消费者都在负载均衡模式下工作; 换句话说,组中的一个消费者将看到每条消息。如果消费者离开,则将分区分配给组中的另一个消费者。这被称为再平衡。如果组中的消费者多于分区,则一些消费者将闲置。如果组中的消费者少于分区,则某些消费者将使用来自多个分区的消息。
- 滞后:当消费者无法从分区中读取消息时,消费者就会滞后。滞后表示为分区头部后面的偏移数。从滞后恢复(到“赶上”)所需的时间取决于消费者每秒消费消息的速度:
使用分区的最佳实践
- 了解分区的数据速率,以确保您拥有正确的保留空间。
分区的数据速率是产生数据的速率; 换句话说,它是平均消息大小乘以每秒消息数。数据速率决定了在给定时间内保留保留所需的保留空间(以字节为单位)。如果您不知道数据速率,则无法正确计算满足基于时间的保留目标所需的保留空间。数据速率还指定了单个消费者需要支持的最低性能而不会滞后。
- 除非您有建筑需求,否则请在编写主题时使用随机分区。
当您大规模运营时,分区之间的数据速率不均可能难以管理。这有三个主要原因:
- 首先,“热门”(更高吞吐量)分区的消费者将不得不处理比消费者群体中的其他消费者更多的消息,这可能导致处理和网络瓶颈。
- 其次,必须为具有最高数据速率的分区调整主题保留,这可能会导致主题中其他分区的磁盘使用量增加。
- 第三,在分区领导方面实现最佳平衡比简单地将领导力扩展到所有经纪人更复杂。“热”分区的重量可能是同一主题中另一个分区的10倍。
有关使用主题分区的详细信息,请参阅Kafka主题分区的有效策略。
与消费者合作的最佳实践
- 如果您的消费者运行的Kafka版本低于0.10,请升级它们。
在0.8.x版本中,消费者使用Apache ZooKeeper进行消费者群体协调,并且许多已知的错误可能导致长期运行的重新平衡甚至是重新平衡算法的失败(我们称之为“重新平衡风暴”)。在重新平衡期间,将一个或多个分区分配给使用者组中的每个使用者。在再平衡风暴中,分区所有权在消费者中不断变化,阻止任何消费者在消费方面取得实际进展。
- 调整消费者套接字缓冲区以进行高速摄取。
在Kafka 0.10.x中,参数为receive.buffer.bytes,默认为64kB。在Kafka 0.8.x中,参数为
socket.receive.buffer.bytes,默认为100kB。对于高吞吐量环境,这两个默认值都太小,特别是如果代理和消费者之间的网络 带宽延迟产品大于局域网(LAN)。对于延迟为1毫秒或更长的高带宽网络(10 Gbps或更高),请考虑将套接字缓冲区设置为8或16 MB。如果内存不足,请考虑1 MB。您还可以使用值-1,它允许底层操作系统根据网络条件调整缓冲区大小。但是,对于需要开始“热”的消费者而言,自动调整可能不会发生得足够快。
- 设计高吞吐量的消费者,在有保证的情况下实施背压。
最好只消耗你可以有效处理的东西,而不是消耗太多,以至于你的过程停止了,然后退出了消费者群体。消费者应该使用固定大小的缓冲区(参见Disruptor模式),如果在Java虚拟机(JVM)中运行,最好是在堆外使用。固定大小的缓冲区将阻止消费者将大量数据拖到堆上,JVM花费所有时间来执行垃圾收集而不是您想要实现的工作 - 即处理消息。
- 在JVM上运行使用者时,请注意垃圾回收可能对您的使用者产生的影响。
例如,长垃圾收集暂停可能导致ZooKeeper会话或者消费者组重新平衡丢失。对于代理来说也是如此,如果垃圾收集暂停时间过长,则可能会从集群中退出。
与生产者合作的最佳实践
- 配置您的生产者等待确认。
这就是生产者如何知道消息实际上已经发送到代理上的分区。在Kafka 0.10.x中,设置为acks; 在0.8.x中,它是request.required.acks。Kafka通过复制提供容错功能,因此单个节点的故障或分区领导的更改不会影响可用性。如果您将生产者配置为没有ack(也称为“fire and forget”),则消息可能会无声地丢失。
- retries在您的生产者上配置。
默认值为3,通常太低。正确的价值取决于您的申请; 对于无法容忍数据丢失的应用,请考虑Integer.MAX_VALUE(有效,无限)。这可以防止领导分区的代理无法立即响应生产请求。
- 对于高通量生产,调缓冲器大小
,特别是buffer.memory与batch.size(以字节计)。因为batch.size是每分区设置,所以生产者性能和内存使用可以与主题中的分区数相关联。这里的值取决于几个因素:生产者数据速率(消息的大小和数量),生成的分区数以及可用的内存量。请记住,较大的缓冲区并不总是更好,因为如果生产者由于某种原因而停顿(例如,一个领导者通过确认响应较慢),在堆上缓存更多数据可能会导致更多垃圾收集。
- 检测应用程序以跟踪指标
例如生成的消息数,平均生成的消息大小和消耗的消息数。
与经纪人合作的最佳实践
- 压缩的主题需要您的代理的内存和CPU资源。
日志压缩需要代理上的堆(内存)和CPU周期才能成功完成,并且失败的日志压缩会使代理处于无限增长的分区的风险中。您可以调整
log.cleaner.dedupe.buffer.size和log.cleaner.threads编写代理,但请记住,这些值会影响代理的堆使用情况。如果代理抛出OutOfMemoryError异常,它将关闭并可能丢失数据。缓冲区大小和线程数将取决于要清理的主题分区的数量以及这些分区中的消息的数据速率和密钥大小。从Kafka版本0.10.2.1开始,监视日志清理程序日志文件中的ERROR条目是检测日志清理程序线程问题的最可靠方法。
- 监控您的经纪人的网络吞吐量。
确保使用发送(TX)和接收(RX)以及磁盘I / O,磁盘空间和CPU使用率来执行此操作。容量规划是维护集群性能的关键部分。
- 在集群中的代理之间分配分区领导。
领导力需要大量的网络I / O资源。例如,当使用复制因子3运行时,领导者必须接收分区数据,将两个副本传输到副本,再传输给许多消费者想要使用该数据。因此,在这个例子中,作为领导者,在使用的网络I / O方面,作为关注者的成本至少是其四倍。领导者也可能必须从磁盘读取; 粉丝只写。
- 不要忽视监视您的代理以获得同步副本(ISR)缩减,重复不足的分区和不受欢迎的领导者。
这些是群集中潜在问题的迹象。例如,单个分区的频繁ISR收缩可能表明该分区的数据速率超过了领导者为消费者和副本线程提供服务的能力。
- 根据需要修改Apache Log4j属性。
Kafka代理日志记录可能会占用过多的磁盘空间。但是,不要完全放弃日志记录 - 代理日志可能是在事件发生后重建事件序列的最佳方式,有时也是唯一方式。
- 禁用自动主题创建或建立有关清除未使用主题的明确策略。
例如,如果x天没有看到任何消息,请考虑主题已解除,并将其从群集中删除。这样可以避免在群集中创建您必须管理的其他元数据。
- 对于持续的高吞吐量代理,请提供足够的内存以避免从磁盘子系统读取。
应尽可能直接从操作系统的文件系统缓存中提供分区数据。但是,这意味着您必须确保您的消费者能够跟上; 滞后的消费者将迫使代理从磁盘读取。
- 对于具有高吞吐量服务级别目标(SLO)的大型群集,请考虑将主题隔离到代理的子集。
您如何确定要隔离的主题取决于您的业务需求。例如,如果您有多个使用相同群集的联机事务处理(OLTP)系统,则将每个系统的主题隔离到代理的不同子集可以帮助限制事件的潜在爆炸半径。
- 使用具有较新主题消息格式的旧客户端(反之亦然)会在代理
客户端转换格式时对代理程序施加额外负担。尽可能避免这种情况。
- 不要认为在本地台式机上测试代理是代表您在生产中看到的性能。
使用复制因子1对分区的环回接口进行测试是与大多数生产环境完全不同的拓扑。通过环回可以忽略网络延迟,并且在不涉及复制时,接收领导确认所需的时间可能会有很大差异。
其他资源
希望这些技巧能让您思考如何更有效地使用Kafka。如果您希望增加Kafka的专业知识,请查看Kafka文档的操作部分,其中包含有关操作集群的有用信息,并借鉴了开发Kafka的LinkedIn的经验。此外,Confluent定期进行和发布在线讲座,这对于了解Kafka的更多信息非常有帮助。