使用Idempotant Producer时,为什么Kafka的订购保证不一致?

时间:2018-04-23 13:47:12

标签: apache-kafka kafka-producer-api idempotent

我在我的应用程序中使用Kafka 1.0.1并且我已经开始使用0.11中引入的Idempotent Producer功能,并且在使用Idempontent功能时我无法理解排序保证。

我的制作人的配置是:

enable.idempotence = true

max.in.flight.requests.per.connection = 5

retries = 50

acks = all

根据文件:

重试

  

设置大于零的值将导致客户端重新发送任何发送失败但可能出现暂时性错误的记录。请注意,此重试与客户端在收到错误时重新发送记录时没有什么不同。允许重试而不将max.in.flight.requests.per.connection设置为1可能会改变记录的顺序,因为如果将两个批次发送到单个分区,并且第一个失败并重试但第二个成功,则记录在第二批可能首先出现。

enable.idempotence

  

当设置为' true'时,生产者将确保在流中写入每个消息的正好一个副本。如果' false',由于代理失败等原因导致生产者重试,可能会在流中写入重试消息的重复项。请注意,启用幂等性要求max.in.flight.requests.per.connection小于或等于5,重试次数大于0且确认必须为“全部”。如果用户未明确设置这些值,则将选择合适的值。如果设置了不兼容的值,则将抛出ConfigException。

我的配置似乎符合要求,但它们似乎并不一致。

我的另一个问题与OutOfOrderSequenceException有关: 根据文档,如果我得到这个例外,这意味着生产者有可能出现故障。但是如果我的生产者配置了max.in.flight.requests.per.connection = 5并且让我们说第二个请求得到了乱序异常,那么以下所有已经在飞行中的请求会发生什么?这是否意味着我确定无序?

1 个答案:

答案 0 :(得分:1)

在KafkaProducer中启用幂等性时,可以保证顺序。

即使max.in.flight.requests.per.connection大于或等于5,幂等的KafkaProducer仍将确保TopicPartition中的排序。仅当禁用幂等性时,有关“重试”的描述与max.in.flight的关系才适用。

幂等的KafkaProducer使用内部递增序列号来确保顺序。

KAFKA-5494Design for max.in.flight > 1 with idempotence enabled.中的相应文档中提供了详细信息,其中第5步和第6步将阐明您的问题:

有了上述假设,解决方案如下:

  1. 我们跟踪发送到分区的最后一个已确认序列。每次成功确认后都会更新一次,因此应该一直在增加。

  2. 我们跟踪给定分区的批处理绑定的下一个序列。

  3. 当批次排空时,我们分配了nextSequence。我们还将nextSequence增加一批记录的数量。

  4. 如果生产请求成功,我们将最后确认的序列设置为批次的最后序列。

  5. 如果生产请求失败,则成功进行飞行批处理也会失败,并显示OutOfOrderSequenceException。

  6. 因此,如果批次的序列号不是最后一个确认序列的后继,并且如果失败并出现OutOfOrderSequenceException,则我们认为该序列是可重试的。

  7. 重新分配批次时,我们先删除生产者ID和序列号,然后再将其插入队列。

  8. 当第一个飞行批次失败时(无论出于何种原因),我们将nextSequence重置为lastAckdSequence + 1。

  9. 因此,如果一个批次致命失败,则后续批次的序列号在重试时将有所不同。很好,因为先前的失败是一个OutOfSequence异常,这绝对意味着该请求被拒绝了。

“ [...]如果我的生产者配置了max.in.flight.requests.per.connection = 5,并且说第二个请求出现了乱序异常,那么以下所有请求都会发生什么已经在飞行吗?这是否意味着我确定会出问题?”

如第5步和第6步所述,所有后续的进行中请求也将失败,并返回可重试 OutOfOrderSequenceExcpetion。当retries大于0时,幂等的KafkaProducer将能够保持顺序。