多个Django Celery任务正在尝试保存到同一个对象并失败

时间:2013-09-06 21:26:38

标签: python django celery django-celery

我的tasks.py文件中有三个Celery @tasks,它们经常排队并由具有相似处理时间的单独工作人员同时处理。我认为我遇到的问题是他们都试图在其他用户配置文件对象完成之前更新它们。看来完成的三个进程中的最后一个是成功写入数据库的进程。如果我在几个任务之间运行这些任务都完成得很好。

知道问题是什么,或者在实际运行之前一直尝试保存到配置文件的方法是什么?

提前感谢您的帮助!

3 个答案:

答案 0 :(得分:3)

我假设您正在使用django,因为您已将其标记为此类。如果是这样,您可以使用select_for_update(documentation)来锁定对象。这将阻止其他工作人员,直到事务完成。如果您的任务运行很长时间,您可以获得超时,以便捕获该异常,并在必要时重试。

from django.db import transaction
from celery.task import task

@task
def mytask(mpk):
    with transaction.commit_on_success():
        my_obj = MyModel.objects.select_for_update().get(pk=mpk)
        ...

请注意,这不适用于sqlite。

答案 1 :(得分:2)

Django ORM可以在这里发挥作用。如果您使用model_object.save()方法,则会更新所有字段。如果您的任务正在更新同一对象中的不同字段,您可以考虑使用ModelClass.objects.filter(pk=model_id).update(some_field=some_value),但在这里您可能会考虑不同的RDBMS如何实现表/行锁定。

另一种选择是使用Celery Chord并在完成获取用户数据的所有任务时更新用户配置文件。您可能需要实现分布式信号量,因此唯一的和弦任务将同时针对同一用户配置文件执行。

答案 2 :(得分:0)

看起来它更像是数据库锁定问题。您是否尝试编辑配置文件并在数据库中允许更多的并发?例如,在Postgre Debian上编辑你的conf文件:

nano /etc/postgresql/9.4/main/postgresql.conf

然后你可以在conf文件中设置这样的东西:

max_connections=100
shared_buffers = 3000MB
temp_buffers = 800MB
effective_io_concurrency = 5
max_worker_processes = 15

这应该允许您在描述时进行读/写。

相关问题