我可以在Kafka流中的多个实例中使用相同的state.dir吗?

时间:2019-07-03 05:31:16

标签: apache-kafka apache-kafka-streams

我的用例是获取Kafka主题中的 any 键的最新值。为此,我目前正在使用GlobalStateStore。

问题是,如果每个实例的application.id都不同,那么将创建一个不同的状态目录。

我想要的是在所有实例之间重用现有的状态存储目录,以避免重复数据。 这是因为我所有的应用程序实例都在同一台计算机上运行,​​因此没有必要使用不同的状态目录。

我已执行以下操作:

使用相同的 application.id 并创建了2个流实例, 这两个实例指向相同的state.dir,但状态存储实例不同(java对象不同) statestore1和statestore2

,然后做一个测试,我做了以下工作:

while(true)
{
 new Thread(()-> stateStore1.get(key)).start();
 new Thread(()-> stateStore2.get(key)).start();
}

然后我开始在主题中产生值...

我观察到所有状态存储实例(statestore1和statestore2)都在更新相同的状态存储(即相同的state.dir)(因为这是代码)

在这样做的测试中,我没有遇到任何问题。但是..我想应该在将数据写入state.dir之前获取写锁定。 现在,如果由于某种原因statestore1没有释放锁,那么statestore2将继续等待吗?

我的上述方法是否安全或还有其他方法?

更新

用例是,我希望在不同的进程(不同的JVM实例)之间共享一些公共数据。由于数据是通用的,因此不必为每个进程都拥有一个全局存储(因为这将是多余的)。

所有进程都应具有读写该存储的能力,因为每个进程彼此独立。 因此,如果一个进程出现故障,则另一个进程可以执行其工作(将最新值存储在全局存储中,并在需要时获取它)。

2 个答案:

答案 0 :(得分:0)

如果全部都在同一台计算机上运行,​​并且要共享一个全局存储,则不应使用多个实例,而应在一个实例中使用多个线程。

全局存储被设计为按实例复制,这正是您要避免的。

答案 1 :(得分:0)

首先,state_dir使用目录的参数,将在其中创建值为application.id的文件夹。

例如,如果state_dirC:\tmp,而application.id test ,则文件夹将是C:\tmp\test

因此,如果将state_dir设置为C:\tmp\test而不是C:\tmp且具有相同的application.id或不同的application.id,则将创建一个新目录在C:\tmp\test\中创建为C:\tmp\test\testC:\tmp\test\some_other_application_id

这些互不冲突。仍然会有多个全球商店。

但是,如果两个state_dir实例的C:\tmp都被赋予KafkaStreams,那么将会有一个例外说明

  

无法锁定全局状态目录。如果多个   KafkaStreams实例使用相同的主机在同一主机上运行   状态目录

对于在所有实例中具有通用位置的用例,最好将数据库用作Kafka的接收器(使用Kafka connect API或手动从流写入数据库)。

如果用例不需要复杂的类似SQL的查询,那么您可以拥有自己的RocksDB,它将为同一台计算机上运行的所有实例写入同一目录。

Kafka似乎不支持这种开箱即用的情况。