我正在尝试过滤任何在长度为N
的给定(跳跃)时间窗口中密钥出现频率超过阈值T
的邮件。
例如,在以下流中:
#time, key
0, A
1, B
2, A
3, C
4, D
5, A
6, B
7, C
8, C
9, D
10, A
11, D
12, D
13, D
14, D
15, D
和N=2
以及T=3
,结果应为
0, A
2, A
7, C
8, C
9, D
11, D
12, D
13, D
14, D
15, D
或者,如果上述情况不可能,则简化只是在满足阈值后过滤消息:
#time, key
2, A
8, C
11, D
12, D
13, D
14, D
15, D
Kafka Streams可以实现吗?
到目前为止,我已尝试创建流的windowed count
(KTable
的实例)并将其连接回原始流。我使用windowed count
将KTable#toStream((k,v) -> k.key())
的密钥更改回原始密钥,然后执行dummy aggregation返回KTable
的实例。这似乎引入了一个延迟,导致leftJoin
错过在超过阈值后非常接近的消息。
final Serde<String> stringSerde = Serdes.String();
final Serde<Long> longSerde = Serdes.Long();
KStream<String, Long> wcount = source.groupByKey()
.count(TimeWindows.of(TimeUnit.SECONDS.toMillis(5)),"Counts")
.toStream((k,v) -> k.key());
// perform dummy aggregation to get KTable
KTable<String, Long> wcountTable = wcount.groupByKey(stringSerde, longSerde)
.reduce((aggValue, newValue) -> newValue,
"dummy-aggregation-store");
// left join and filter with threshold N=1
source.leftJoin(wcountTable, (leftValue, rightValue) -> rightValue,stringSerde, stringSerde )
.filter((k,v) -> v!=null)
.filter((k,v) -> v>1)
.print("output");
我还尝试使用适当的窗口执行KStream
- KStream
联接(省略虚拟聚合):
source.join(wcount, (leftValue, rightValue) -> rightValue, JoinWindows.of(TimeUnit.SECONDS.toMillis(5)),stringSerde, stringSerde, longSerde)
.filter((k,v) -> v!=null)
.filter((k,v) -> v>1)
.print("output");
这导致重复输出,因为每个UPSERT
进入wcount
会触发一个事件。
答案 0 :(得分:1)
这当然是可能的。您可以应用窗口聚合来收集列表中的所有原始数据(即,您手动实现窗口)。然后,应用评估窗口的flatMap。如果尚未达到阈值,则不发出任何内容。如果第一次满足阈值,则发出所有缓冲数据。对于计数大于阈值的flatMap的所有进一步调用,您只发出列表中的最新一个(您知道您之前发出的所有其他调用flatMap,即仅发出新添加的一个)。 / p>
注意:您需要禁用KTable缓存,即设置配置参数“cache.max.bytes.buffering”= 0.否则,算法将无法正常工作。
这样的事情:
KStream<Windowed<K>, List<V>> windows = stream.groupByKey()
.aggregate(
/*init with empty list*/,
/*add value to list in agg*/,
TimeWindows.of()...),
...)
.toStream();
KStream<K,V> thresholdMetStream = windows.flatMap(
/* if List#size < threshold
then return empty-list, ie, nothing
elseif List#size == threshold
then return whole list
else [List#size > threshold]
then return last element from list
*/);
答案 1 :(得分:0)
AFAIK这是Count-Min-Sketch算法的最佳选择。参见例如stream-lib实现: