假设我有一个基本的KafkaStreams应用程序,其中包含一个主题(具有多个分区)和一个处理消息的处理器类型,如下所示:
builder.stream(topic)
.process(() -> new MyProcessor());
是否会出现以下情况?对于MyProcessor的特定实例,例如 M (即通过调用处理器供应商获得的特定java对象),以及对于该主题的特定分区,例如 P ,
我检查了documentation关于流任务如何与Kafka主题分区相关但我没有找到有关如何与构造和删除处理器实例和/或(取消)主题分区相关的详细信息重新平衡发生时对现有处理器的影响。
答案 0 :(得分:3)
在Kafka Streams,"处理单位"被称为流任务。
任务可以是有状态的和/或无状态的。当重新平衡事件发生时,在应用程序的一个实例(例如,M
)上运行的任务可能会被移动到应用程序的另一个实例。
主题分区和流任务之间存在1-1映射,这保证了一个且只有一个任务将处理来自特定分区的数据。例如,如果任务3负责从分区P
读取和处理,那么当任务3从实例M
移动到另一个实例M'
时,则M
将停止阅读P
(因为它不再运行任务3),M'
(现在任务3运行)将继续/继续处理P
。
- 在某个时间t1,M从P
接收消息 醇>
让我们说负责处理主题分区P
的流任务称为task(P)
。在时间t1,M
恰好是运行task(P)
的应用实例。这就是上面#1点的情况。
- 在稍后的时间点t2,P从M撤销,因此M不再接收来自P的消息(例如,因为启动了一个处理P的额外工作人员)
醇>
这里,应用程序的另一个实例(您将此实例称为"额外的工作者")负责运行task(P)
。此处,task(P)
会自动从原始应用实例M
迁移到新实例M'
。由task(P)
管理的任何状态(例如,当任务正在执行诸如连接或聚合的有状态操作时)当然将与任务一起迁移。迁移task(P)
后,读取和处理主题分区P
的责任也将从应用实例M
移至M'
。
或许并没有过多考虑"哪个应用实例正在处理主题分区P
?"相反,特定分区始终由特定流任务处理,并且流任务可以跨应用实例移动。 (当然,Kafka的Streams API可以防止不必要的任务迁移,以确保您的应用程序处理保持高效。)
- 稍后,t3,M再次从P
接收消息 醇>
这意味着,在时间t3,由于另一个重新平衡事件,M
被再次分配了任务task(P)
- 可能是因为另一个应用实例M'
已被删除,或发生了需要任务迁移的其他事情。