假设我们有一个包含1000条消息的Kafka主题。我们从中创建一个流(我们称之为st),并执行以下操作:
int count = 0;
st.groupByKey().count().foreach((key, value) -> {
count += value)
System.out.println(count)
});
当处理"结束"时,它返回略大于1000的数字。 什么可能导致这种奇怪的行为?
答案 0 :(得分:1)
如果您的某些消息具有相同的密钥,则您的代码会重复计算。 请注意,传递给KTable上的foreach()方法的函数不是每行执行一次,而是每次更新一次执行一次(可能不会因缓存而每次更新)。请参阅:https://kafka.apache.org/11/javadoc/org/apache/kafka/streams/kstream/KTable.html#foreach-org.apache.kafka.streams.kstream.ForeachAction-
对此KTable的每个更新记录执行操作。注意 这是一个返回void的终端操作。
请注意,foreach()未应用于内部状态存储和 只调用每个新的KTable更新记录。
想象一下,您有3条带有“A”键的消息。 count()聚合创建的KTable将更新3次,并且您的函数(lambda表达式)将使用以下参数调用3次: (“A”,1),(“A”,2),(“A”,3)导致计数增加1 + 2 + 3 = 6,而不是增加3。
KStream和KTable表示“运动中的数据”,它们的方法通常在数据流上运行。如果要对数据的当前快照进行操作,请考虑使用交互式查询。可能是因为KTable.foreach方法最初可能令人困惑,因此不推荐使用以下注释:
已过时。使用Interactive Queries API(例如, KafkaStreams.store(String,QueryableStoreType)后跟 ReadOnlyKeyValueStore.all())迭代KTable的键。 或者使用toStream()转换为KStream然后使用 关于结果的foreach(行动)。