Complex 在历史数据上加入 Kafka Streams

问题描述 投票:0回答:0

我想弄清楚我是否应该将数据发送到数据库并使用数据库执行复杂的连接,或者是否可以避免使用数据库。

考虑具有以下结构的 Kafka 主题:

Citizen: 
    String name (key)
    Date age
    String partner
    String father
    String mother

让我们假设名字是唯一的。

目标是将该主题与自身结合起来以实现以下目标:

Output: 
    String name (key)
    Date age
    String partner
    Date partnerAge <--
    String father
    Date fatherAge <--
    String mother
    Date motherAge <--

换句话说,目标是让公民与其直系亲属团聚。使用 Kafka 流执行此操作的最佳方法是什么?使用其他技术也很好。考虑到每分钟大约有 10,000 条消息,这些消息会保留一周,因此在主题中的任何给定时间总共有大约 1 亿条消息。该处理像往常一样在 Kafka 流中由 RocksDB 支持,这意味着 Kafka 流持有一个 RocksDB 表,其中包含每个公民的当前数据,并将其用于连接,据我所知。

这是我的想法:

  • 以 ktable x ktable 的形式加入流。这样做的问题是,除了更改密钥外,没有其他方法可以保证流处理器的给定实例将负责同时包含公民、伙伴和父母的分区。让我们想象一下,以公民、伴侣和父母都拥有相同密钥的方式更改密钥。现在,如果公民与另一个分区中的公民再婚怎么办?有必要通过更改密钥将公民、他们的孩子、他们孩子的孩子等移动到另一个分区。现在将如何实施?除了使用全局 ktables 或使用数据库之外,我想不出任何其他方法。但不管用什么方案,这都是一个复杂的方案,难以维护,没有进一步思考的意义。

  • 创建 3 个额外的主题,它们是:

    • partner - citizen 主题的克隆,但使用 partner 作为键。这将公民和他们的伙伴放在同一个分区中。

    • mother;father - 包含有关母亲/父亲的信息,使用孩子的名字作为键。这将公民和他们的父母放在同一个分区中。但这本身就是一个挑战:需要 kstream(Citizen 主题)-globalKTable(也是 Citizen 主题)连接,以便在更新公民时,对 globalKTable 执行检查,以便当公民是某人的母亲时,在母亲主题上创建了一个更新的条目,父亲也是如此。

      由于所有数据都是同一个分区,所以可以使用ktable-ktable joins。首先将 Citizen 主题与 Partner 主题连接起来,然后将结果与父亲主题连接起来,最后将结果与母亲主题连接起来。这工作正常,但需要为每个连接创建一个新主题。此外,它还给状态存储带来了巨大的负担。这似乎是一种解决方法而不是可靠的解决方案。

  • 使用 kstream-globalktable 连接将公民与其余数据连接起来。换句话说,将 citizen kstream(以partner为键)与citizen globalktable连接以获取合作伙伴信息,然后将citizen kstream(以mother为键)与citizen globalktable连接以获取母亲信息,父亲也是如此。这样做的问题是,如果伴侣、母亲或父亲的数据发生变化,输出将不会更新。所以需要一个额外的操作:使用另一个 kstream(citizen)-globaktable(output),这样当一个公民被更新时,也会更新它在所有输出中的数据。同样,有大量数据被放入状态存储以支持 globalktable 连接。

问题 1:是否有一种可靠的方法可以使用 Kafka Streams 实现像这样的复杂连接?

问题二:这个join是否可以通过Spark/Flink等其他流处理框架更好的完成? Flink 有 SQL 支持,但我不确定它有多有限。

问题三:流处理框架涉及到处理历史数据,还有意义吗?也许数据应该全部传输到数据库,然后从那里进行处理。这似乎是目前最好的选择。

database apache-kafka architecture apache-kafka-streams stream-processing
© www.soinside.com 2019 - 2024. All rights reserved.