我有ServiceA,它产生DomainChangeEvents并将它们提交到kafka中的主题,然后ServiceB使用kafka主题中的此事件,并将更改应用于存储在内存中的读取模型。 DomainChangeEvent中的某些事件是重置事件,而某些重置域是起点。重新启动ServiceB时,我想读取上次重置的ChangeEvent,然后再重新构建域。
ServiceB在docker中作为复制服务午餐。
因为我想要ServiceB的每个副本中的所有ChangeEvent,所以我不能给它们相同的group.id,否则消息将达到负载平衡,而我不会在所有副本中都获得所有事件。重新启动后如何配置ServiceB从最新的重置事件继续?
我尝试在ServiceB上设置随机group.id,并在使用它后提交重置消息,但是重新启动后,我有不同的group.id,因此所有消息均从头开始被使用。
考虑为docker副本提供不同的配置,但是在我阅读docker服务时,所有副本都配置为相同,这不是一个选择。
答案 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
}
调用此方法将使您的使用者完全位于每个分区中的所需位置。我不确定是否要回答您的问题,但希望对您有帮助!