# models.py
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
text_blob = models.CharField(max_length=50000)
# tasks.py
import celery
@celery.task
def my_task(person):
# example operation: does something to person
# needs only a few of the attributes of person
# and not the entire bulky record
person.first_name = person.first_name.title()
person.last_name = person.last_name.title()
person.save()
在我的应用程序某处我有类似的东西:
from models import Person
from tasks import my_task
import celery
g = celery.group([my_task.s(p) for p in Person.objects.all()])
g.apply_async()
如何有效且均匀地将人员记录分发给在多台计算机上运行的员工?
这可能是个更好的主意吗?如果Person有几百万条记录,难道不会压倒db吗?
# tasks.py
import celery
from models import Person
@celery.task
def my_task(person_pk):
# example operation that does not need text_blob
person = Person.objects.get(pk=person_pk)
person.first_name = person.first_name.title()
person.last_name = person.last_name.title()
person.save()
#In my application somewhere
from models import Person
from tasks import my_task
import celery
g = celery.group([my_task.s(p.pk) for p in Person.objects.all()])
g.apply_async()
答案 0 :(得分:12)
我认为通过PK而不是整个模型对象更好更安全。由于PK只是一个数字,序列化也更简单。最重要的是,您可以使用更安全的sarializer(json / yaml而不是pickle),并且可以放心,您在序列化模型时不会遇到任何问题。
正如this文章所说:
由于Celery是一个分布式系统,因此您无法知道在哪个进程中运行,甚至无法知道任务运行在哪台机器上。因此,您不应该将Django模型对象作为任务的参数传递,而是从数据库中重新获取对象几乎总是更好,因为可能存在竞争条件。
答案 1 :(得分:1)
是。如果数据库中有数百万条记录,那么这可能不是最好的方法,但是因为你必须经历所有数百万条记录,那么无论你做什么,你的数据库都会受到很大影响。硬。
以下是一些替代方案,其中没有一个我称之为“更好”,只是不同。
./manage.py my_task a
将更新姓氏以“a”开头的所有记录。显然你必须多次运行才能通过整个数据库请记住,.save()将更难“击中”数据库,然后实际选择数百万条记录。