Confluent 4.1中Kafka KSQL简单关联(Join)失效问题排查
嘿,我来帮你捋下这个关联失败的问题,看了你的操作步骤,发现两个关键细节可能导致了u.root全为null的情况:
1. 字段大小写不匹配,导致拼接的root值完全不一致
你在处理voip流的时候,拼接root字段用了全大写的字段名:
CREATE STREAM voip_details_stream_update as select SessionIdTime ,SessionIdSeq, CONCAT(SESSIONIDTIME,SESSIONIDSEQ) as root from voip_details_stream partition by SessionIdTime;
但你定义voip_details_stream的时候,字段是驼峰命名的:SessionIdTime和SessionIdSeq。KSQL里字段引用是严格区分大小写的,这就意味着SESSIONIDTIME会被当成一个不存在的字段,取值为null,最终拼出来的root就是null+null=null。
而你处理session流的时候,用的是正确的驼峰字段拼接:
CONCAT(SessionIdTime,SessionIdSeq) as root
两边的root值完全不匹配,关联自然找不到对应记录,返回null就很正常了。
修复方案:
把voip流的CONCAT语句改成和session流一致的驼峰字段:
CREATE STREAM voip_details_stream_update as select SessionIdTime ,SessionIdSeq, CONCAT(SessionIdTime,SessionIdSeq) as root from voip_details_stream partition by SessionIdTime;
之后重新创建后续的重分区流和表即可。
2. 表对应的Kafka Topic未启用日志压缩
在Confluent 4.1的KSQL里,表是依赖**日志压缩(Log Compaction)**的Kafka Topic来维护状态的。你通过CREATE AS SELECT生成的voip_details_stream_rekeyed6对应的Topic,默认是没有开启日志压缩的。
如果Topic没开日志压缩,KSQL没法正确维护表的最新状态,查询时就可能找不到关联的记录。
修复方案:
有两种方式可以解决:
方式一:创建流时直接指定日志压缩配置
CREATE STREAM voip_details_stream_rekeyed6 as select SessionIdTime ,SessionIdSeq,root from voip_details_stream_update partition by root WITH (kafka_topic='VOIP_DETAILS_STREAM_REKEYED6', value_format='JSON', cleanup_policy='compact');
如果需要指定分区数,可以加上partitions=<原Topic分区数>,保持和上游一致。
方式二:手动修改Topic配置
用Kafka命令行工具修改这个Topic的cleanup.policy:
kafka-configs --zookeeper <你的ZooKeeper地址> --alter --entity-type topics --entity-name VOIP_DETAILS_STREAM_REKEYED6 --add-config cleanup.policy=compact
改完之后可以重启KSQL,让它重新加载表的状态。
验证步骤
修复完之后,先查下voip_details_stream_rekeyed6的root字段,确认有非null的值;再查voipDetails_table_test的root,确保数据正常;最后再执行左关联查询,应该就能匹配到对应的记录了。
内容的提问来源于stack exchange,提问作者Mikhail

