Apache Kafka分区保证中的消息顺序

时间:2019-11-07 16:35:17

标签: apache-kafka kafka-producer-api

阅读有关主题分区中的消息排序的本文:https://blog.softwaremill.com/does-kafka-really-guarantee-the-order-of-messages-3ca849fd19d2

  

允许重试而不设置飞行中的最大请求数   到1可能会更改记录的顺序,因为如果两个   批处理发送到单个分区,第一个失败并且是   重试但第二次成功,则第二批中的记录   可能会先出现。

据此,可以通过两种类型的生产者配置来实现订购保证:

max.in.flight.requests.per.connection=1 // can impact producer throughput

或替代

enable.idempotence=true
max.in.flight.requests.per.connection //to be less than or equal to 5
max.retries // to be greater than 0
acks=all

有人可以解释第二种配置如何实现订单保证吗?另外,在第二个配置中,仅启用一次语义。

3 个答案:

答案 0 :(得分:3)

幂等 :(每个分区的语义顺序恰好一次)

  

等幂传递使生产者能够准确地将消息写入Kafka   一次在主题的生存期内转到主题的特定分区   一个生产者,没有数据丢失和每个分区的订单。

幂等是在Kafka中实现一次语义化的关键功能之一。最终将“ enable.idempotence = true”设置为每个分区一次,这意味着没有重复,特定分区没有数据丢失。如果发生错误,即使生产者发送消息多次,也将一次写入Kafka。

Kafka生产商使用PID和序列号实现等幂的概念,如下所述:

PID和序列号

幂等生产者在生成消息时使用产品id(PID)和序列号。生产者在发布的每个消息上保持递增的序列号,这些消息具有唯一的PID。代理始终将当前序列号与前一个序列号进行比较,如果新序列号不比上一个序列号大+1,这会避免重复;如果消息中丢失了更多的序列号,则会拒绝同时出现。

enter image description here

在失败的情况下,它将仍然保持序列号并避免重复,如下所示:

enter image description here

注意::生产者重新启动时,将分配新的PID。因此,仅在单个生产者会话中就承诺了幂等性

如果使用enable.idempotence = true,则可以将max.in.flight.requests.per.connection最多保持5个,并可以实现订单保证,从而带来更好的并行性并提高性能。

Kafka 0.11+中引入的幂等功能,然后才能通过使用带有重试和Acks设置的max.in.flight.requests.per.connection达到一定程度的保证:

max.in.flight.requests.per.connection to 1
max.retries bigger number
acks=all

最大飞行飞行次数。连接数= 1 :以确保在重试邮件时不会发送其他邮件。

这至少一次保证了性能,同时带来了性能和吞吐量方面的成本,因此鼓励引入enable.idempotence功能来提高性能并同时保证订购。

exactly_once :要实现与幂等性恰好一次,我们需要将事务设置为read_committed,并且不允许覆盖以下参数:

  • isolation.level:read_committed(消费者将始终读取已提交的内容 仅限数据)

  • enable.idempotence = true(生产者将始终启用幂等)

  • MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION = 5(制作人将 每个连接始终有一个进行中的请求)

答案 1 :(得分:2)

UNIX Shellkip-98的一部分中引入的新设置(在kafka 0.11+中实现)。用户必须先将max.inflight设置为1。

它的工作方式(缩写)是生产者现在将序列号放到我们正在生产的产品批次中,并且经纪人跟踪与之相连的每个生产者的序列号。如果经纪人收到一批无序的订单(例如,第1批之后的第3批),它将拒绝它,并希望看到第2批(生产者将重新传输)。有关完整的详细信息,您应该阅读kip-98

答案 2 :(得分:0)

等幂生成器是一种在其中再次发送同一条消息的地方,它对消息序列没有任何影响。因此,如果您使用enable.idempotence=true,也会在不设置max.in.flight.requests.per.connection=1的情况下产生一次语义。