Kafka - 如何同时使用过滤器和filternot?

时间:2016-12-01 18:44:16

标签: java apache-kafka apache-kafka-streams

我有一个从主题获取数据的Kafka流,需要将该信息过滤为两个不同的主题。

KStream<String, Model> stream = builder.stream(Serdes.String(), specificAvroSerde, "not-filtered-topic");
stream.filter((key, value) -> new Processor().test(key, value)).to(Serdes.String(), specificAvroSerde, "good-topic");
stream.filterNot((key, value) -> new Processor().test(key, value)).to(Serdes.String(), specificAvroSerde, "bad-topic");

然而,当我这样做时,它会从主题中读取数据两次 - 不确定这是否会随着数据变大而对性能产生任何影响。有没有办法只过滤一次并将其推送到两个主题?

1 个答案:

答案 0 :(得分:4)

您的方法是正确的,并且主题中的数据未读取两次,并且还有无内部数据复制。您的方法的唯一缺点是,每个记录都会评估两个过滤器谓词 - 但是,这非常便宜并且不应该是性能问题。

但是,您仍然可以通过使用KStream#branch()来提高性能,branch()确实占用多个谓词并在彼此之后评估所有谓词,并为每个谓词返回一个输入流。如果记录与谓词匹配,则将其放入相应的输出流中并且评估停止(即,不对该单个记录评估进一步的谓词 - 这确保将每个记录添加到最多一个输出流;或者如果没有谓词匹配)。

因此,您只需向filter()提供两个谓词:第一个谓词与原始true谓词相同,第二个谓词始终返回KStream<String, Model> stream = builder.stream( Serdes.String(), specificAvroSerde, "not-filtered-topic" ); KStream[] splitStreams = stream.branch( (key, value) -> new Processor().test(key,value), (key, value) -> true ); splitStreams[0].to(Serdes.String(), specificAvroSerde, "good-topic"); splitStreams[1].to(Serdes.String(), specificAvroSerde, "bad-topic");

true

不确定此代码是否比原始版本更易读。我想这是一个品味问题,我个人更喜欢你的原始代码,因为它确实更好地表达了语义。

我添加的版本应该稍微提高CPU效率,因为对于满足谓词的所有记录,它只被评估一次。对于所有不满足结果的记录,将返回一个简单的splitStream[1](即没有第二个谓词评估)。

如果你知道大多数记录最终会在splitStream[0]中,你也可以反转谓词(并使用true作为&#34; bad-stream&#34;)来减少数量调用第二个$(".subTabAction").keyup(function (event) { if (event.keyCode == 13) { $("#uniqueIdHere").click(); } }); - 返回谓词。但这些只是微观优化而且无关紧要。