【发布时间】:2017-05-25 06:24:18
【问题描述】:
我有一个 Kafka Streams 应用程序,它按多个值对传入消息进行分组。例如:
示例消息:
{ "gender": "female", "location": "canada", "age-group": "25-30" }
拓扑:
table
.groupBy((key, value) -> groupByGender) // example key: female
.count("gender-counts");
table
.groupBy((key, value) -> groupByLocation) // example key: canada
.count("location-counts");
table
.groupBy((key, value) -> groupByAgeGroup) // example key: 25-30
.count("age-group-counts");
这会产生很多主题:
my-consumer-gender-counts-changelog
my-consumer-gender-counts-repartition
my-consumer-location-counts-changelog
my-consumer-location-counts-repartition
my-consumer-age-group-counts-changelog
my-consumer-age-group-counts-repartition
如果我们可以将多个聚合发送到单个状态存储,并按值包含分组作为键的一部分,那就太好了。例如:
table
.groupBy((key, value) -> groupByGender) // example key: female_gender
.count("counts");
table
.groupBy((key, value) -> groupByLocation) // example key: canada_location
.count("counts");
table
.groupBy((key, value) -> groupByAgeGroup) // example key: 25-30_age_group
.count("counts");
这将导致更少的主题:
counts-changelog
counts-repartition
目前这似乎是不可能的(无论如何都使用 DSL),因为使用 groupBy 运算符会创建一个内部主题以进行重新分区,所以如果我们有多个子拓扑 groupBy 不同的东西,那么 Kafka Streams 将尝试从多个源注册相同的重新分区主题。这会导致以下错误:
org.apache.kafka.streams.errors.TopologyBuilderException: Invalid topology building: Topic counts-repartition has already been registered by another source.
at org.apache.kafka.streams.processor.TopologyBuilder.validateTopicNotAlreadyRegistered(TopologyBuilder.java:518)
如果 groupBy 可以返回多条记录(例如,像 flatMap 那样),那么我们可以返回一组记录(每个分组一个记录),但这似乎也不可能使用DSL。
我的问题是,给定一个可以按多个值分组的记录(例如{ "gender": "female", "location": "canada", "age-group": "25-30" }),是否应该关注创建多个主题(每个分组 2 个)(例如,我们有 100 个不同的分组? )?当一条记录可以按多个值分组时,是否还有其他更适合的策略?我的提议(将多个聚合下沉到单个变更日志主题)是一个坏主意(即使唯一键的数量非常少)?
【问题讨论】:
标签: apache-kafka apache-kafka-streams