我想在同一实例上运行2种拓扑。 1个拓扑涉及状态存储,其他拓扑涉及全局存储。我如何成功做到这一点?
我创建了一个具有3个分区的主题,然后在1个拓扑中添加了状态存储,并在第二个拓扑中添加了全局存储。
拓扑1:
public void createTopology() {
Topology topology = new Topology();
topology.addSource("source", new KeyDeserializer(), new ValueDeserializer(), "topic1");
topology.addProcessor("processor1", new CustomProcessorSupplier1(), "source");
final KeyValueStoreBuilder<Bytes, byte[]> rStoreBuilder = new KeyValueStoreBuilder<>(new RocksDbKeyValueBytesStoreSupplier("rstore"), Serdes.Bytes(), Serdes.ByteArray(), Time.SYSTEM);
rStoreBuilder.withLoggingEnabled(new HashMap<>());
topology.addStateStore(rStoreBuilder, "processor1");
Properties p = new Properties();
p.put(APPLICATION_ID_CONFIG, "stream1");
p.put(BOOTSTRAP_SERVERS_CONFIG, KafkaUtil.getBootStrapServers());
p.put(DEFAULT_KEY_SERDE_CLASS_CONFIG, KeySerde.class);
p.put(DEFAULT_VALUE_SERDE_CLASS_CONFIG, ValueSerde.class);
streams = new KafkaStreams(topology, p);
streams.start();
}
拓扑2:
public void createTopology() {
Topology topology = new Topology();
final KeyValueStoreBuilder<Bytes, byte[]> rStoreBuilder = new KeyValueStoreBuilder<>(new RocksDbKeyValueBytesStoreSupplier("rstoreg"), Serdes.Bytes(), Serdes.ByteArray(), Time.SYSTEM);
rStoreBuilder.withLoggingDisabled();
topology.addGlobalStore(rStoreBuilder, "globalprocessname", Serdes.Bytes().deserializer(), Serdes.ByteArray().deserializer(), "topic1", "processor2", new CustomProcessorSupplier1());
Properties p = new Properties();
p.put(APPLICATION_ID_CONFIG, "stream1");
p.put(BOOTSTRAP_SERVERS_CONFIG, KafkaUtil.getBootStrapServers());
p.put(DEFAULT_KEY_SERDE_CLASS_CONFIG, KeySerde.class);
p.put(DEFAULT_VALUE_SERDE_CLASS_CONFIG, ValueSerde.class);
p.put(STATE_DIR_CONFIG, "/tmp/" + System.getProperty("server.port"));
streams = new KafkaStreams(topology, p);
streams.start();
}
}
运行单个实例时:-
预期: 状态存储区和全局存储区都必须包含所有键(来自topic1所有输入分区的数据
实际: 状态存储包含2个分区中的数据 全局存储包含来自1个分区的数据
运行此代码的2个实例时:-
预期:两个全局存储区都必须包含所有数据。 3个分区分为2个状态存储,其中包含部分数据
Actual:(S表示状态存储,G表示全局存储,P表示输入数据的分区) S1-P1 G1-P2 S2-P3 G2-P1,P2,P3
答案 0 :(得分:1)
问题出在StreamsConfig.APPLICATION_ID_CONFIG
上。您可以将它们用于两种不同类型的应用程序。
StreamsConfig.APPLICATION_ID_CONFIG
的值用作group.id
。
group.id
用于扩展应用程序。如果您具有同一应用程序的两个实例(具有相同的group.id
),则它们开始处理分区子集中的消息。
在您的情况下,您有两个不同的应用程序,但是它们使用相同的StreamsConfig.APPLICATION_ID_CONFIG
。为它们中的每一个分配分区的子集(App1:2个分区,App2:1分区),并且它们仅处理整个消息的子集。这是消费者组机械。
有关消费者组的更多信息,您可以找到: