繁体   English   中英

如何根据来自另一个主题的响应读取来自 Kafka 主题的消息

[英]how to read message from Kafka topic based on response from another topic

我在 Kafka 中有 2 个主题:MetaData 和 MasterData。 我正在使用 Kafka Listners 实时读取数据。 有2种情况:

  1. 我必须先阅读 MetaData 主题,然后再阅读 MasterData 主题。
  2. 也有可能在 MetaData 主题中没有新的 msg,但在 MasterData 主题中插入了一条消息。 在这种情况下,应该继续使用 MasterData 主题。

蚂蚁建议如何实现这一目标?

在评论中澄清之后,这是我的理解,您想要实现的目标:

您有一个类似系统的数据库,来自 kafka 主题的元数据用于调整表结构。 然后实际数据进入主 kafka 主题,然后您希望将其插入表中。 换句话说:您想使用 kafka 定义数据的结构。

我不确定,如果这就是我所说的 Kafka 的常规用例,因为它旨在成为交换事件(即数据)的接口。 您尝试做的是将系统用作定义数据结构的手段。 但这只是我的意见。

正如前面评论中所说,几乎没有办法说一个主题中不会有消息。 您只能说:“还没有”消息。 您“可以”做的可能是:当master主题中的消息到达时,您首先检查meta主题,如果也有消息。 如果有,则应用数据结构中的更改,然后从主主题导入消息。

另一种选择是使用 Kafka Streams 而不是原始消费者来将两个主题组合在一起,例如通过join

无论如何,要定义数据结构,通常会使用 Avro 之类的东西,它为您提供架构演变等。 然后编写您的应用程序以了解架构更改并相应地将它们应用于您的数据库表。

更新:如何使用 Kafka Streams 解决

如上所述,使用 Kafka Streams 将是您的案例的可能解决方案。 让我解释一下,我在一些伪 kafka 流代码中的意思是:

import org.apache.kafka.streams.StreamsBuilder;
import org.apache.kafka.streams.kstream.GlobalKTable;

import java.nio.charset.StandardCharsets;

/**
 * Just an incomplete Kafka Streams Code Demo to show how the problem could
 * be solved with this framework instead of using the consumers directly.
 * Kafka Streams Boilerplate code not included.
 */
public class Example {
    private static final String META_TOPIC = "meta";
    private static final String MASTER_TOPIC = "master";

    // You have to make sure, the meta data is stored under this
    // specific key in the meta topic.
    private static final byte[] META_KEY = MetaEvent.class.getName().getBytes(StandardCharsets.UTF_8);

    public static void main(String[] args) {
        new Example().createTopology();
    }

    public void createTopology() {

        final StreamsBuilder builder = new StreamsBuilder();

        final GlobalKTable<byte[], MetaEvent> metaTable = builder.globalTable(META_TOPIC);

        builder.<byte[], MasterEvent>stream(MASTER_TOPIC)
                .leftJoin(
                        metaTable,
                        (k, v) -> META_KEY,
                        MasterWithMeta::new)
                .foreach(this::handleEvent);
    }

    private void handleEvent(byte[] key, MasterWithMeta masterWithMeta) {
        // 1) check if meta has changed, if so, apply changes to database
        // 2) import master data to database
    }
}

class MasterWithMeta {
    private final MasterEvent master;
    private final MetaEvent meta;

    public MasterEvent getMaster() {
        return master;
    }

    public MetaEvent getMeta() {
        return meta;
    }

    public MasterWithMeta(MasterEvent master, MetaEvent meta) {
        this.master = master;
        this.meta = meta;
    }

    public static MasterWithMeta create(MasterEvent master, MetaEvent meta) {
        return new MasterWithMeta(master, meta);
    }
}

class MetaEvent {
    // ...
}

class MasterEvent {
    // ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM