简体   繁体   English

芹菜,一个再见一个队列,并行许多时间队列

[英]celery, one bye one queue and parallel many in time queues

I am trying to use celery to manage tasks. 我正在尝试使用芹菜来管理任务。 The problem i am into now, that i have many minor tasks(emails, cross-server posts, etc) And time consumable tasks, like file uploads. 我现在遇到的问题是,我有许多次要任务(电子邮件,跨服务器帖子等)以及耗时的任务,例如文件上传。

Is there any way, to specify, that uploads will always will be one by one. 有什么方法可以指定,上传将始终是一个接一个的。 Only one task executed in time, while other workers will work on other queues? 只有一个任务及时执行,而其他工作人员会在其他队列上工作吗?

An effective way to serialize the execution of tasks is to use a mutex (Mutual Exclusion). 序列化任务执行的有效方法是使用互斥锁(互斥)。

Python's threading module has a Lock object which can be used to this effect : Python的threading模块具有一个Lock对象 ,可用于实现此目的

# ...
module_lock = threading.Lock() # or make this an attribute in an object with sufficiently-large scope
# ...
def do_interesting_task():
     with module_lock.acquire():
         interesting_task()

"Abandon all hope, ye who enter here." “放弃所有希望,你们进入这里的人。”

Mutexes and semaphores are powerful tools, but used unwisely they will yield deadlocks and occasionally eat your lunch. 互斥体和信号量是强大的工具,但如果使用不当,则会产生僵局,并偶尔吃午餐。

Meanwhile i've implemented such solution, works pretty good. 同时,我已经实现了这样的解决方案,效果很好。 But, i am not pretty sure, tha max_retries=None states that there are will be unlimited number of retries. 但是,我不太确定,tha max_retries =没有状态说明重试次数不受限制。 This solution works on redis, but can work on any other engine that supports atomicaly operation of increment. 该解决方案适用于redis,但可以用于支持增量原子操作的任何其他引擎。

@task(max_retries=None,default_retry_delay=3)
def sleepTask():
    if r.incr('sleep_working')>1:
        r.incr('sleep_working',-1)
        sleepTask.retry()
    else:
        try:
            r.expire('sleep_working',3600)
            sleep(30)
        finally:
            r.incr('sleep_working',-1)
        return True

The key here, is that incr is atomically, so it will never happen, that two clients receive counter==1. 这里的关键是incr是原子的,因此永远不会发生,两个客户端收到counter == 1。

Also expire is very important, anything can happen, and we will get our counter >1 forever, so expire makes sure, that no matter what, after specific time counter will be dropped. 到期非常重要,任何事情都可能发生,并且我们将永远使计数器> 1,因此到期确保了在特定时间计数器被删除后无论如何。 This value can be adjusted to the needs. 该值可以根据需要进行调整。 Mine is big files uploads, so 3600 sounds OK. 我的是大文件上传,所以3600听起来还可以。

I think that this is good starting point, to make custom Task object, that will do all of this automatically, by recieving redis_key and expire_time values. 我认为这是制作自定义Task对象的良好起点,它将通过接收redis_key和expire_time值自动完成所有这些任务。 I will update this post if I'll do such a Task. 如果我要做这样的任务,我将更新这篇文章。

As a bonus, this solution is also can be easily adjusted to 2/3/any other number of parallel limit, by changing >1 to >anynumber 另外,通过将> 1更改为> anynumber,也可以轻松地将此解决方案调整为2/3 /任何其他并行限制数

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

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