[英]Should django model object instances be passed to celery?
# 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记录分发给在多台机器上运行的工作人员?
这可能是一个更好的主意吗? 如果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()
我相信通过PK而不是整个模型对象更好更安全。 由于PK只是一个数字,序列化也更简单。 最重要的是,您可以使用更安全的sarializer(json / yaml而不是pickle),并且可以放心,您在序列化模型时不会遇到任何问题。
由于该文章说:
由于Celery是一个分布式系统,因此您无法知道在哪个进程中运行,甚至无法知道运行任务的机器。 因此,您不应该将Django模型对象作为参数传递给任务,而是从数据库中重新获取对象几乎总是更好,因为可能存在竞争条件。
是。 如果数据库中有数百万条记录,那么这可能不是最好的方法,但由于你必须经历所有数百万条记录,那么无论你做什么,你的数据库都会受到很大影响。硬。
以下是一些替代方案,其中没有一个我称之为“更好”,只是不同。
./manage.py my_task a
会更新姓氏以“a”开头的所有记录。 显然你必须多次运行才能通过整个数据库 请记住,.save()将更难“击中”数据库,然后实际选择数百万条记录。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.