繁体   English   中英

django模型对象实例应该传递给芹菜吗?

[英]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()
  • 芹菜泡菜将它发送给工人吗?
  • 如果工作人员在多台计算机上运行,​​那么整个人对象(以及主要不需要的庞大的text_blob)是否会通过网络传输? 有没有办法避免它?
  • 如何有效且均匀地将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模型对象作为参数传递给任务,而是从数据库中重新获取对象几乎总是更好,因为可能存在竞争条件。

是。 如果数据库中有数百万条记录,那么这可能不是最好的方法,但由于你必须经历所有数百万条记录,那么无论你做什么,你的数据库都会受到很大影响。硬。

以下是一些替代方案,其中没有一个我称之为“更好”,只是不同。

  1. 为你的Person类实现一个pre_save信号处理程序,它执行.title()的东西。 这样,您的first_name / last_names将始终正确存储在数据库中,您不必再次执行此操作。
  2. 使用带有某种分页参数的管理命令...也许使用姓氏的第一个字母来分割人员。 所以运行./manage.py my_task a会更新姓氏以“a”开头的所有记录。 显然你必须多次运行才能通过整个数据库
  3. 也许你可以用一些创造性的SQL来做到这一点。 我甚至不打算在这里尝试,但它可能值得调查。

请记住,.save()将更难“击中”数据库,然后实际选择数百万条记录。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM