私がやりたいのはこれです:
私のコードは次のようになります。
KStream<String, Long> longs = builder.stream(
Serdes.String(), Serdes.Long(), "longs");
// In one ktable, count by key, on a five second tumbling window.
KTable<Windowed<String>, Long> longCounts =
longs.countByKey(TimeWindows.of("longCounts", 5000L));
// Finally, sink to the long-avgs topic.
longCounts.toStream((wk, v) -> wk.key())
.to("long-counts");
すべてが期待どおりに機能するように見えますが、集計は各着信レコードの宛先トピックに送信されます。私の質問は、各ウィンドウの最終的な集計結果のみを送信するにはどうすればよいですか?
In Kafka Streamsには「最終的な集約」などはありません。ウィンドウは、ウィンドウの終了時間が経過した後に到着する順不同レコードを処理するために常に開いています。 、ウィンドウは永久に保持されるわけではありません。保持時間が経過すると破棄されます。
詳細については、Confluentのドキュメントを参照してください。 http://docs.confluent.io/current/streams/
したがって、集計の更新ごとに、結果レコードが生成されます(Kafka Streamsは順序が狂ったレコードの集計結果も更新するため)。「最終結果」が最新になります)結果レコード(ウィンドウが破棄される前)。ユースケースに応じて、手動の重複排除が問題を解決する方法になります(下位レバーAPI、transform()
またはprocess()
を使用)
このブログ投稿も役立つかもしれません: https://timothyrenner.github.io/engineering/2016/08/11/kafka-streams-not-looking-at-facebook.html
句読点を使用せずにこの問題に対処する別のブログ投稿: http://blog.inovatrend.com/2018/03/making-of-message-gateway-with-kafka.html
更新
KIP-328 を使用すると、KTable#suppress()
演算子が追加されます。これにより、厳密な方法で連続した更新を抑制し、ウィンドウごとに単一の結果レコードを発行できます。トレードオフは遅延の増加です。
Kafka= Streamsバージョン2.1から、これを実現できます singsuppress
。
前述のApache Kafkaユーザーが1時間に3つ未満のイベントを持っている場合にアラートを送信するStreamsのドキュメントからの例があります。
KGroupedStream<UserId, Event> grouped = ...;
grouped
.windowedBy(TimeWindows.of(Duration.ofHours(1)).grace(ofMinutes(10)))
.count()
.suppress(Suppressed.untilWindowCloses(unbounded()))
.filter((windowedUserId, count) -> count < 3)
.toStream()
.foreach((windowedUserId, count) -> sendAlert(windowedUserId.window(), windowedUserId.key(), count));
this answerの更新で述べたように、トレードオフに注意する必要があります。さらに、 注 suppress()はイベント時間に基づいています。