在Django中为多个SQS使用者启用锁定机制的常见做法是什么,所以我可以是幂等的

时间:2012-08-04 18:45:21

标签: django background-process amazon-sqs

SQS希望你的应用程序是幂等的,我有多个消费者/生产者(即使SQS有一次交付机制)我会有竞争条件造成重复和竞争条件消耗,因为我的消费者通过cron作业运行。

我目前的计划是使用Django 1.4 select_for_update,它应该阻止同一行中的其他消费者,执行以下操作:

reminders = EmailReminder.objects.select_for_update().filter(id=some_id)
if not reminders[0].finished:
    reminder.send()
    reminder.update(finished=datetime.now())
# Delete job.

有没有更好的方法来解决这个问题?

1 个答案:

答案 0 :(得分:3)

将django-celery连接到SQS并让它使用celerybeat指定一个定期工作。然后让celeryd worker在任何你想要的队列上运行。只有一个人会一次拿起一份工作并执行它。无需在任何级别引入数据库锁定。

只要您的工作人员在celerybeat发射新任务之前保证完成当前任务,您将永远不需要锁定。现在,如果您认为它们可能会重叠,您可以在以下位置介绍通知状态:

  1. 任何提醒都以“未发送”状态开始。
  2. 您的celerybeat发送请求以处理未发送的电子邮件到队列。
  3. 一些工人拿起它并抓住所有这些。
  4. 工作人员立即将所有人转变为“发送”状态。
  5. 一次发送一个(或批量发送)。
  6. 如果发送失败,请将其状态恢复为未发送状态。
  7. 为成功过渡到发送的所有内容。
  8. 这样,如果celerybeat在原始作业未完成初始批处理时触发另一个作业,则不会发送重复的电子邮件。作为额外的奖励,您可以扩展解决方案并分配负载。