web-dev-qa-db-ja.com

Kafka KStreamからKstreamへのウィンドウ結合を管理する方法は?

Apache Kafka docsKStream-to-KStream Joins are always windowed joinsに基づいて、私の質問は、ウィンドウのサイズをどのように制御できますか?データを保持するための同じサイズですか?トピックですか?または、たとえば、データを1か月間保持しても、過去1週間だけストリームに参加できますか?

ウィンドウ化されたKStreamからkStreamへのウィンドウ化された結合を示す良い例はありますか?

私の場合、2つのKStream、kstream1kstream2があります。10日間のkstream1から30日間のkstream2に参加できるようにしたいとします。

9
Am1rr3zA

それは絶対に可能です。 Stream演算子を定義するときは、結合ウィンドウのサイズを明示的に指定します。

KStream stream1 = ...;
KStream stream2 = ...;
long joinWindowSizeMs = 5L * 60L * 1000L; // 5 minutes
long windowRetentionTimeMs = 30L * 24L * 60L * 60L * 1000L; // 30 days

stream1.leftJoin(stream2,
                 ... // add ValueJoiner
                 JoinWindows.of(joinWindowSizeMs)
);

// or if you want to use retention time

stream1.leftJoin(stream2,
                 ... // add ValueJoiner
                 (JoinWindows)JoinWindows.of(joinWindowSizeMs)
                                         .until(windowRetentionTimeMs)
);

詳細については、 http://docs.confluent.io/current/streams/developer-guide.html#joining-streams を参照してください。

スライディングウィンドウは、基本的に追加の結合述語を定義します。 SQLのような構文では、これは次のようになります。

SELECT * FROM stream1, stream2
WHERE
   stream1.key = stream2.key
   AND
   stream1.ts - before <= stream2.ts
   AND
   stream2.ts <= stream1.ts + after

どこ before == after == joinWindowSizeMsこの例では。 JoinWindows#before()JoinWindows#after()を使用してこれらの値を明示的に設定する場合、beforeafterも異なる値を持つことができます。

ソーストピックの保持時間は、Kafka Streams自体によって作成された変更ログトピックに適用される指定されたwindowRetentionTimeMsとは完全に独立しています。ウィンドウの保持により、順序が正しくないレコードを相互に結合できますつまり、遅れて到着したレコード(Kafkaにはオフセットベースの注文保証がありますが、 タイムスタンプに関しては、レコードの順序が狂っている可能性があります)。

13
Matthias J. Sax

Matthias J. Saxが言ったことに加えて、次の場所にストリーム間(ウィンドウ)結合の例があります: https://github.com/confluentinc/examples/blob/3.1.x/kafka-streams /src/test/Java/io/confluent/examples/streams/StreamToStreamJoinIntegrationTest.Java

これは、Apache Kafka 0.10.1、つまり2017年1月現在の最新バージョンを使用するConfluent 3.1.x用です。使用するコード例については、上記のリポジトリのmasterブランチを参照してください。新しいバージョン。

上記のコード例の重要な部分は次のとおりです(ここでも、Kafka 0.10.1)の場合、質問に少し適合しています。この例は、OUTERJOINを示していることに注意してください。

long joinWindowSizeMs = TimeUnit.MINUTES.toMillis(5);
long windowRetentionTimeMs = TimeUnit.DAYS.toMillis(30);

final Serde<String> stringSerde = Serdes.String();
KStreamBuilder builder = new KStreamBuilder();
KStream<String, String> alerts = builder.stream(stringSerde, stringSerde, "adImpressionsTopic");
KStream<String, String> incidents = builder.stream(stringSerde, stringSerde, "adClicksTopic");

KStream<String, String> impressionsAndClicks = alerts.outerJoin(incidents,
    (impressionValue, clickValue) -> impressionValue + "/" + clickValue,
    // KStream-KStream joins are always windowed joins, hence we must provide a join window.
    JoinWindows.of(joinWindowSizeMs).until(windowRetentionTimeMs),
    stringSerde, stringSerde, stringSerde);

// Write the results to the output topic.
impressionsAndClicks.to(stringSerde, stringSerde, "outputTopic");
4
Michael G. Noll