web-dev-qa-db-ja.com

Kafka Streams API:KStream to KTable

ロケーションイベント(key = user_id、value = user_location)を送信するKafkaトピックがあります。これを読み取り、KStreamとして処理できます。

KStreamBuilder builder = new KStreamBuilder();

KStream<String, Location> locations = builder
        .stream("location_topic")
        .map((k, v) -> {
            // some processing here, omitted form clarity
            Location location = new Location(lat, lon);
            return new KeyValue<>(k, location);
        });

それはうまくいきますが、各ユーザーの最後の既知の位置を持つKTableが欲しいです。どうすればいいですか?

中間トピックへの書き込みと読み取りを行うことができます:

// write to intermediate topic
locations.to(Serdes.String(), new LocationSerde(), "location_topic_aux");

// build KTable from intermediate topic
KTable<String, Location> table = builder.table("location_topic_aux", "store");

KTableからKStreamを取得する簡単な方法はありますか?これはKafka= Streamsを使用した最初のアプリなので、おそらく明らかな何かを見逃しています。

29
Guido

現在のところ、これを行うための直接的な方法はありません。 Confluent FAQsで説明されているように、アプローチは完全に有効です。 http://docs.confluent.io/current/streams/faq.html#how-can-i-convert-a-kstream-to-a-ktable -without-an-aggregation-step

これは、コードに関して最も単純なアプローチです。ただし、(a)追加のトピックを管理する必要があり、(b)Kafkaとの間でデータが読み書きされるため、追加のネットワークトラフィックが発生するという欠点があります。

「ダミー削減」を使用する1つの代替方法があります。

KStreamBuilder builder = new KStreamBuilder();
KStream<String, Long> stream = ...; // some computation that creates the derived KStream

KTable<String, Long> table = stream.groupByKey().reduce(
    new Reducer<Long>() {
        @Override
        public Long apply(Long aggValue, Long newValue) {
            return newValue;
        }
    },
    "dummy-aggregation-store");

このアプローチは、オプション1に比べてコードに関してやや複雑ですが、(a)トピックの手動管理が不要で、(b)Kafka is必要はありません。

全体として、自分で決める必要があります。

オプション2では、Kafka Streamsは、内部変更ログトピックを作成して、フォールトトレランスのためにKTableをバックアップします。したがって、両方のアプローチは、Kafka全体として、オプション2のやや複雑なコードとオプション1の手動トピック管理とのトレードオフです。

24
Matthias J. Sax