学习kafka的第五天

204 阅读4分钟

这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战

 Producer 中的直观用户超时

Kafka 内部是如何保存数据的。?

Kafka 使用的topics只是“feeds”发布的。可以注意到,Kafka 为每个主题维护了一个分区日志,在官方文档中是这样描述的:

So from our point of view, the most important thing to remember is that Kafka preserves the order of messages within a partition.。

所以从我们的角度来看,最重要的是要记住 Kafka 保留了分区内消息的顺序。

对于某些用例,从业务角度来看,保留消息的顺序可能非常重要。例如,假设您正在从事某种银行项目,您正在通过 Kafka 进行通信。在银行账户中保持正确的操作顺序非常重要,否则,如果消息以错误的顺序被消费,那么我们的应用程序的用户可能会在交易过程中失败,因为取款消息会在存款消息之前到达并且交易获胜'无法处理。

前段时间,有人提议更改 Kafka 生产者实现,称为:生产者中的直观用户超时。引入此更改主要是为了将发送超时的所有可用设置打包为一个:delivery.timeout.ms。但是这个提案还引入了另一个小改动,记录为:在提案文档中将重试的默认值更改为 MAX_INT,这看起来不像是要记住的重要内容。这些更改已在 2.1.0 版的 Kafka producer 中发布,因此自1.0 版以来,这也对 Alpakka Kafka Connector 产生了影响. 如果您仔细阅读 Apache Kafka 升级说明,您会注意到整个更改被描述为:

生产者重试配置的默认值更改为 Integer.MAX_VALUE,因为我们在 KIP-91 中引入了 delivery.timeout.ms,它设置了发送记录和从代理接收确认之间的总时间的上限。默认情况下,传递超时设置为 2 分钟。

处理失败——重试机制

由于Kafka 2.1.0当消息不会被broker确认时,那么它会被生产者再次重新发送,默认情况下,最多2147483647(MAX_INT)次或直到delivery.timeout.ms到期(默认2分钟) ,这是 KIP-91 中引入的新行为。但这在这种情况下并不那么重要。最重要的信息隐藏在 retries 参数的描述中:

允许重试而不将 max.in.flight.requests.per.connection 设置为 1 **可能会更改记录的顺序, **因为如果将两个批次发送到单个分区,第一个失败 并重 试但第二个成功,则记录在第二批中可能会先出现。

max.in.flight.requests.per.connection 的默认值是 5。所以正如你所料,如果记录没有被代理确认而失败,生产者可能会发送很可能会存储在错误中的记录order 并且这是 Kafka 生产者的正常行为,因此默认情况下 Kafka 不保证生产者发送到特定主题分区的消息将按发送顺序附加。

概括

只需将一个生产者设置max.in.flight.requests.per.connection 更改为 1,即可轻松修复此行为,但请注意,更改此属性会影响生产者吞吐量。您还可以设置enable.idempotence=true而无需减少max.in.flight.requests.per.connection但您需要根据文档调整其他设置:

请注意,启用幂等性要求 max.in.flight.requests.per.connection 小于或等于 5,重试次数大于 0 并且 acks 必须为“全部”。如果用户未明确设置这些值,则会选择合适的值。如果设置了不兼容的值,则会抛出 ConfigException。

由于生产者如何实现幂等性,这将起作用。无需过多赘述,生产者维护的序列号随每条消息发送到 Kafka,如果该序列号比上一条正好多 1,则消息将存储在 Kafka 中。您可以在 Adam Warski 博客文章中阅读有关其工作原理的更多信息:Kafka 的完全一次处理究竟意味着什么?. 值得一提的是,默认配置会导致在发生故障时以错误的顺序生成消息,如果消息顺序对您的应用程序很重要,那么您可能会遇到很多麻烦,因为有人告诉过您如您所见的保证并不总是正确的。

\