简体   繁体   English

Kafka Streams KTable 外键连接无法按预期工作

[英]Kafka Streams KTable foreign key join not working as expected

I'm trying to have a simple foreign key join in Kafka Streams similar to many articles (like this for one: https://www.confluent.io/blog/data-enrichment-with-kafka-streams-foreign-key-joins/ ).我正在尝试在 Kafka Streams 中加入一个类似于许多文章的简单外键(例如: https : //www.confluent.io/blog/data-enrichment-with-kafka-streams-foreign-key-加入/ )。

When I try to join the user id (primary key of user table) with the foreign key user_id in the account_balance table to produce an AccountRecord object, I get the following error: [-StreamThread-1] ignJoinSubscriptionSendProcessorSupplier : Skipping record due to null foreign key.当我尝试将用户id (用户表的主键)与account_balance表中的外键user_id起来以生成AccountRecord对象时,出现以下错误: [-StreamThread-1] ignJoinSubscriptionSendProcessorSupplier : Skipping record due to null foreign key.

The goal is ultimately to deliver the AccountRecord 's to a topic each time any field in either table update.最终目标是在每次更新任一表中的任何字段时将AccountRecord传递给主题。 The problem is that when I simply print the user table and the account table separately, the foreign keys and all fields are totally populated.问题是,当我简单地分别打印用户表和帐户表时,外键和所有字段都被完全填充。 I can't see what's wrong or why this error occurs.我看不出有什么问题或为什么会发生此错误。 Here is a snippet of my code:这是我的代码片段:

    public void start_test(){
        StreamsBuilder builder = new StreamsBuilder();

        KTable<Long, User> userTable = builder.table(USER_TOPIC, Consumed.with(CustomSerdes.UserPKey(), CustomSerdes.User()));
        KTable<Long, AccountBalance> accountBalanceTable = builder.table(ACCOUNT_BALANCE_TOPIC, Consumed.with(CustomSerdes.UserPKey(), CustomSerdes.AccountBalance()));

        final KTable<Long, AccountRecord> accountRecordTable = accountBalanceTable.join(
                userTable,
                AccountBalance::getUserId,
                (account, user) -> new AccountRecord(user.getFirstName(), account.getBalance());
        );

        // print the table
        accountRecordTable
                .toStream()
                .print(Printed.toSysOut());

        KafkaStreams stream = new KafkaStreams(builder.build(), properties);
        stream.start();
    }

Any guidance will be helpful.任何指导都会有所帮助。 I didn't include the custom serde code or the object shapes, but they are very simple.我没有包含自定义 serde 代码或对象形状,但它们非常简单。 Please let me know if you need additional clarification.如果您需要额外说明,请告诉我。

Thanks谢谢

Does your messages contain key record?您的消息是否包含密钥记录? A KTable is an abstraction of a changelog stream, where each data record represents an update, The way to know that update is with the key, is very important the key of the record at the moment to work with KTables. KTable 是对 changelog 流的抽象,其中每条数据记录代表一个更新,知道更新的方法是使用 key,对于 KTables 工作时记录的 key 非常重要。 Eg例如

AccountBalance<Key=10,Value={accountBalanceId=10,userId=777,balance=10}>
User<Key=777, Value={firstName="Panchito"}>

Another observation is your Serde key, why are you using a custom serde if you are defining Long as key?另一个观察结果是您的 Serde 键,如果您将 Long 定义为键,为什么要使用自定义 serde?

KTable<Long, User> userTable = builder.table(USER_TOPIC, Consumed.with(Serdes.Long(), CustomSerdes.User()));

KTable<Long, AccountBalance> accountBalanceTable = builder.table(ACCOUNT_BALANCE_TOPIC, Consumed.with(Serdes.Long(), CustomSerdes.AccountBalance()))

Maybe your key deserializer is sending the key as null.也许您的密钥解串器将密钥发送为空值。 Check the output of your custom Serde loggin the output.检查您的自定义 Serde 的输出记录输出。 Also you have to improve the join method adding a materialized because you are creating a new object and Kafka does not know how to handle the new object.此外,您必须改进添加物化的 join 方法,因为您正在创建一个新对象,而 Kafka 不知道如何处理新对象。

      final KTable<Long, AccountRecord> accountRecordTable = accountBalanceTable.join(
                    userTable,
                    AccountBalance::getUserId,
                    (account, user) -> new AccountRecord(user.getFirstName(), account.getBalance()),
Materialized.with(Serdes.Long(), CustomSerdes.AccountBalanceSerde() )
            );

Try to work with JsonSerde or Avro instead to create your custom Serdes.尝试使用 JsonSerde 或 Avro 来创建您的自定义 Serdes。

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

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