之前讲到利用celery异步处理一些耗时或者耗资源的任务,但是近来分析数据的时候发现一个奇怪的现象,即是某些数据重复了,自然想到是异步任务重复执行了。

查阅之后发现,到如果一个任务太耗时,任务完成时间超过了broker的时间(Redis默认为一小时)则任务会被再次分配到worker.

Visibility Timeout

The visibility timeout defines the number of seconds to wait for the worker to acknowledge the task before the message is redelivered to another worker. Be sure to see Caveats below.

This option is set via the broker_transport_options setting:

app.conf.broker_transport_options = {'visibility_timeout': 3600}  # 1 hour.

The default visibility timeout for Redis is 1 hour.

问题在于我的应用中的异步任务耗时绝不可能超过Redis默认的一小时,那么问题出在这个“Acknowledge”了,一开始我的理解是这个acknowledge是worker收到了broker发送的任务。但是通过查看workererr.log 发现:

[2019-03-01 14:20:30,695: INFO/MainProcess] Received task: task_async[4e0378e2-ff5d-4394-a842-ece2d1c8118a] ETA:[2019-03-01 15:44:03.692831+08:00]

[2019-03-01 15:23:58,477: INFO/MainProcess] Received task: task_async[4e0378e2-ff5d-4394-a842-ece2d1c8118a] ETA:[2019-03-01 15:44:03.692831+08:00]

[2019-03-01 15:44:04,620: INFO/ForkPoolWorker-2] Task task_async[4e0378e2-ff5d-4394-a842-ece2d1c8118a] succeeded in 0.003580662072636187s: None

[2019-03-01 15:44:04,621: INFO/ForkPoolWorker-1] Task task_async[4e0378e2-ff5d-4394-a842-ece2d1c8118a] succeeded in 0.004984764964319766s: None

1. 重复执行的任务被发送了多次 (时间间隔为1小时)

2. worker多次接收到同样的任务(同ID),并且几乎一样的ETA(预计执行时间)

3. 在ETA到达之后,这个任务会被多个子线程认领并执行,每次执行时间并不长

所以为什么14:20:30任务接收到之后15:23:58任务再次发送呢,问题在约“Acknowledge”(认领)并不是以“Received”为结束标志的,看celery对于acknowledge的解释:

acknowledged

Workers acknowledge messages to signify that a message has been handled. Failing to acknowledge a message will cause the message to be redelivered. Exactly when a transaction is considered a failure varies by transport. In AMQP the transaction fails when the connection/channel is closed (or lost), but in Redis/SQS the transaction times out after a configurable amount of time (the visibility_timeout).

所以说是以“Handled”来进行判定而非任务已被接收,所以会出现当我的定时任务在一小时后才执行的情况下,第一次发送的任务虽然接受了但是并未执行(Acknowledge),所以一小时后任务再次被发送。

解决这个问题的时候回看celery开篇教程中的一段:

Ideally task functions should be idempotent: meaning the function won’t cause unintended effects even if called multiple times with the same arguments. Since the worker cannot detect if your tasks are idempotent, the default behavior is to acknowledge the message in advance, just before it’s executed, so that a task invocation that already started is never executed again.

最佳实践中的任务应该是幂等的!

总结起来:

1. Task received的时候并不是acknowledge的时候,而task执行才是acknowledge (任务才会从broker队列中移除).

2. 我的任务都是定时任务(超过一小时),所以我设置visibility_time 超出我的定时,则重复执行不会再发生.

3. 如果任务很长或者跨度很长,如果对于只执行一次有严格要求,可以参考celery_once.

4. 还是要仔细阅读官方文档!!

Ref:

Scheduled tasks are being duplicated

https://github.com/cameronmaske/celery-once

http://docs.celeryproject.org/en/latest/getting-started/brokers/redis.html#visibility-timeout

https://github.com/celery/django-celery/issues/176

Celery异步任务重复执行(Redis as broker)的更多相关文章

  1. Celery异步处理

    1.Celery概述 1.1问题抛出 我们在做网站后端程序开发时,会碰到这样的需求:用户需要在我们的网站填写注册信息,我们发给用户一封注册激活邮件到用户邮箱,如果由于各种原因,这封邮件发送所需时间较长 ...

  2. celery异步任务框架

    目录 Celery 一.官方 二.Celery异步任务框架 Celery架构图 消息中间件 任务执行单元 任务结果存储 三.使用场景 四.Celery的安装配置 五.两种celery任务结构:提倡用包 ...

  3. django、celery异步发邮件

    django.celery异步发邮件 django自带的send_mail发邮件功能执行发邮件功能会因为网络的原因造成花费的时间过长,为了解决这个问题,可以用celery + redis代替 安装包: ...

  4. Django使用Celery异步任务队列

    1  Celery简介 Celery是异步任务队列,可以独立于主进程运行,在主进程退出后,也不影响队列中的任务执行. 任务执行异常退出,重新启动后,会继续执行队列中的其他任务,同时可以缓存停止期间接收 ...

  5. celery异步消息处理框架

    Celery 1.什么是Clelery Celery是一个简单.灵活且可靠的,处理大量消息的分布式系统 专注于实时处理的异步任务队列 同时也支持任务调度 Celery架构 Celery的架构由三部分组 ...

  6. Celery 异步任务

    Celery https://www.cnblogs.com/DragonFire/p/10356615.html 介绍: Celery 是芹菜 Celery 是基于Python实现的模块, 用于执行 ...

  7. Celery 异步任务 , 定时任务 , 周期任务 的芹菜

    1.什么是Celery?Celery 是芹菜Celery 是基于Python实现的模块, 用于执行异步定时周期任务的其结构的组成是由    1.用户任务 app    2.管道 broker 用于存储 ...

  8. celery异步认知

    celery是异步任务的框架 是由python实现的异步框架. 在使用celery我们经常分为三个部分, 第一部分就是我们所说的客户端, 就是发起异步任务的一方, 第二部分 任务队列 broker 第 ...

  9. Django商城项目笔记No.6用户部分-注册接口-短信验证码实现celery异步

    Django商城项目笔记No.4用户部分-注册接口-短信验证码实现celery异步 接上一篇,如何解决前后端请求跨域问题? 首先想一下,为什么图片验证码请求的也是后端的api.meiduo.site: ...

随机推荐

  1. split_brain

    脑裂 系统中两个或多个部分开始独立工作

  2. 【题解】Jury Compromise(链表+DP)

    [题解]Jury Compromise(链表+DP) 传送门 题目大意 给你\(n\le 200\)个元素,一个元素有两个特征值,\(c_i\)和\(d_i\),\(c,d \in [0,20]\), ...

  3. python数据分析之:数据清理,转换,合并,重塑(一)

    DataFrame合并: merge运算是将一个或多个键将行链接起来.来看下面的这个例子: In [5]: df1=DataFrame({'key':['b','b','a','c','a','a', ...

  4. [IR课程笔记]Hyperlink-Induced Topic Search(HITS)

    两个假设 1. 好的hub pages: 好的对某个主题的hub pages 链接许多好的这个主题的authoritative pages. 2. 好的authoritative pages: 好的对 ...

  5. uboot 2013.01 代码简析(1)开发板配置

    u-boot下载地址:ftp://ftp.denx.de/pub/u-boot/u-boot-2013.01.01.tar.bz2 下载之后对该文件进行解压. 我试着分析smdk2410_config ...

  6. PS图片透明处理方法

    // http://www.3lian.com/edu/2014/06-18/149890.html 今天想把图片背景做成透明效果,以前叫美工的妹纸帮忙做过,自己没留意学. 今天需要做这个东西,特别记 ...

  7. 4.7 希尔(shell)排序法

    4-7 ShellSort.c #include <stdio.h> #include "4-1 CreateData.c" //生成随机数的函数 #define AR ...

  8. 基于深度学习的目标检测算法:SSD——常见的目标检测算法

    from:https://blog.csdn.net/u013989576/article/details/73439202 问题引入: 目前,常见的目标检测算法,如Faster R-CNN,存在着速 ...

  9. 前端多媒体(1)——获取摄像头&麦克风

    捕获视频/音频 PPT地址 长久以来,音频/视频捕获都是网络开发中的"圣杯".多年来,我们总是依赖于浏览器插件(Flash 或 Silverlight)实现这一点. 依靠 WebR ...

  10. c# json 排版

    public static string PraseToJson(string json) { try { JsonSerializer s = new JsonSerializer(); JsonR ...