龙空技术网

Kafka灵活性的陷阱

闻数起舞 901

前言:

现时大家对“jennyapache”可能比较珍视,姐妹们都想要剖析一些“jennyapache”的相关资讯。那么小编同时在网络上网罗了一些对于“jennyapache””的相关文章,希望小伙伴们能喜欢,咱们快快来了解一下吧!

Kafka用于构建实时数据管道和流应用程序。 它在一个或多个服务器上作为群集运行。 Kafka群集将数据存储在主题中。 该主题可以包含一些分区。

它具有生产者,消费者,流和连接器API。 此外,Kafka具有大量的配置参数,这些参数提供了很大的灵活性。 许多公司将Kafka用作其应用程序的"循环系统"。

考虑到这些方面,正确的使用和配置需要记住很多事情。 Kafka文档很全面,但是缺乏简单的解释,特别是对于新手。

在这里,我将解释几种配置的情况,它们如何影响整个系统以及哪些陷阱(问题)可以等待我们:

· 消费者偏移量保留–可能导致低吞吐量主题中的数据重新处理问题;

· 段保留-低吞吐量的主题可以将事件保留的时间比预期的长,而无需考虑细分级别的保留期限;

· 不干净的领导人选举-可能导致数据丢失;

· 生产者设置-区分吞吐量和延迟的配置;

· 分区数-更多分区会如何影响性能;

· 分区分配策略-分配给使用者的分区分配不均。

在深入探讨该主题之前,请阅读本文以获取有关Kafka的一些刷新。

消费者偏移量保留

默认偏移量保留期可能导致低吞吐量主题中的数据重新处理或跳过。 从0.9.0版本开始,每个使用者都将其最近使用的消息的偏移量提交给__consumer_offsets主题。

在一定的时间内保留使用者的偏移量,如果分区在代理之间重新平衡,或者当使用者或代理暂时不可用时,使用者可以知道从分区日志继续读取的位置。 如果使用者刚刚开始使用或请求过期的偏移量,它将重置为__consumer_offsets主题中存储的最早(最早)或最新(最新)偏移量。

来源:将抵销保留期默认增加到7天

2.0版之前的Kafka低吞吐量主题可以通过偏移量保留期(一天),而无需处理任何新消息,__ consumer_offsets主题会删除该主题的使用者偏移量。

然后,Kafka使用者无法获取其偏移量,因此他们将重置为最早的偏移量(基于auto.offset.reset配置),并开始处理仍在代理上可用的最早消息。 这意味着他们重新处理了过去已经使用过的某些数据。 最好将retention.ms小于offsets.retention.minutes。

偏移补偿保留期的增加会导致某些副作用。 例如,它可以增加代理上的内存使用量,因为它必须将这些偏移量在内存中保留更长的时间。

段保留

如果您不考虑细分受众群级别的保留期限,则低吞吐量主题可以将事件保留的时间比预期的长。

Kafka将每个分区的数据存储在日志中,然后将其进一步分为日志段。 Kafka根据主题级别和段级别的日志保留时间确定存储数据的时间。 这使得很难跟踪消息实际存储在代理上的时间。

> Table 1. The configuration settings that determine how long Kafka will retain data.

当发生以下两种情况之一(以先到者为准)时,Kafka将关闭细分并打开一个新细分:

· 段达到最大大小(由segment.bytes确定)

· 段级别的保留期已过(基于segment.ms)

如果主题的吞吐量较低,则调整日志段的大小可能很重要。 例如,如果某个主题每天收到200兆字节的消息(log.segment.bytes = 1GB,log.segment.ms = 7天),则需要5天才能填满一个段。

由于在关闭日志段之前邮件不会过期,因此,如果将log.retention.ms设置为7天,则实际上将保留多达12天的邮件,直到关闭的日志段过期。 这是因为一旦使用当前5天的消息关闭了日志段,则根据时间策略,该日志段必须保留7天才能过期(因为直到该段中的最后一条消息都无法删除该段) 可以过期)。

了解分区的数据速率,以确保您拥有正确的保留空间。 数据速率决定了需要多少保留空间(以字节为单位)以保证在给定时间内保留。 如果您不知道数据速率,则无法正确计算实现基于时间的保留目标所需的保留空间。

"不干净"的领导人选举

在Kafka,当不干净的经纪人("不干净"意味着未完成从前任领导者复制最新数据更新)成为新的领导者时,就会发生不干净的领导者选举。 尽管此功能优先考虑可用性而不是持久性,但是它可能导致数据丢失。

Kafka在每个主题中跨分区存储数据,并且每个分区都有一个领导者和零个或多个从者获取并复制来自领导者的新数据的关注者。 每个代理充当某些分区的领导者,而充当其他分区的跟随者,这降低了任何给定分区出现单点故障的可能性。 如果关注者与领导者保持同步并保持可用状态,则将其视为同步副本(ISR)。 领导者后面的追随者将从ISR中移除,直到追赶分区领导者为止。

如果unclean.leader.election.enable被禁用(错误),Kafka将无法在特定时间选举新领导人。 如果不能选举新的领导者,Kafka将停止对该分区的所有读取和写入。 另一方面,如果启用了不干净的领导者选举并且领导者变得不可用,即使没有同步副本(ISR = 0),Kafka仍然可以通过选举新的领导者来保持分区在线。

假设我们有3个副本,复制因子设置为3,并且启用了不干净的领导者选举:

· 充当分区X领导者的代理处理的消息最多达到offset = 100,然后脱机。 跟随者(经纪人)以offset = 90(ISR = 0)稍微落后。

· 如果启用了不干净的领导者选举,则其中一个跟随者代理将被选举为该分区的新领导者(即使该分区是"不干净的")。 这使消费者和生产者可以继续向分区X发送请求。因此,现在新的领导者可以有更多消息,最大偏移量为120。 在偏移量90和100之间有全新的消息。

· 如果以前的领导者重新上线,它将重置其偏移量以匹配新领导者的偏移量,从而导致数据丢失。 请注意,有些消费者可能已经阅读了旧事件,与旧领导者之间的偏移量为90–100,有些消费者收到了新事件,有些则混合了两者。

生产者设置

有许多生产者配置可能会影响性能和耐用性,但其中一些是常用的:

批量大小

每个Kafka生产商都会为单个分区批处理记录,优化发给分区负责人的网络和IO请求。 因此,增加批大小可能会导致更高的吞吐量。 在轻负载下,这可能会增加Kafka发送延迟,因为生产者会等待批次准备就绪。

在高负载下,建议增加批大小以提高吞吐量和延迟。

Linger.ms

Linger.ms设置还控制批处理。 它为生产者在发送批次之前等待了多长时间设定了上限,即使批次未满。 在低负载情况下,这可以通过缩短延迟时间来提高吞吐量。

cks

Kafka通过复制提供容错功能,因此单个节点的故障或分区领导力的变化不会影响可用性。 如果您配置的生产者不带附件,则消息可能会静默丢失。

生产者需要的ack配置确定分区负责人在写请求被视为完成之前所需的确认数。 此设置会影响数据可靠性,其取值为0、1或-1(即"全部")。

为了获得最高的可靠性,将acks设置为all可确保领导者等待所有同步副本(ISR)确认消息。 在这种情况下,如果同步副本的数量少于配置的min.insync.replicas,则请求将失败。 请注意,即使Asks = all,但min.insync.replicas = 1消息的持久性也无法保证。

虽然ack = -1为防止数据丢失提供了更强的保证,但会导致更高的延迟和更低的吞吐量。

分区数

为了选择正确的分区数量,我们测量了我们希望在单个分区上实现的产量P和消耗C的吞吐量。假设您的目标吞吐量为T。那么您至少需要有max(T / P,T / C)分区。 生产者可以实现的每分区吞吐量取决于配置,例如批处理大小,压缩编解码器,确认类型,复制因子等。

更多分区会带来一些问题:

· 更多的开放文件句柄-每个分区都映射到代理中文件系统中的目录。 在该日志目录中,每个日志段将有两个文件(一个用于索引,另一个用于实际数据)。

· 可能会增加可用性,将消费者和生产者的请求发送给领导者副本。 当代理失败时,该代理上带有领导者的分区将暂时不可用。 Kafka将自动将那些不可用分区的领导者移至其他一些副本,以继续满足客户端请求。 该过程由指定为控制者的Kafka经纪人之一完成。 它涉及为ZooKeeper中的每个受影响的分区读写一些元数据。 如果失败的代理是控制者,则无法开始此过程。 应该选择新的控制器,然后在初始化期间从ZooKeper中读取每个分区的一些元数据。

· 可能会增加端到端延迟-Kafka中的端到端延迟是由生产者发布消息到消费者读取消息的时间定义的。 Kafka仅在提交消息后(即,将消息复制到所有同步副本时)才将消息公开给使用者。 因此,应在其中复制消息的副本数和负责此过程的线程数可能是端到端延迟的重要部分。

· 可能在客户端中需要更多的内存-内部,生产者在每个分区中缓冲消息。 在累积了足够的数据(batch.size参数)或经过了足够的时间(linger.ms参数)之后,累积的消息将从缓冲区中删除并发送到代理。 如果增加一个分区的数量,则消息将在生产者的更多分区中累积。

· 当使用的内存量超过配置的内存限制时,生产者必须阻止或丢弃任何新消息,这两种都不是理想的消息。 消费者也存在类似的问题。 使用者从每个分区获取一批消息。 使用者使用的分区越多,所需的内存就越多。

· 查看此建议以提高使用者的内存使用率。

发布密钥消息时,Kafka根据密钥的哈希确定性地将消息映射到分区。 这样可以保证具有相同密钥的消息始终被路由到同一分区。 更改主题中的分区数会更改键的哈希,因此可以在与以前不同的分区上生成新消息。

> Image 1. Overview of three brokers with topics and partitions (blue — partitions leader, grey —

分区分配策略

当使用者希望加入使用者组时,它将向组协调器发送JoinGroup请求。 加入该小组的第一个消费者成为小组负责人。 领导者从组协调器接收组中所有消费者的列表(这将包括最近发送心跳并因此被认为是活动的所有消费者),并且负责为每个消费者分配分区的子集。 它使用PartitionAssignor接口的实现来确定哪个分区应由哪个使用者处理。

在确定分区分配之后,消费者负责人将分配列表发送给GroupCoordinator,后者将此信息发送给所有消费者。 每个消费者仅看到自己的任务-领导者是唯一拥有组中所有消费者及其任务列表的客户流程。

每当发生重新平衡时,都会重复此过程。

您可以实施自己的策略来扩展PartitionAssignor接口或使用:

· org.apache.kafka.clients.consumer.RangeAssignor —对于每个主题,将其分区除以预订的消费者数量,然后将X分配给每个(按字母顺序排序的)消费者。 如果不能平均分配,则第一个使用者将具有更多的分区。

· org.apache.kafka.clients.consumer.RoundRobinAssignor —依次将所有已订阅主题的所有分区依次分配给每个使用者。

· org.apache.kafka.clients.consumer.StickyAssignor-分配分区,以便它们尽可能均匀地分布。 在重新平衡期间,分区尽可能地与其先前分配的使用者保持在一起。

通过使用者中的partition.assignment.strategy参数提供配置。

如果组使用的主题(例如通过正则表达式)由不相等数量的分区组成,则RangeAssignor(默认的分区分配策略)可以增加对组中某些使用者的分区分配。

> Image 2. Consumers partition assignments.

假设我们有一个带有8个分区的主题(主题1)和一个带有2个分区的20个主题(类似于图片上的主题2和3)。 在这种配置中(默认的RangeAssignor),我们最终为使用者1和2分配了23个分区(主题1中的3个分区,其他20个主题为20个分区)和使用者3的2个分区(主题1中的2个分区)。

最好使用不同的分区分配策略,以便在组中的使用者之间平均分配分区。

总结

可以调整数百种Kafka配置,以配置生产者,经纪人和消费者。 在这篇文章中,我们指出了从在生产环境中运行Apache Kafka中学到的一些宝贵经验。

最初于2019年9月11日发布在卡夫卡的Synerise:陷阱的灵活性。

(本文翻译自Jenny Ye的文章《Flexibility With Traps in Kafka》,参考:)

标签: #jennyapache