Apache kafka 卡夫卡流-外部写入的无序副作用

Apache kafka 卡夫卡流-外部写入的无序副作用,apache-kafka,apache-kafka-streams,Apache Kafka,Apache Kafka Streams,我有两个Kafka流应用程序处理消息A->B,并在此之后进行进一步的业务处理。每个流应用程序也在向主题“X”写入事件包 KafkaProducer send("X", K, V) (k1, x1) ┌────────────┐ ┌──────────────────────────────────────────────────►│

我有两个Kafka流应用程序处理消息A->B,并在此之后进行进一步的业务处理。每个流应用程序也在向主题“X”写入事件包

                                 KafkaProducer send("X", K, V)         (k1, x1)   ┌────────────┐
                              ┌──────────────────────────────────────────────────►│ Topic X    │
                              │                                                   │            │
                              │                                       ┌──────────►│            │
                              │                                       │ (k1, x2)  └────────────┘
                              │                                       │
                              │                                       │
                     ┌────────┴─────┐                           ┌─────┴─────────┐
                     │ KStream A    │                           │ KStream B     │
┌───────────┐        │ .from(A)     │      ┌───────────┐        │ .from(B)      │
│Topic A    ├───────►│ .transform() ├──────┤Topic B    ├───────►│ .transform()  ├────►
└───────────┘        │ .peek(x1)    │      └───────────┘        │ .peek(x2)     │
                     │ .to(B)       │                           │ .to(C)        │
                     └──────────────┘                           └───────────────┘
流
.transform(()->eventTransformer)
.peek((键,值)->{
eventProducer.send(新的ProducerRecord(“X”,键,值));
});
流应用程序A发出带有键k1的事件消息x1,并且

流应用程序B发出具有相同密钥k1的事件消息x2,以确保相同的分区

然而,我注意到,有时它们被写错了顺序,x2在x1之前,这导致了特定事务的事件处理失败

我如何保证写入总是按顺序进行,x1后跟x2


我很乐意探索其他方法。

您观察到的无序事件最有可能是由于producer和Kafka流中的缓存(缓冲)

  • 您可以将生产者配置为最小化延迟(主要是
    linger.ms
    batch.size
    配置参数)。请参阅文章了解更多详细信息
  • 看看卡夫卡流缓存。设置
    CACHE\u MAX\u BYTES\u BUFFERING\u CONFIG=0
    在这里可能会有所帮助
  • 就个人而言,我不喜欢从KS应用程序调用
    producer.send()
    方法。您可以使用如下方法将流具体化为主题
    .to()

  • 谢谢@kikulikov,我将在接下来的几天内对建议的更改进行全面测试。
    stream
        .transform(() -> eventTransformer)
        .peek((key, value) -> {
            eventProducer.send(new ProducerRecord<>("X", key, value));
        });
    
    var transformed = stream.transform(() -> eventTransformer)
    
    transformed.to("topic-B")
    
    transformed.to("topic-X")