我的用例是获取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实例)之间共享一些公共数据。由于数据是通用的,因此不必为每个进程都拥有一个全局存储(因为这将是多余的)。
所有进程都应具有读写该存储的能力,因为每个进程彼此独立。 因此,如果一个进程出现故障,则另一个进程可以执行其工作(将最新值存储在全局存储中,并在需要时获取它)。
答案 0 :(得分:0)
如果全部都在同一台计算机上运行,并且要共享一个全局存储,则不应使用多个实例,而应在一个实例中使用多个线程。
全局存储被设计为按实例复制,这正是您要避免的。
答案 1 :(得分:0)
首先,state_dir
使用目录的参数,将在其中创建值为application.id
的文件夹。
例如,如果state_dir
是C:\tmp
,而application.id
是 test ,则文件夹将是C:\tmp\test
>
因此,如果将state_dir
设置为C:\tmp\test
而不是C:\tmp
且具有相同的application.id
或不同的application.id
,则将创建一个新目录在C:\tmp\test\
中创建为C:\tmp\test\test
或C:\tmp\test\some_other_application_id
。
这些互不冲突。仍然会有多个全球商店。
但是,如果两个state_dir
实例的C:\tmp
都被赋予KafkaStreams
,那么将会有一个例外说明
无法锁定全局状态目录。如果多个 KafkaStreams实例使用相同的主机在同一主机上运行 状态目录
对于在所有实例中具有通用位置的用例,最好将数据库用作Kafka的接收器(使用Kafka connect API或手动从流写入数据库)。
如果用例不需要复杂的类似SQL的查询,那么您可以拥有自己的RocksDB
,它将为同一台计算机上运行的所有实例写入同一目录。
Kafka似乎不支持这种开箱即用的情况。