java - Kafka 流:从应用程序的每个实例中的所有分区读取
问题描述
使用 KTable 时,当实例/消费者的数量等于分区数时,Kafka 流不允许实例从特定主题的多个分区中读取。我尝试使用 GlobalKTable 实现这一点,问题是数据将被覆盖,也无法对其应用聚合。
假设我有一个名为“data_in”的主题,有 3 个分区(P1、P2、P3)。当我运行 Kafka 流应用程序的 3 个实例(I1、I2、I3)时,我希望每个实例从“data_in”的所有分区中读取数据。我的意思是 I1 可以从 P1、P2 和 P3 中读取,I2 可以从 P1、P2 和 P3、I2 中读取等等。
编辑:请记住,生产者可以将两个相似的 ID 发布到“data_in”中的两个不同分区中。所以当运行两个不同的实例时,GlobalKtable 会被覆盖。
请问,如何实现?这是我的代码的一部分
private KTable<String, theDataList> globalStream() {
// KStream of records from data-in topic using String and theDataSerde deserializers
KStream<String, Data> trashStream = getBuilder().stream("data_in",Consumed.with(Serdes.String(), SerDes.theDataSerde));
// Apply an aggregation operation on the original KStream records using an intermediate representation of a KStream (KGroupedStream)
KGroupedStream<String, Data> KGS = trashStream.groupByKey();
Materialized<String, theDataList, KeyValueStore<Bytes, byte[]>> materialized = Materialized.as("agg-stream-store");
materialized = materialized.withValueSerde(SerDes.theDataDataListSerde);
// Return a KTable
return KGS.aggregate(() -> new theDataList(), (key, value, aggregate) -> {
if (!value.getValideData())
aggregate.getList().removeIf((t) -> t.getTimestamp() <= value.getTimestamp());
else
aggregate.getList().add(value);
return aggregate;
}, materialized);
}
解决方案
将输入主题“data_in”的分区数更改为 1 个分区,或者使用 aGlobalKtable
从主题中的所有分区获取数据,然后您可以将流加入其中。这样,您的应用程序实例不再需要位于不同的消费者组中。
代码将如下所示:
private GlobalKTable<String, theDataList> globalStream() {
// KStream of records from data-in topic using String and theDataSerde deserializers
KStream<String, Data> trashStream = getBuilder().stream("data_in", Consumed.with(Serdes.String(), SerDes.theDataSerde));
thrashStream.to("new_data_in"); // by sending to an other topic you're forcing a repartition on that topic
KStream<String, Data> newTrashStream = getBuilder().stream("new_data_in", Consumed.with(Serdes.String(), SerDes.theDataSerde));
// Apply an aggregation operation on the original KStream records using an intermediate representation of a KStream (KGroupedStream)
KGroupedStream<String, Data> KGS = newTrashStream.groupByKey();
Materialized<String, theDataList, KeyValueStore<Bytes, byte[]>> materialized = Materialized.as("agg-stream-store");
materialized = materialized.withValueSerde(SerDes.theDataDataListSerde);
// Return a KTable
KGS.aggregate(() -> new theDataList(), (key, value, aggregate) -> {
if (!value.getValideData())
aggregate.getList().removeIf((t) -> t.getTimestamp() <= value.getTimestamp());
else
aggregate.getList().add(value);
return aggregate;
}, materialized)
.to("agg_data_in");
return getBuilder().globalTable("agg_data_in");
}
编辑:我编辑了上面的代码以强制对名为“new_data_in”的主题进行重新分区。
推荐阅读
- hyperledger-fabric - 如何使用基于属性的访问控制 (ABAC)
- flutter - 我无法在颤振中使用 DIO 包将图像和表单数据上传到 rest api
- json - Amazon Sagemaker Factorization Machine 预测结果不一致
- php - 两个数组如何将每个内部对象键匹配交叉?
- vba - IF 语句,IF NOT ...False Vs IF TRUE 之间的区别
- intellij-idea - IntelliJ:在@Sql 注释中注入 SQL 作为语言
- ios - iPad 上的渐变背景 iPhone 尺寸
- javascript - 无法将 MongoDB 文档字段设置为 Null
- scikit-learn - 如何缩小词袋模型?
- angular - index.html 位于 dist/src,但 bundle.js 文件位于 dist。无法找到 bundle.js 文件