如何在两个Kafka流之间使用持久化的StateStore

时间:2019-04-12 17:01:58

标签: apache-kafka apache-kafka-streams

我在尝试通过Kafka Streams实现以下目标时遇到了麻烦:

  • 在应用启动时,(紧凑的)主题alpha被加载到键值StateStore映射中
  • Kafka Stream从另一个主题消费,使用(.get)上面的地图,最后在主题alpha中产生一条新记录
  • 结果是,即使重新启动了流光,内存映射也应与基础主题对齐。

我的方法如下:

val builder = new StreamsBuilderS()

val store = Stores.keyValueStoreBuilder(
   Stores.persistentKeyValueStore("store"), kSerde, vSerde)
)

builder.addStateStore(store)

val loaderStreamer = new LoaderStreamer(store).startStream()

[...] // I wait a few seconds until the loading is complete and the stream os running

val map = instance.store("store", QueryableStoreTypes.keyValueStore[K, V]()) // !!!!!!!! ERROR HERE !!!!!!!!

builder
  .stream("another-topic")(Consumed.`with`(kSerde, vSerde))
  .doMyAggregationsAndgetFromTheMapAbove
  .transform(() => new StoreTransformer[K, V]("store"), "store")
  .to("alpha")(Produced.`with`(kSerde, vSerde))

LoaderStreamer(store)

[...]
val builders = new StreamsBuilderS()

builder.addStateStore(store)

builder
  .table("alpha")(Consumed.`with`(kSerde, vSerde))

builder.build
[...]

StoreTransformer

[...]
override def init(context: ProcessorContext): Unit = {
  this.context = context
  this.store = 
    context.getStateStore(store).asInstanceOf[KeyValueStore[K, V]]
}

override def transform(key: K, value: V): (K, V) = {
  store.put(key, value)
  (key, value)
}
[...]

...但是我得到的是:

Caused by: org.apache.kafka.streams.errors.InvalidStateStoreException:
The state store, store, may have migrated to another instance.

在尝试获取商店处理程序时。

关于如何实现这一目标的任何想法?

谢谢!

1 个答案:

答案 0 :(得分:2)

您不能在两个Kafka Streams应用程序之间共享状态存储。

根据文档:https://docs.confluent.io/current/streams/faq.html#interactive-queries,可能有上述异常的两个原因:

  • 本地KafkaStreams实例尚未准备好,因此无法查询其本地状态存储。

  • 本地KafkaStreams实例已准备就绪,但特定的状态存储区刚刚迁移到幕后的另一个实例。

最简单的处理方法是等待状态存储可查询:

public static <T> T waitUntilStoreIsQueryable(final String storeName,
                                              final QueryableStoreType<T> queryableStoreType,
                                              final KafkaStreams streams) throws InterruptedException {
  while (true) {
    try {
      return streams.store(storeName, queryableStoreType);
    } catch (InvalidStateStoreException ignored) {
      // store not yet ready for querying
      Thread.sleep(100);
    }
  }
}

可以在confluent github上找到整个示例。