[英]Kafka streams handle batch data to reset aggregation
我有一些数据到达我的 kafka 主题“数据源”,其中包含以下架构(此处为演示简化):
{ "deal" : -1, "location": "", "value": -1, "type": "init" }
{ "deal": 123456, "location": "Mars", "value": 100.0, "type": "batch" },
{ "deal" 123457, "location": "Earth", "value", 200.0, "type": "batch" },
{ "deal": -1, "location": "", "value", -1, "type": "commit" }
这些数据来自批量运行,我们获取所有交易并重新计算它们的价值。 将其视为一天的开始过程 - 此时,这是所有位置的一组新数据。 目前 init 和 commit 消息没有发送到真正的主题,它们被生产者过滤掉了。
白天,随着事情的变化,会有更新。 这提供了新数据(在本例中,我们可以忽略覆盖数据,因为这将通过重新运行批处理来处理):
{ "deal": 123458, "location", "Mars", "value": 150.0, "type": "update" }
该数据作为 KStream“位置”进入应用程序。
另一个主题“位置”有一个可能的位置列表。 这些作为 KGlobalTable 位置被拉入 java kafka-streams 应用程序:
{ "id": 1, "name": "Mars" },
{ "id": 2, "name": "Earth"}
计划是使用 java 9 kafka-streams 应用程序来聚合这些值,按位置分组。 输出应该类似于:
{ "id": 1, "location": "Earth", "sum": 250.0 },
{ "id": 2, "location": "Mars": "sum": 200.0 }
这是我到目前为止所做的工作:
StreamsBuilder builder = new StreamsBuilder();
/** snip creating serdes, settings up stores, boilerplate **/
final GlobalKTable<Integer, Location> locations = builder.globalTable(
LOCATIONS_TOPIC,
/* serdes, materialized, etc */
);
final KStream<Integer, PositionValue> positions = builder.stream(
POSITIONS_TOPIC,
/* serdes, materialized, etc */
);
/* The real thing is more than just a name, so a transformer is used to match locations to position values, and filter ones that we don't care about */
KStream<Location, PositionValue> joined = positions
.transform(() -> new LocationTransformer(), POSITION_STORE)
.peek((location, positionValue) -> {
LOG.debugv("Processed position {0} against location {1}", positionValue, location);
});
/** This is where it is grouped and aggregated here **/
joined.groupByKey(Grouped.with(locationSerde, positionValueSerde))
.aggregate(Aggregation::new, /* initializer */
(location, positionValue, aggregation) -> aggregation.updateFrom(location, positionValue), /* adder */
Materialized.<Location, Aggregation>as(aggrStoreSupplier)
.withKeySerde(locationSerde)
.withValueSerde(aggregationSerde)
);
Topology topo = builder.build();
我遇到的问题是,这是聚合所有内容 - 所以每日批次,加上更新,然后是下一个每日批次,都被添加。 基本上,我需要一种方法来说“这是下一组批处理数据,对此进行重置”。 我不知道该怎么做 - 请帮忙!
谢谢
因此,如果我理解正确的话,您希望聚合数据,但仅针对最后一天,而丢弃其余数据。
我建议您聚合到一个包含流中所有值的中间类,并且还具有过滤掉其他日子数据的逻辑。 如果我理解正确,那将丢弃最后一个“批处理”类型之前的所有数据。
虽然在 Kotlin 中,我做了一个类似的解决方案,你可以根据需要查看。
您可以做一些事情,但我建议您使用 TimeWindowed Stream。 您可以将时间设置为 1 天的滚动窗口并对该流执行自旋。 您最终将在 KTable 中自己的窗口中汇总每一天。 这样您就不必担心丢弃数据(尽管您可以)并且每一天都将被分开。
有一些很好的例子说明了它们的工作方式: https : //www.programcreek.com/java-api-examples/?api=org.apache.kafka.streams.kstream.TimeWindows
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.