Apache kafka ApacheKafka流:无序消息

Apache kafka ApacheKafka流:无序消息,apache-kafka,timestamp,extractor,Apache Kafka,Timestamp,Extractor,我有一个ApacheKafka 2.6的制作人,它编写topic-A(TA)。 我还有一个Kafka streams应用程序,它使用TA并写入topic-B(TB)。 在streams应用程序中,我有一个自定义的时间戳提取器,它从消息负载中提取时间戳 对于我的一个故障处理测试用例,我在应用程序运行时关闭了Kafka集群 当生产者应用程序尝试将消息写入TA时,它无法写入,因为集群已关闭,因此(我假设)缓冲了消息。 假设它以递增的时间顺序接收4条消息m1、m2、m3、m4。(即m1为第一位,m4为最

我有一个ApacheKafka 2.6的制作人,它编写topic-A(TA)。 我还有一个Kafka streams应用程序,它使用TA并写入topic-B(TB)。 在streams应用程序中,我有一个自定义的时间戳提取器,它从消息负载中提取时间戳

对于我的一个故障处理测试用例,我在应用程序运行时关闭了Kafka集群

当生产者应用程序尝试将消息写入TA时,它无法写入,因为集群已关闭,因此(我假设)缓冲了消息。 假设它以递增的时间顺序接收4条消息m1、m2、m3、m4。(即m1为第一位,m4为最后一位)

当我将Kafka集群重新联机时,制作人将缓冲消息发送到主题,但它们不符合顺序。例如,我接收m2,然后是m3,然后是m1,然后是m4

为什么呢?是不是因为生产者中的缓冲是多线程的,每个生产者同时对主题进行缓冲

我假设自定义时间戳提取器在使用消息时有助于对消息进行排序。但事实并非如此。或者我对时间戳提取器的理解是错误的

我从SO得到了一个解决方案,将所有事件从tA流式传输到另一个中间主题(比如tA'),这将使用时间戳提取器传输到另一个主题。但我不确定这是否会导致事件根据提取的时间戳重新排序

我的生产者代码如下所示(我使用SpringCloud创建生产者): Producer.java

@服务
公共级制作人{
私有字符串topicName=“输入主题”;
私有应用程序属性appProps;
@自动连线
私人卡夫卡模板卡夫卡模板;
公共制片人(){
超级();
}
@自动连线
public void setAppProps(ApplicationProperties appProps){
this.appProps=appProps;
this.topicName=appProps.getInput().getTopicName();
}
公共void发送消息(字符串键,MyEvent ce){
ListenableFuture=this.kafkaTemplate.send(this.topicName,key,ce);
}
}
为什么呢?是不是因为生产者中的缓冲是多线程的,每个生产者同时对主题进行缓冲

默认情况下,生产者最多允许向代理发出5个并行进行中的请求,因此,如果某些请求失败并重试,请求顺序可能会更改

为避免此重新排序问题,您可以设置
max.in.flight.requests.per.connection=1
(可能会影响性能的内容)或设置
enable.idemponence=true

顺便说一句:你没有说你的主题是一个分区还是多个分区,以及你的消息是否有密钥?如果您的主题有不止一个分区,并且您的消息被发送到不同的分区,那么在读取时就没有顺序保证,因为偏移量顺序只保证在一个分区内

我假设自定义时间戳提取器在使用消息时有助于对消息进行排序。但事实并非如此。或者我对时间戳提取器的理解是错误的

时间戳提取器仅提取时间戳。Kafka Streams不会对任何消息重新排序,但始终以偏移顺序处理消息

如果没有,那么时间戳提取器的具体用途是什么?只是将时间戳与事件关联

我从这里得到了一个解决方案,将所有事件从tA流式传输到另一个中间主题(比如tA'),它将使用时间戳提取器传输到另一个主题。但我不确定这是否会导致事件根据提取的时间戳重新排序

不,它不会进行任何重新排序。另一个问题是更改时间戳,但是如果您按照顺序a、b、c读取消息,结果将按照顺序a、b、c写入(只是使用不同的时间戳,但应该保留偏移顺序)


本讲座将解释更多细节:

关于我们是否使用钥匙的问题,是的,我们使用钥匙。我尝试使用max.in.flight.requests.per.connection=1,并且在重试期间保留顺序。因此,在维护消息顺序的同时,
enable.idemponence=true
是否也会导致性能下降?
enable.idemponence=true
可能也会导致性能下降,但可能会小于
max.in.flight.request.per.connection=1
——此外,如果启用幂等写,您还可以在重试时保护重复项(否则,重试可能会导致主题附加重复项,因为写入可能已成功,但只有ack丢失,从而触发重试)。此外,“我的主题”有2个分区。如果我的消息有密钥,那么为什么卡夫卡不保持顺序(即使它们正在重试)?我认为拥有消息键的好处之一是确保它们都在同一个分区中结束,并且在该分区中排序。是否有任何参考文档可以告诉我重试机制是如何工作的?如果您的邮件具有相同的密钥,则说明您很好。但在你的问题中,你没有提到任何关于钥匙的问题,所以不清楚他们是否有钥匙,或者可能有不同或相同的钥匙