Kafka Streams KTable国家商店的不同serde

时间:2018-05-11 16:51:29

标签: apache-kafka-streams

作为我们的应用程序逻辑的一部分,我们使用Kafka Streams状态存储进行范围查找,使用builder.table()方法从Kafka主题加载数据。

问题是源主题的密钥被序列化为JSON,并且不适合基于RocksDB的状态存储内部使用的二进制密钥比较。

我们希望通过将密钥传递给Materialized.as()来使用单独的serde。但是,看起来流实现重置传递给用于从表主题加载的原始serdes的任何内容。

这是我在流构建器内部可以看到的内容:

public synchronized <K, V> KTable<K, V> table(final String topic,
                                              final Consumed<K, V> cons,
                                              final Materialized<K, V, KeyValueStore<Bytes, byte[]>> materialized) {
    Objects.requireNonNull(topic, "topic can't be null");
    Objects.requireNonNull(consumed, "consumed can't be null");
    Objects.requireNonNull(materialized, "materialized can't be null");
    materialized.withKeySerde(consumed.keySerde).withValueSerde(consumed.valueSerde);
    return internalStreamsBuilder.table(topic,
                                        new ConsumedInternal<>(consumed),
                                        new MaterializedInternal<>(materialized, internalStreamsBuilder, topic + "-"));
}

任何人都知道为什么这样做,以及是否可以为DSL状态商店使用不同的serde?

请不要建议使用Processor API,这条路线已经过充分探索。每次我需要在将数据保存到状态存储之前按摩数据时,我想避免编写处理器和自定义状态存储。

经过一些挖掘流源后,我发现我可以使用始终为真的谓词将自定义Materialized.as传递给过滤器。但它闻起来有点黑客。

这是我的代码,遗憾的是,我们没有按照我们希望的方式工作,因为&#34; serdes reset&#34;如上所述。

Serde<Value> valueSerde = new JSONValueSerde()
KTable<Key, Value> table = builder.table(
    tableTopic,
    Consumed.with(new JSONKeySerde(), valueSerde)
    Materialized.as(cacheStoreName)
        .withKeySerde(new BinaryComparisonsCompatibleKeySerde())
        .withValueSerde(valueSerde)
)

1 个答案:

答案 0 :(得分:0)

代码按设计工作。从流的角度来看,没有理由为商店使用不同的Serde来读取主题中的数据,因为它知道是相同的数据。因此,如果一个人不使用StreamsConfig中的默认Serdes,那么只需指定一次Serde(Consumed),并且不需要在Materialized中指定它试。

对于您的特殊情况,您可以将该主题作为流来阅读&#34;虚拟聚合&#34;只返回每条记录的最新值(而不是计算实际的聚合)。这允许您为结果类型指定不同的Serde。