消息的有序性配置
来源:13-8 Kafka消息有序性处理

叫我滨哥哥
2023-03-14
首先单Toptic单分区的情况下,并不是天然有序的吧?应该根据版本来配置
1)kafka在1.x版本之前保证数据单分区有序,条件如下:
max.in.flight.requests.per.connection=1(不需要考虑是否开启幂等性)。 2)kafka在1.x及以后版本保证数据单分区有序,条件如下:
(1)开启幂等性
max.in.flight.requests.per.connection需要设置小于等于5。
(2)未开启幂等性
max.in.flight.requests.per.connection需要设置为1。
原因说明:因为在kafka1.x以后,启用幂等后,kafka服务端会缓存producer发来的最近5个request的元数据,
故无论如何,都可以保证最近5个request的数据都是有序的。
以上说明然后再结合官网的配置说明,我就懵逼了,以下是官网的配置说明
retries:若设置大于0的值,则客户端会将发送失败的记录重新发送,尽管这些记录有可能是暂时性的错误。请注意,这种 retry 与客户端收到错误信息之后重新发送记录并无区别。允许 retries 并且没有设置max.in.flight.requests.per.connection 为1时,记录的顺序可能会被改变。比如:当两个批次都被发送到同一个 partition ,第一个批次发生错误并发生 retries 而第二个批次已经成功,则第二个批次的记录就会先于第一个批次出现。
enable.idempotence:当设置为true时, Producer 将确保每个消息在 Stream 中只写入一个副本。如果为false,由于 Broker 故障导致 Producer 进行重试之类的情况可能会导致消息重复写入到 Stream 中。请注意,启用幂等性需要确保 max.in.flight.requests.per.connection小于或等于5,retries 大于等于0,并且ack必须设置为all 。如果这些值不是由用户明确设置的,那么将自动选择合适的值。如果设置了不兼容的值,则将抛出一个ConfigException的异常。
max.in.flight.requests.per.connection :在发生阻塞之前,客户端的一个连接上允许出现未确认请求的最大数量。注意,如果这个设置大于1,并且有失败的发送,则消息可能会由于重试而导致重新排序(如果重试是启用的话)。
我的疑问是:
根据上面那张图,开启幂等性之后,且缓存请求个数小于等于5,请求失败后,则会重试,等重试成功后再重新排序进行磁盘写入,保证消息单会话单分区有序性,那既然会重新排序的话,为什么重试大于0时且保证有序性的情况下还要限制max.in.flight.requests.per.connection 为1呢?为5不也可以保证有序性吗?
举个例子:
正常请求是:1,2,3,4,5
正常入队时是:5,4,3,2,1
假如异常情况下多个请求重试成功后入队(5,4,3均发生重试):5,4,3,2,1,这样不也可以保证有序性吗?
1回答
-
同学,你的思考非常深入,我们来一起梳理一下这个问题。Kafka 的幂等性确实可以在
max.in.flight.requests.per.connection <= 5
的情况下保证消息的单会话单分区有序性,这是因为 Kafka 的服务端会为幂等生产者缓存最近 5 个请求的元数据,从而能够在请求成功后重新排序,确保写入磁盘时有序。但是,为什么推荐在严格要求有序性的情况下将 **
max.in.flight.requests.per.connection
设置为 1 呢?这是因为在实际运行中,虽然 Kafka 服务端具备重新排序的能力,但重新排序会增加延迟,同时加大服务端的复杂度和资源消耗。将max.in.flight.requests.per.connection
设置为 1 的核心意义在于简化问题,避免服务端需要额外的排序操作,直接从生产者端控制消息的顺序,确保即使发生重试,消息的发送顺序也不会改变。举个例子,如果请求顺序是 1, 2, 3,但 2 发生了重试,当
max.in.flight.requests.per.connection
= 5 时,服务端需要缓存并排序才能恢复顺序;但如果设置为 1,生产者会等待前一个请求完成再发送下一个请求,这样无论是否发生重试,顺序自然就不会乱。所以,从理论上讲,
max.in.flight.requests.per.connection <= 5
可以在服务端重新排序后保证顺序,但在对延迟敏感或对实现复杂度有要求的场景下,设置为 1 是更保险、更高效的选择。希望我的讲解能帮你厘清这个问题!00
相似问题