Django芹菜任务重复:无法锁定DB?

时间:2016-03-10 15:33:05

标签: django redis celery django-celery

我的django应用程序允许用户相互发送消息,我将一些最近的消息汇集在一起​​,并使用celery和redis通过电子邮件发送它们。

每次用户发送消息时,我都会向数据库添加一条消息,然后触发异步任务以汇集最近60秒内该用户的消息并将其作为电子邮件发送。

tasks.pushMessagePool.apply_async(args = (fromUser,), countdown = 60)

如果用户在接下来的60秒内发送了5条消息,那么我的假设是应创建5个任务,但只有第一个任务发送电子邮件,其他4个任务不执行任何操作。我实现了一个简单的锁定机制,以确保消息只被考虑一次,并确保数据库锁定。

@shared_task
def pushMessagePool(fromUser, ignore_result=True):
    lockCode = randint(0,10**9)
    data.models.Messages.objects.filter(fromUser = fromUser, locked=False).update(locked=True, lockCode = lockCode)
    M = data.models.Messages.objects.filter(fromUser = fromUser, lockCode = lockCode)
    sendEmail(M,lockCode)

通过这种设置,我偶尔会得到(~10%)重复。重复项将在彼此相差10ms内启动,并且它们具有不同的lockCodes。

为什么这种锁定机制不起作用?芹菜是指旧数据库快照吗?这没有任何意义。

1 个答案:

答案 0 :(得分:0)

Djangojack,这是一个类似的问题?但对于SQS。我不确定它是否也适用于Redis?

  

创建SQS队列时,需要设置默认可见性   超时到某个时间,大于你期望的最长时间   任务运行。这是SQS将使所有人都看不到的消息的时间   交付给一个消费者后的其他消费者。我相信   默认为30秒。因此,如果任务需要超过30秒,SQS   将它传递给另一个消费者,因为它假定   第一个消费者死了,没有完成任务。

来自@ gustavo-ambrozio对this answer的评论。