概述
首先,我们要了解什么是Celery的Prefetch和Acknowledged。
顾名思义,Prefetch指的是一个Celery Worker节点,能够提前获取一些还还未被其他节点执行的任务,这样可以提高Worker节点的运行效率。
而Acknowledged则是一个任务执行完后,只有确认返回发送了Acknowledged确认信息后,该任务才算完成。
Prefetch Limit
在这里,Celery给我们提供了一个节点级别的变量,worker_prefetch_multiplier
,用以控制一个工作节点所能预取的任务倍数。这里倍数的意思是:该节点可同时执行的任务数量的N
倍(默认设置是4
倍)。即,一个并行100
个任务的节点,它默认能够预取的任务数量是400
。
在这里,我们可以根据我们的任务性质,对其进行一些改动。
假如一个节点运行的任务以长时间任务为主,那么该节点可以设置worker_prefetch_multiplier
为1
,即仅预取1
倍的未运行任务。
若是一个节点以短时间任务为主,那么该节点可以增大worker_prefetch_multiplier
的值(如64
),这样能够提高节点的效率。
而在这里,很多人可能会疑惑,假如一个100
并发的节点,worker_prefetch_multiplier=4
,那么该节点最大能够保留多少正在执行与未执行的任务呢?
这里就涉及到Acknowledged
相关的知识了。
Acknowledged
Acknowledged机制是设计用来确定一个任务已经被执行/已完成的。
Celery默认的ACK行为是,当一个任务被执行后,立刻发送Acknowledged信息,标记该任务已被执行。
比如一个任务被节点执行后,节点发送Acknowledged信号标记该任务已被执行。结果执行过程中该节点出现由断电、运行中被结束等异常行为,那么该任务则不会被重新分发到其他节点,因为该任务已经被标记为Acknowledged了。
以上是Celery的默认Acknowledged机制,而我们有时候需要一个任务确实被一个节点执行完成后才发送Acknowledged消息,这就需要提到一个配置task_acks_late
。
当我们设置一个节点为task_acks_late=True
之后,那么这个节点上正在执行的任务若是遇到断电,运行中被结束等情况,这些任务会被重新分发到其他节点进行重试。
注意:要求被重试的任务是幂等的,即多次运行不会改变结果
同时,Celery还提供了一个Task级别的acks_late
设置,可以单独控制某一个任务是否是采用Acknowledged Late
模式的。
Prefetch与Acknowledged
回到上面的问题,当一个节点的Acknowledged是Celery默认模式(提前确认)时,一个节点的任务组成是这样样子的:
100个正在执行中的任务(已确认) + 400个预取任务(未确认)
而若我们将节点的Acknowledged设置为Late Acknowledged模式,那么一个节点的任务组成会变为:
100个正在执行中的任务(未确认) + 300个预取任务(未确认)
也就是说,假如我们需要一个节点仅保留它正在运行的任务,而不需要任何预取的时候,我们需要设置该节点为Late Acknowledged模式(task_acks_late=True
),并把预取倍率调为1
(worker_prefetch_multiplier=1
)
你好按照这个设置 celery 4.4 + redis 版本,队列中的任务会被一次性全部拿完,请问可以加个好友请教一下吗?