Java 当应用程序中存在一个生产者和多个消费者时,apache kafka如何处理一致性

Java 当应用程序中存在一个生产者和多个消费者时,apache kafka如何处理一致性,java,concurrency,apache-kafka,kafka-consumer-api,kafka-producer-api,Java,Concurrency,Apache Kafka,Kafka Consumer Api,Kafka Producer Api,假设您有一个具有一个生产者(P1)和多个消费者(C1-C2-C3)的体系结构。当一个小型java客户机按顺序生成消息为M1、M2、M3时,另一个java客户机(按3倍比例扩展到另一台机器)得到一条消息,然后在计算完某些内容后将该消息写入数据库表 如果消费者应用程序中的计算周期不同,并且最初使用的消息可能会以最后的顺序写入同一个表中,则可能会导致数据不一致 也许我在文档中遗漏了一些东西,但我想知道卡夫卡如何在这种情况下处理一致性。消费者不听制作人的话。相反: 制作人向Kafka服务器集群管理的Ka

假设您有一个具有一个生产者(P1)和多个消费者(C1-C2-C3)的体系结构。当一个小型java客户机按顺序生成消息为M1、M2、M3时,另一个java客户机(按3倍比例扩展到另一台机器)得到一条消息,然后在计算完某些内容后将该消息写入数据库表

如果消费者应用程序中的计算周期不同,并且最初使用的消息可能会以最后的顺序写入同一个表中,则可能会导致数据不一致


也许我在文档中遗漏了一些东西,但我想知道卡夫卡如何在这种情况下处理一致性。

消费者不听制作人的话。相反:

  • 制作人向Kafka服务器集群管理的Kafka主题写入消息
  • Kafka服务器在为该主题创建的其中一个分区中持久化该消息,并且
  • 只有这样,消费者才能访问该消息 如果消费者在同一消费者组中,那么他们中只有一个将从消息的分区中读取,并且只有该消费者能够读取该消息。如果消费者不在同一消费者组中,则他们可能都能够阅读该消息。事实上,该消息可能会被许多消费者多次读取,直到Kafka服务器删除该消息,因为该消息早于为主题配置的生存时间


    一旦消费者阅读了来自卡夫卡主题的消息,卡夫卡就无法控制如何、何时甚至是否处理该消息

    如果您正在编写一个主题T1,该主题有3个分区,并且您的消费者属于一个消费者组,那么每个消费者将从T1的一个分区中消费。假设C1读取分区1C2读取分区2等。不能保证跨多个分区的数据排序,只能保证在一个分区内排序。考虑下面的例子:

    P1正在按顺序生成以下记录:

    ╔════════╗
    ║ Record ║
    ╠════════╣
    ║ R1     ║
    ║ R2     ║
    ║ R3     ║
    ║ R4     ║
    ║ R5     ║
    ║ R6     ║
    ╚════════╝
    
    假设记录按以下方式进行分区:

    ╔═════════════╦═════════════╦═════════════╗
    ║ Partition 1 ║ Partition 2 ║ Partition 3 ║
    ╠═════════════╬═════════════╬═════════════╣
    ║ R1          ║ R2          ║ R3          ║
    ║ R4          ║ R5          ║ R6          ║
    ╚═════════════╩═════════════╩═════════════╝
    

    现在C1可以在C2C3甚至开始之前完成所有记录的读取。因此,记录R4将在R2R3之前处理。但是,分区1中的顺序将始终保持不变,因此如果您希望保留发送到卡夫卡主题的相关消息的顺序,则R1将始终在R4之前接收和处理,您可以选择一个关于这些消息的唯一标识符作为Kafka分区键

    例如,如果您正在处理来自不同客户的交易,您可以选择customerId(假设它是客户的唯一标识符)作为分区密钥,这样您为给定客户发送给Kafka的所有消息都将在同一分区中结束;这意味着它们将被同一消费者按顺序消费

    但是,如果您说所有消息都是相关的并且相互依赖的,那么除了自己在使用者端处理并发性,或者最好只有一个分区和一个使用者,就没有什么可做的了