使用数据库存储从卡夫卡消费的消息状态是否正确?

时间:2019-06-27 04:53:16

标签: c# .net-core apache-kafka confluent-kafka

目前,我已经实现了一个kafka使用者,其工作方式如下:

在while循环中:

  1. 消费来自kafka的消息
  2. 将已消耗的消息放入单独的任务中进行处理,从而不会阻塞主线程和使用者循环 2.1仅在处理成功或尝试的尝试次数超过时才提交消息。

步骤#2.1可能需要 1秒至6个小时才能完成

问题在于,如果应用程序崩溃并且有一些任务尚未完成,则在应用程序重新启动(甚至重新平衡)时,这些消息将被消耗并再次处理。

我不想自动提交偏移量,因为它只能保证最多发送一次。我正在考虑使用数据库作为消息状态的存储并按如下方式实现使用者:

在while循环中:

  1. 消费来自kafka的消息
  2. 检查数据库是否存在该消息

    • 如果消息存在于数据库中并且状态为“已完成”,则提交消息

    • 如果数据库中存在消息,但状态为“进行中”,则直接转到步骤4。

    • 如果消息不存在,请转到步骤#3
  3. 将消息以“进行中”状态保存到数据库中

  4. 将已消耗的消息放入单独的任务中进行处理,从而不会阻塞主线程和使用者循环 4.1仅在处理成功或尝试处理的尝试次数超出时,才提交消息并将db中的状态更改为“已完成”。

我不确定使用db是否正确,因为如果我有很多消息,它将减慢使用速度。您能否给我一些有关如何正确实现使用者的建议,以便每个消息仅处理一次?

1 个答案:

答案 0 :(得分:2)

您的使用者应从流(Kafka)中获取任务,以使流不再包含该任务。如果您的工作节点在运行任务时崩溃,则需要实现冗余/错误处理,即全局异常处理和持久性临时存储。因此,我不建议在流旁边将任务存储在数据库中,但是,如果要执行此操作,则最好在Kafka中创建表,因为它们是持久性的。

处理错误时,实施策略由您决定,因为有几种方法可以解决,例如,如果节点崩溃,则准备将任务放回流中,准备由另一个节点捕获,或者您可以记录任务并通知用户任务已失败。