【问题标题】:How is ordering guaranteed during failures in Kafka Async Producer?Kafka Async Producer 发生故障时如何保证排序?
【发布时间】:2016-05-17 16:19:04
【问题描述】:

如果我使用 Kafka 异步生产者,假设缓冲区中有 X 条消息。 当它们在客户端实际处理时,如果代理或特定分区关闭了一段时间,kafka 客户端将重试,如果一条消息失败,它是否会将特定消息标记为失败并继续下一条消息(这可能导致乱序消息)?或者,为了保持顺序,它是否会使批处理中的剩余消息失败?

我接下来要维护顺序,所以理想情况下希望 kafka 从失败的地方使批次失败,所以我可以从失败点重试,我将如何实现?

【问题讨论】:

  • 只有在你改变了默认的retires设置后,Kafka才会重试。 fron kafka docs:允许重试可能会改变记录的顺序,因为如果将两条记录发送到单个分区,并且第一个失败并被重试但第二个成功,那么第二个记录可能首先出现。

标签: apache-kafka kafka-producer-api


【解决方案1】:

就像在 kafka 文档中所说的关于重试的内容

设置大于零的值将导致客户端重新发送任何 记录其发送失败并可能出现暂时性错误。注意 此重试与客户端重新发送记录没有什么不同 收到错误。允许重试可能会改变 记录的排序,因为如果将两条记录发送到单个 分区,第一个失败并重试,但第二个成功, 那么第二条记录可能首先出现。

所以,回答你的标题问题,没有 kafka 在异步发送下没有订单保证。


我正在根据 Peter Davis 的问题更新答案。

我认为,如果您想以批处理模式发送,保护它的唯一方法是设置max.in.flight.requests.per.connection=1,但正如文档所述:

请注意,如果此设置设置为大于 1 并且有 发送失败,由于重试,存在消息重新排序的风险 (即,如果启用重试)。

【讨论】:

  • 如果 retries=0,这不会回答行为。如果您确实需要订购,但想批量发送而不在每次发送后调用 Future.get(),我可以设置 retries=0 并期望如果生产者未能发送一条消息,那么它将使所有后续消息都失败到分区以保留顺序?
  • 只要将重试次数设置为零并且每个主题只有一个分区,就可以依赖 Kafka 排序。您不必设置 max.in.flight.requests.per.connection=1 因为您只有一个分区,因此 Kafka 将永远只有 1 个正在运行的请求,因为分区是 kafka 并行机制
【解决方案2】:

从 Kafka 0.11.0 开始,有 enable.idempotence 设置,如 documented

enable.idempotence:当设置为true时,生产者将确保 每条消息的一个副本被写入流中。如果false, 由于 broker 故障等导致生产者重试,可能会写入重复 流中的重试消息。注意启用幂等性 要求 max.in.flight.requests.per.connection 小于或 等于5,重试次数大于0,acks必须为all。如果 这些值不是由用户明确设置的,合适的值将 被选中。如果设置了不兼容的值,ConfigException 将是 扔了。

Type: boolean Default: false

这将保证消息是有序的,并且在生产者会话期间不会发生丢失。不幸的是,生产者无法设置序列 ID,因此 Kafka 只能针对每个生产者会话做出这些保证。

如果您需要 set the sequence id,请查看 Apache Pulsar,这将允许您使用外部序列 ID,这将保证在代理和生产者故障转移之间进行有序且一次性的消息传递。

【讨论】:

    猜你喜欢
    • 2018-10-03
    • 2019-01-29
    • 1970-01-01
    • 1970-01-01
    • 2018-03-01
    • 2019-12-27
    • 2020-09-19
    • 1970-01-01
    • 2022-08-21
    相关资源
    最近更新 更多