芹菜与redis的任务优先级

时间:2013-03-06 05:47:26

标签: python celery distributed

我想用芹菜实现分布式作业执行系统。鉴于rabbitMQ不支持优先级,我很痛苦地需要这个功能,我转向celery + redis。

在我的情况下,任务与硬件密切相关,例如,任务A只能在Worker 1上运行,因为只有Worker 1的PC才能获得必要的硬件。我将每个worker的CONCURRENCY设置为1,这样一个worker每次只能运行一个任务。每项任务大约需要2分钟。

要实现优先级功能,首先我在调用priority时尝试添加apply_async()参数,例如apply_async(priority=0)apply_async(priority=9)。在这个测试中,我只启动了一个COCURRENCY = 1的Worker,并以不同的优先级逐个启动了10个任务。我希望看到apply_async(priority=0)启动的任务将优先运行,但不幸的是,它们刚刚开始作为启动命令。

然后我尝试做一些工作。我克隆了每个任务,因此对于每个任务我都有task_high和task_low,由@celery.task(priority=0)@celery.task(priority=1)修饰。然后我做了与上面相同的测试,这次它更好,当开球顺序是“HH-LLLL-HHHH”时,真正的顺序是“HH-L-H-H-L-H-L-L-H”。我想redis在这里做了一些调度和平衡工作。

但这仍然不能满足我的期望。我希望得到像“HHHHHH-LLLL”这样的订单,因为对于某些任务,我只有一台带有必要硬件的合适机器,并希望尽快运行高优先级任务。

我在互联网上搜索了其他工作,例如使用两个队列,一个用于高优先级任务,另一个用于低优先级,前者使用2台机器,后者使用1台机器。但由于我的硬件非常有限,这对我不起作用。

你能提出一些建议吗?

2 个答案:

答案 0 :(得分:16)

Celery Redis运输确实尊重优先领域, 但Redis本身并没有优先考虑的概念。

通过为每个队列创建n个列表来实现优先级支持 并在BRPOP命令中使用该顺序。 我在这里说n因为即使有10(0-9)个优先级,这些也是 默认情况下合并为4个级别以节省资源。 这意味着名为celery的队列将真正分成4个队列:

['celery0', 'celery3`, `celery6`, `celery9`]

如果您想要更多优先级,可以设置priority_steps传输选项:

BROKER_TRANSPORT_OPTIONS = {
    'priority_steps': list(range(10)),
}

尽管如此,请注意,这绝不会像优先实施的那样好 在服务器级别,并且最多可能是近似的。但它可能仍然是好的 足以满足您的申请。

答案 1 :(得分:0)

有关redis邮件优先级的Celery文档在redis-message-priorities上,您可以自定义优先级。以10为例:

  1. 设置priority_steps传输选项
app.conf.broker_transport_options = {
    'priority_steps': list(range(10)),
    'queue_order_strategy': 'priority',
}
  1. 以正常方式启动芹菜工作者
celery -A tasks worker --loglevel=info
  1. 呼叫任务, 0为最高优先级,9为最低优先级
custom_priority=5 
task.apply_async(args=[arg1, arg2], kwargs={'kwarg1': 'x', 'kwarg2': 'y'},priority=custom_priority)