【问题标题】:KTable with windowing produces wrong type带窗口的 KTable 产生错误的类型
【发布时间】:2018-05-11 19:24:08
【问题描述】:

我在 Kafka 中创建带有时间窗口的 KTable 时遇到了一些问题。

我想创建一个像这样计算流中 ID 数量的表。

ID (String) |  Count (Long)
    X       |       5
    Y       |       6
    Z       |       7

等等。我希望能够使用 Kafka REST-API 获取表格,最好是 .json。

这是我现在的代码:

    StreamsBuilder builder = new StreamsBuilder();

    KStream<String, String> streams = builder.stream(srcTopic);

    KTable<Windowed<String>, Long> numCount = streams
            .flatMapValues(value -> getID(value))
            .groupBy((key, value) -> value)
            .windowedBy(TimeWindows.of(windowSizeMs).advanceBy(advanceMs))
            .count(Materialized.<String, Long, WindowStore<Bytes, byte[]>>as("foo"));

我现在面临的问题是该表不是创建为&lt;String, Long&gt;,而是创建为&lt;String, String&gt;。这意味着我无法获得正确的计数,而是我收到了正确的密钥,但计数已损坏。我尝试使用Long.valueOf(value) 将其强制为Long,但没有成功。我不知道如何从这里开始。我需要将 KTable 写入新主题吗?由于我希望表可以使用 kafka REST-API 进行查询,所以我认为不需要它,对吗? Materialized.&lt;String, Long, WindowStore&lt;Bytes, byte[]&gt;&gt;as("foo") 应该使它可以作为“foo”查询,对吧?

KTable 创建了一个changelog-topic,这足以使其可查询吗?还是我必须为其创建一个新主题才能写入?

我现在正在使用另一个 KStream 来验证输出。

KStream<String, String> streamOut = builder.stream(srcTopic);

streamOut.foreach((key, value) -> System.out.println(key + " => " + value));

它输出:

 ID    COUNT
2855 => ~
2857 => �
2859 => �
2861 => V(
2863 => �
2874 => �
2877 => J
2880 => �2
2891 => �=

无论哪种方式,我都不想使用 KStream 来收集输出,我想查询 KTable。但如前所述,我不太了解查询的工作原理..

更新

设法让它工作

    ReadOnlyWindowStore<String, Long> windowStore =
            kafkaStreams.store("tst", QueryableStoreTypes.windowStore());
        long timeFrom = 0;
        long timeTo = System.currentTimeMillis(); // now (in processing-time)
        WindowStoreIterator<Long> iterator = windowStore.fetch("x", timeFrom, timeTo);
        while (iterator.hasNext()) {
          KeyValue<Long, Long> next = iterator.next();
          long windowTimestamp = next.key;
          System.out.println(windowTimestamp + ":" + next.value);
        }

非常感谢,

【问题讨论】:

    标签: java apache-kafka apache-kafka-streams


    【解决方案1】:

    KTable 的输出类型是&lt;Windowed&lt;String&gt;,String&gt;,因为在 Kafka Streams 中并行维护多个窗口以允许处理乱序数据。因此,不是的情况是,只有一个窗口实例,而是并行的许多窗口实例。 (参见https://docs.confluent.io/current/streams/developer-guide/dsl-api.html#hopping-time-windows

    保留“旧”窗口允许在数据延迟到达时更新它们。注意,Kafka Streams 语义是基于事件时间的。

    你仍然可以查询KTable——你只需要知道你想查询哪个窗口。

    更新

    JavaDoc 描述了如何查询表:https://github.com/apache/kafka/blob/trunk/streams/src/main/java/org/apache/kafka/streams/kstream/TimeWindowedKStream.java#L94-L101

    KafkaStreams streams = ... // counting words
    Store queryableStoreName = ... // the queryableStoreName should be the name of the store as defined by the Materialized instance
    ReadOnlyWindowStore<String,Long> localWindowStore = streams.store(queryableStoreName, QueryableStoreTypes.<String, Long>windowStore());
    
    String key = "some-word";
    long fromTime = ...;
    long toTime = ...;
    WindowStoreIterator<Long> countForWordsForWindows = localWindowStore.fetch(key, timeFrom, timeTo); // key must be local (application state is shared over all running Kafka Streams instances)
    

    【讨论】:

    • 好的,谢谢!我现在意识到,它当然必须有多个窗口才能工作。问题仍然存在,它将 KTable 返回为&lt;Windowed&lt;String&gt;,String&gt;。我用我现在收到的输出编辑了我的问题。我不明白为什么字符是原来的样子,而不仅仅是应该的“1”或“3”。我是在打印窗口而不是第二个字符串吗?
    • 从您的代码中不清楚您是如何尝试查询的——我更新了我的答案。也许您应该考虑阅读文档。
    • 对不起,我完全忘了用实际查询来更新问题。我的错。谢谢你的帮助!还有一个问题,您知道有什么简单的方法可以在 WindowStore 中获取所有键及其值吗?它似乎只适用于 KeyValueStores...
    • WindowedReadOnlyStore 自 1.1 版本以来具有 all() 方法(参见cwiki.apache.org/confluence/display/KAFKA/…
    猜你喜欢
    • 1970-01-01
    • 2016-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-26
    • 1970-01-01
    • 1970-01-01
    • 2019-08-13
    相关资源
    最近更新 更多