聊聊通过celery_one避免Celery定时任务重复执行的问题

 更新时间:2021年10月31日 10:44:36   作者:吾星喵  
Celery Once 也是利用 Redis 加锁来实现, Celery Once 在 Task 类基础上实现了 QueueOnce 类,该类提供了任务去重的功能,今天通过本文给大家介绍通过celery_one避免Celery定时任务重复执行的问题,感兴趣的朋友一起看看吧

在使用Celery统计每日访问数量的时候,发现一个任务会同时执行两次,发现同一时间内(1s内)竟然同时发送了两次任务,也就是同时产生了两个worker,造成统计两次,一直找不到原因。

参考:https://www.jb51.net/article/226849.htm

有人使用 Redis 实现了分布式锁,然后也有人使用了 Celery Once。

Celery Once 也是利用 Redis 加锁来实现, Celery Once 在 Task 类基础上实现了 QueueOnce 类,该类提供了任务去重的功能,所以在使用时,我们自己实现的方法需要将 QueueOnce 设置为 base

@task(base=QueueOnce, once={'graceful': True})

后面的 once 参数表示,在遇到重复方法时的处理方式,默认 graceful 为 False,那样 Celery 会抛出 AlreadyQueued 异常,手动设置为 True,则静默处理。

另外如果要手动设置任务的 key,可以指定 keys 参数

@celery.task(base=QueueOnce, once={'keys': ['a']})
def slow_add(a, b):
    sleep(30)
    return a + b

解决步骤

Celery One允许你将Celery任务排队,防止多次执行

安装

pip install -U celery_once

要求,需要Celery4.0,老版本可能运行,但不是官方支持的。

使用celery_once,tasks需要继承一个名为QueueOnce的抽象base tasks

Once安装完成后,需要配置一些关于ONCE的选项在Celery配置中

from celery import Celery
from celery_once import QueueOnce
from time import sleep

celery = Celery('tasks', broker='amqp://guest@localhost//')

# 一般之前的配置没有这个,需要添加上
celery.conf.ONCE = {
  'backend': 'celery_once.backends.Redis',
  'settings': {
    'url': 'redis://localhost:6379/0',
    'default_timeout': 60 * 60
  }
}

# 在原本没有参数的里面加上base
@celery.task(base=QueueOnce)
def slow_task():
    sleep(30)
    return "Done!"

要确定配置,需要取决于使用哪个backend进行锁定,查看Backends

在后端,这将覆盖apply_async和delay。它不影响直接调用任务。

在运行任务时,celery_once检查是否没有锁定(针对Redis键)。否则,任务将正常运行。一旦任务完成(或由于异常而结束),锁将被清除。如果在任务完成之前尝试再次运行该任务,将会引发AlreadyQueued异常。

example.delay(10)
example.delay(10)
Traceback (most recent call last):
    ..
AlreadyQueued()
result = example.apply_async(args=(10))
result = example.apply_async(args=(10))
Traceback (most recent call last):
    ..
AlreadyQueued()

graceful:如果在任务的选项中设置了once={'graceful': True},或者在运行时设置了apply_async,则任务可以返回None,而不是引发AlreadyQueued异常。

from celery_once import AlreadyQueued
# Either catch the exception,
try:
    example.delay(10)
except AlreadyQueued:
    pass
# Or, handle it gracefully at run time.
result = example.apply(args=(10), once={'graceful': True})
# or by default.
@celery.task(base=QueueOnce, once={'graceful': True})
def slow_task():
    sleep(30)
    return "Done!"

其他功能请访问:https://pypi.org/project/celery_once/

到此这篇关于通过celery_one避免Celery定时任务重复执行的文章就介绍到这了,更多相关Celery定时任务重复执行内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python实现的大数据分析操作系统日志功能示例

    Python实现的大数据分析操作系统日志功能示例

    这篇文章主要介绍了Python实现的大数据分析操作系统日志功能,涉及Python大文件切分、读取、多线程操作等相关使用技巧,需要的朋友可以参考下
    2019-02-02
  • django框架使用方法详解

    django框架使用方法详解

    这篇文章主要介绍了django框架使用方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • Python常见报错解决方案总结(新手拯救指南)

    Python常见报错解决方案总结(新手拯救指南)

    我们再使用python难免会出现各种各样的报错,下面这篇文章主要给大家介绍了关于Python常见报错解决方案的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-05-05
  • python中什么是面向对象

    python中什么是面向对象

    在本篇文章里小编给大家分享了关于python面向对象的相关基础知识点,有兴趣的朋友们跟着学习下。
    2020-06-06
  • python 数据挖掘算法的过程详解

    python 数据挖掘算法的过程详解

    这篇文章主要介绍了python 数据挖掘算法,首先给大家介绍了数据挖掘的过程,基于sklearn主要的算法模型讲解,给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-02-02
  • Pandas读取csv时如何设置列名

    Pandas读取csv时如何设置列名

    这篇文章主要介绍了Pandas读取csv时如何设置列名,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • python使用tkinter实现屏幕中间倒计时

    python使用tkinter实现屏幕中间倒计时

    这篇文章主要为大家详细介绍了python使用tkinter实现屏幕中间倒计时,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-03-03
  • Python处理Excel表中单元格带有换行的数据问题

    Python处理Excel表中单元格带有换行的数据问题

    这篇文章主要介绍了Python处理Excel表中单元格带有换行的数据问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • 详解使用python crontab设置linux定时任务

    详解使用python crontab设置linux定时任务

    本篇文章主要介绍了使用python crontab设置linux定时任务,具有一定的参考价值,有需要的可以了解一下。
    2016-12-12
  • Python  中的pass语句语法详析

    Python  中的pass语句语法详析

    这篇文章主要介绍了Python 中的pass语句语法详析,pass是一种空操作(null operation),解释器执行到它的时候,除了检查语法是否合法,什么也不做就直接跳过
    2022-07-07

最新评论