【问题标题】:Kafka Streams - is it possible to reduce the number of internal topics created by multiple aggregationsKafka Streams - 是否可以减少由多个聚合创建的内部主题的数量
【发布时间】: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


    【解决方案1】:

    如果要按不同的属性进行分组,则无法避免多个重新分区的主题。假设您有两个分组属性 g1g2 以及三个具有以下值的记录:

    r1 = g1:A, g2:1
    r2 = g1:A, g2:2
    r3 = g1:B, g2:2
    

    因此,要根据g1 正确聚合记录,必须将记录r1r2 组合在一起。假设您的重新分区主题有 2 个分区 p1p2,则记录会重新分配,如

    p1: r1, r2
    p2: r3,
    

    另一方面,如果您在 r2 上聚合,则记录 r2r3 必须组合在一起:

    p1: r1
    p2: r2,r3
    

    请注意,r2 对于这两种情况都必须转到不同的分区,因此,不可能使用单个主题,但每个分组需要一个主题。 (这不是 Kafka 特定的——任何其他框架也需要多次复制和重新分配日期)。

    理论上,如果您添加更多语义信息(如超级键、子键或 1 对 1 键映射),则可以减少主题的数量。但这不受 Kafka Streams(和 AFAIK,没有其他可比系统)的支持。

    【讨论】:

      猜你喜欢
      • 2017-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-08
      • 1970-01-01
      • 2016-10-12
      • 1970-01-01
      相关资源
      最近更新 更多