【问题标题】:Kafka Streams processors - state store and input topic partitioningKafka Streams 处理器 - 状态存储和输入主题分区
【发布时间】:2019-03-15 14:51:46
【问题描述】:

我想完全了解 kafka-streams 处理器在划分处理器输入及其状态时必须遵守的规则。具体我想了解:

  1. 对于状态存储使用与输入主题的键不同的键是否可行以及可能的后果是什么
  2. 状态存储键是否在分区之间共享,即如果我在处理属于两个不同分区的记录时尝试访问处理器中的相同键,我是否会得到相同的值

我一直在对此进行一些研究,我发现的答案似乎不是很清楚,有时甚至是矛盾的:例如this one 似乎暗示商店是完全独立的,您可以使用任何键,而 this one 表示您永远不应该使用与输入主题中的键不同的商店。

感谢您的澄清。

【问题讨论】:

    标签: apache-kafka apache-kafka-streams


    【解决方案1】:

    您必须区分输入分区和存储分片/更改日志主题分区以获得完整的图片。此外,这取决于您使用的是 DSL 还是处理器 API,因为 DSL 会进行一些自动重新分区,但处理器 API 不会。因为 DSL 编译为处理器 API,所以我将从这个开始。

    如果您有一个具有 4 个分区的主题,并且您创建了一个使用该主题的有状态处理器,您将获得 4 个任务,每个任务运行一个处理器实例,该实例维护一个存储分片。注意,整体状态被分成4个shard,每个shard基本上和其他shard是隔离的。

    从处理器 API 运行时的角度来看,输入主题分区和状态存储分片(包括它们对应的变更日志主题分区)是一个并行单元。因此,store 的 changelog 主题创建了 4 个分区,changelog-topic-partition-X 映射到 input-topic-partition-X。请注意,Kafka Streams 在写入更改日志主题时使用基于散列的分区,但显式提供分区号,以确保处理 input-topic-partition- 的“处理器实例 X” X,仅读取/写入/写入 changelog-topic-partition-X。

    因此,如果您愿意,运行时与键无关。

    如果您的输入主题没有按键分区,则具有相同键的消息将由不同的任务处理。取决于程序,这可能是好的(例如过滤),也可能不是(例如,每个键的计数)。

    与 state 类似:您可以将任何 key 放入 state store,但这个 key 对相应的 shard 是“本地的”。其他任务,永远不会看到这个键。因此,如果您在不同任务的商店中使用相同的密钥,它们将完全相互独立(就像它们是两个密钥一样)。

    使用处理器 API,您有责任正确分区输入数据并正确使用存储,具体取决于您需要的运算符语义。

    在 DSL 级别,Kafka Streams 将确保数据被正确分区以确保正确的运算符语义。首先,假设输入主题是按键分区的。如果 key 被修改,例如通过selectKey() 并且下游操作符是一个聚合,Kafka Streams 会首先对数据进行重新分区,以确保具有相同 key 的记录在同一个主题分区中。这确保了每个密钥都将在单个存储分片中使用。因此,DSL 将始终对数据进行分区,从而永远不会在不同的分片上处理一个键。

    【讨论】:

    • 如果在拓扑中使用具有 4 个分区的主题并将其作为单个实例运行,相同的状态存储是否会包含来自所有 4 个分区的数据,并且是否可以在同一个 RPC 端点上查询所有4 个分区键?
    • 是的。如果只有一个实例,它将处理所有分区并保存所有存储分片。是的,所有本地分片都可以在该实例上查询。
    猜你喜欢
    • 2017-12-18
    • 1970-01-01
    • 2018-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多