2013-02-26 54 views
18
# 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() 

在我的应用程序的地方我有类似:应该将django模型对象实例传递给芹菜?

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() 
  • 芹菜泡菜p来将其发送到工人的权利?
  • 如果工作人员在多台机器上运行,整个人是否会通过网络传输对象(连同主要不需要的庞大text_blob)?有没有办法避免它?
  • 如何将人员记录有效均匀地分配给多台机器上运行的员工?

  • 这可能是一个更好的主意吗?如果Person有几百万条记录,它不会压倒数据库吗?

    # 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

使用任务延迟,并把它的计时器 – catherine 2013-02-26 00:43:29

+0

@catherine计时器如何帮助我在这种情况下? – 2013-02-26 00:52:25

+0

对不起,这个计时器我的错误,这只是任务延迟。当这个人拥有数百万条记录时,芹菜会延迟任务并通过逐一发送 – catherine 2013-02-26 00:57:05

回答

1

是。如果数据库中有数百万条记录,那么这可能不是最好的办法,但是由于你必须经历数百万条记录,所以无论你做什么,你的数据库都会被打得漂亮硬。

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

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

请记住,.save()将会对数据库造成更大的“打击”,然后实际选择数百万条记录。

+0

所以.title()是这里的一个示例操作,我想在它的帮助下指出,并不是对象所具有的所有内容都被my_task()使用。 – 2013-02-26 00:54:38

+0

分批保存可以减少'命中'的强度,不是吗?但是,如何有效地批量发送? – 2013-02-26 00:57:13

10

我相信通过PK而不是整个模型对象会更好更安全。由于PK只是一个数字,所以序列化也简单得多。最重要的是,你可以使用一个更安全的sarializer(json/yaml代替pickle),并且心安理得地让你在序列化你的模型时不会有任何问题。

由于this文章说:

由于芹菜是一个分布式系统,你可以不知道在哪个过程中,甚至在任务将运行什么机器。所以你不应该把Django模型对象作为参数传递给任务,它总是更好地从数据库中重新获取对象,因为可能存在竞争条件。

相关问题