django / celery:在150k Django对象上运行任务的最佳实践?

时间:2011-09-21 00:22:35

标签: django orm celery

我必须在大约150k Django对象上运行任务。做这个的最好方式是什么?我使用Django ORM作为经纪人。数据库后端是MySQL,并且在所有任务的task.delay()期间窒息而死。相关的,我也想从提交表单中解决这个问题,但是由此产生的请求产生了一个非常的响应时间超时。

3 个答案:

答案 0 :(得分:10)

我还会考虑使用除了使用数据库之外的其他东西作为“经纪人”。它真的不适合这种工作。

但是,您可以通过启动任务来创建其他任务,从而将部分开销从请求/响应周期中移除:

from celery.task import TaskSet, task

from myapp.models import MyModel

@task
def process_object(pk):
    obj = MyModel.objects.get(pk)
    # do something with obj

@task
def process_lots_of_items(ids_to_process):
    return TaskSet(process_object.subtask((id, ))
                       for id in ids_to_process).apply_async()

此外,由于您可能没有15000个处理器来处理所有这些对象 与此同时,您可以将对象分成100或1000的块:

from itertools import islice
from celery.task import TaskSet, task
from myapp.models import MyModel

def chunks(it, n):
    for first in it:
        yield [first] + list(islice(it, n - 1))

@task
def process_chunk(pks):
    objs = MyModel.objects.filter(pk__in=pks)
    for obj in objs:
        # do something with obj

@task
def process_lots_of_items(ids_to_process):
    return TaskSet(process_chunk.subtask((chunk, ))
                       for chunk in chunks(iter(ids_to_process),
                                           1000)).apply_async()

答案 1 :(得分:2)

尝试使用RabbitMQ。

RabbitMQ被许多大公司使用,人们真正依赖它,因为它是如此优秀的经纪人。

Here is a great tutorial on how to get you started with it.

答案 2 :(得分:1)

我使用beanstalkd(http://kr.github.com/beanstalkd/)作为引擎。如果你使用django-beanstalkd,添加一个worker和一个任务对Django来说非常简单:https://github.com/jonasvp/django-beanstalkd/

这对我的使用非常可靠。

工人的例子:

import os
import time

from django_beanstalkd import beanstalk_job


@beanstalk_job
def background_counting(arg):
    """
    Do some incredibly useful counting to the value of arg
    """
    value = int(arg)
    pid = os.getpid()
    print "[%s] Counting from 1 to %d." % (pid, value)
    for i in range(1, value+1):
        print '[%s] %d' % (pid, i)
        time.sleep(1)

启动工作/工作人员/任务:

from django_beanstalkd import BeanstalkClient
client = BeanstalkClient()

client.call('beanstalk_example.background_counting', '5')

(从django-beanstalkd的示例应用程序中提取的源代码)

享受!