Kafka Streams当地的国营商店

时间:2018-03-20 09:55:13

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

我有一个简单的流应用程序将一个主题作为输入流并将KeyValues转换为另一个,如:

StoreBuilder<KeyValueStore<Long, CategoryDto>> builder =
        Stores.keyValueStoreBuilder(Stores.inMemoryKeyValueStore(CategoryTransformer.STORE_NAME),
                                    Serdes.Long(), CATEGORY_JSON_SERDE);
    streamsBuilder.addStateStore(builder)
                         .stream(categoryTopic, Consumed.with(Serdes.Long(), CATEGORY_JSON_SERDE))
                         .transform(CategoryTransformer::new, CategoryTransformer.STORE_NAME);

static class CategoryTransformer implements Transformer<Long, CategoryDto, KeyValue<Long, CategoryDto>> {

    static final String STORE_NAME = "test-store";

    private KeyValueStore<Long, CategoryDto> store;

    @Override
    public void init(ProcessorContext context) {
      store = (KeyValueStore<Long, CategoryDto>) context.getStateStore(STORE_NAME);
    }

    @Override
    public KeyValue<Long, CategoryDto> transform(Long key, CategoryDto value) {
      store.put(key, value);
      return KeyValue.pair(key, value);
    }

    @Override
    public KeyValue<Long, CategoryDto> punctuate(long timestamp) {
      return null;
    }

    @Override
    public void close() {

    }
  }

这里我不得不使用变换器,因为我需要获取存储并更新相关值。

问题是使用本地状态存储区和将值放在HashMap内的简单ForeachAction之间有什么区别?

在这种情况下使用本地状态商店有什么好处?

2 个答案:

答案 0 :(得分:4)

虽然代码中没有显示,但我假设您以某种方式阅读并使用存储状态。

使用简单(在内存中)HashMap存储您的状态会使您的状态完全没有持久性,这意味着当下列任何一种情况发生时,您的状态将会丢失(这些都不是特别的,假设它会经常发生):

  • 您的流处理器/应用程序停止,
  • 崩溃,或
  • 由于重新平衡,
  • 部分迁移到其他地方(其他JVM)。

非持久状态的问题是,当发生上述任何一种情况时,kafka-streams将在最后提交的偏移处重新启动处理。因此,在崩溃/停止/重新平衡之前处理的所有记录都不会被重新处理,这意味着当处理重新开始时,HashMap的内容将为空。这当然不是你想要的。

另一方面,如果您使用其中一个提供的状态存储,kafka-streams将确保一旦处理在上面列出的任何中断之后重新启动,状态将可用,就像处理从未停止一样,重新处理任何先前处理过的记录。

答案 1 :(得分:2)

  

问题是使用本地状态存储和将值放在ForeachAction内的简单HashMap之间有什么区别?

如果您的输入主题未进行分区,并且您运行Streams应用程序的单个实例,则本地状态API的值并不大。在这种情况下 - 确定:您可以在处理器中使用HashMap,或者如果您想在重新启动后继续使用some persistent HashMap

当您的主题被分区时,本地存储的值会变得清晰,当您运行Streams应用程序的多个实例时,本地存储的值仍然更清晰。在这种情况下,您需要使用处理器处理特定分区来维护特定状态,并且该状态需要能够与处理器一起移动,以防它移动到不同的Streams实例。在这种情况下 - AKA规模 - 本地存储设施既有必要又非常宝贵。想象一下,必须自己大规模地编排这个,而不是让这个工具成为核心平台(本地状态API)的一部分。

相关问题