Apache kafka 带有KafkaStreams的窗外连接端
我有一个卡夫卡主题,我期望消息具有两种不同的键类型:旧键和新键。 i、 e.Apache kafka 带有KafkaStreams的窗外连接端,apache-kafka,outer-join,apache-kafka-streams,Apache Kafka,Outer Join,Apache Kafka Streams,我有一个卡夫卡主题,我期望消息具有两种不同的键类型:旧键和新键。 i、 e.“1-新”,“1-旧”,“2-新”,“2-旧”。键是唯一的,但可能缺少一些键 现在,使用Kotlin和KafkaStreams API,我可以使用新旧密钥id相同的密钥记录这些消息 val windows = JoinWindows.of(Duration.of(2, MINUTES).toMillis()) val newStream = stream.filter({ key, _ -> is
“1-新”
,“1-旧”
,“2-新”
,“2-旧”
。键是唯一的,但可能缺少一些键
现在,使用Kotlin和KafkaStreams API,我可以使用新旧密钥id相同的密钥记录这些消息
val windows = JoinWindows.of(Duration.of(2, MINUTES).toMillis())
val newStream = stream.filter({ key, _ -> isNew(key) })
.map({key, value -> KeyValue(key.replace(NEW_PREFIX, ""), value) })
val oldStream = stream.filter({ key, _ -> isOld(key) })
.map({key, value -> KeyValue(key.replace(OLD_PREFIX, ""), value) })
val joined = newStream.join(oldStream,
{ value1, value2 -> "$value1&$value2" }, windows)
joined.foreach({ key, value ->
log.info { "JOINED $key : $value" }
})
现在我想知道由于某种原因,时间窗口中缺少的新/旧键。是否可以使用KafkaStreams API实现
在我的情况下,当收到钥匙
“1-old”
,并且“1-new”
不在2分钟内时,仅在这种情况下,我想将id1
报告为可疑 如果我正确理解了您的问题,您只想在2分钟的窗口内有一个“旧”而没有相应的“新”时,将id报告为可疑
如果是这种情况,则需要使用左联接:
val leftJoined = oldStream.leftJoin(newStream,...).filter(condition where value expected from "new" stream is null);
HTHDSL可能无法满足您的需求。但是,您可以使用处理器API。说到这里,
leftJoin
实际上可以用来做“繁重的工作”。因此,在leftJoin
之后,可以使用带有附加状态的.transform(…)
进一步“清理”数据
对于收到的每个旧记录和空记录,将其放入存储区。如果您收到以后的旧版和新版
,您可以将其从商店中删除。此外,您注册了一个标点符号,在每次标点符号调用时,您都会扫描存储区中“足够旧”的条目,以确保以后不会生成old&new
join结果。对于这些条目,您将发出old&null
,并将其从存储中删除
另一种选择是,您也可以省略连接,并使用state在单个transform()
中执行所有操作。为此,您需要KStream#merge()
新旧流,并在合并流上调用transform()
注意:除了注册标点符号,您还可以将“扫描逻辑”放入转换中,并在每次处理记录时执行它。看起来就像您正在查找的一样
消除了kafka streams框架中缺少类似sql的左连接语义。只有在连接窗口持续时间间隔内未发生完全连接事件时,此实现才会生成左连接事件
你关于可疑身份证的假设是正确的。但是,如果我将一个旧流左键连接到那些匹配ID的新流,我将获得流中相同键的old&null
,然后old&new
值。(我假设旧的键值总是首先到达)。如果我通过contains(“&null”)过滤值,我会得到可疑的所有ID。为什么我应该选择这种方法而不是groupby和后续窗口化的reduce?有多个原因:(1)连接使用滑动窗口,而聚合使用跳转窗口(所以语义不同)(2)reduce()也会连续计算,因此,您可能会遇到一些问题,需要使用suppress()加上一个计算实际联接的下游运算符。(3) 结合第(2)点,您需要将所有原始数据作为reduce
的结果(即,使用aggregate
并返回原始记录列表)。这会增大消息大小,并且可能不适用于较大的窗口。通过计算实际联接的下游运算符
您的意思是将leftJoin作为单独的步骤来执行?我们想先做leftJoin,然后做groupby+reduce加上窗口长度限制。在windows方面,我想我们也可以使用SessionWindow。据我所知,使用SessionWindow可以解决这个问题。这种方法有意义吗?我明白了——你仍然有一个问题,那就是你可能会在窗口中创建潜在的大消息——我也不确定,如果你能正确区分结果记录:假设你有(时间戳、键、值)
对,连接窗口大小5ms
:左输入(9,a,a)
->输出(9,a,)
,左输入(10,A,A)
->输出(10,A,)
,右输入(15,A,x)
->输出(15,A,)
,您怎么知道这会替换第二条记录而不是第一条记录?还要注意的是,如果右输入的ts=14,则会在连接上发出两条记录。因此,我怀疑它是否有效。