为来自不同组的Kafka使用者配置相同的偏移量

时间:2019-06-27 08:36:35

标签: docker apache-kafka

我有ServiceA,它产生DomainChangeEvents并将它们提交到kafka中的主题,然后ServiceB使用kafka主题中的此事件,并将更改应用于存储在内存中的读取模型。 DomainChangeEvent中的某些事件是重置事件,而某些重置域是起点。重新启动ServiceB时,我想读取上次重置的ChangeEvent,然后再重新构建域。

ServiceB在docker中作为复制服务午餐。

因为我想要ServiceB的每个副本中的所有ChangeEvent,所以我不能给它们相同的group.id,否则消息将达到负载平衡,而我不会在所有副本中都获得所有事件。重新启动后如何配置ServiceB从最新的重置事件继续?

我尝试在ServiceB上设置随机group.id,并在使用它后提交重置消息,但是重新启动后,我有不同的group.id,因此所有消息均从头开始被使用。

考虑为docker副本提供不同的配置,但是在我阅读docker服务时,所有副本都配置为相同,这不是一个选择。

1 个答案:

答案 0 :(得分:1)

一种可能的解决方案是,通过将偏移量手动提交到例如数据库中,来存储您希望其他使用者从中开始的那些点。

看起来像这样的表

Topic  Partition  Offset

topicA 0          112
topicA 1          125
topicB 0          2313
topicB 1          2984
topicB 2          2554

这些将是您的“最新重置”点,或您的消费者希望从中开始的位置。正如您正确地说的,subscribe()方法的问题在于它取决于 group.id 参数,并且在进行消费者重新平衡和协调游戏。

为了从固定点(或不同分区中的一组点)进行消耗,您应该改为调用assign()。使用这种方法,您可以手动为用户指定分区列表。没有group.id,没有动态分区分配,也没有偏移量加载,这正是您所需要的。

分配分区后,应致电seek()。借助seek,您可以告诉使用者要从assign()方法中指定的分区开始读取哪个偏移量。

例如,要从任何主题的“最新重置”开始阅读,您应该执行以下操作:

//seeking the last offset of topicA's partition0
public void setStartPosition(TopicPartition partition, long offset) 
{
     consumer.assign(Collections.singletonList(partition)); //f.e-> partition0
     consumer.seek(partition, offset);                      //f.e -> 112
}

调用此方法将使您的使用者完全位于每个分区中的所需位置。我不确定是否要回答您的问题,但希望对您有帮助!