celery-redbeat方案(动态定时任务、异步任务)

2024-06-11 17:12

本文主要是介绍celery-redbeat方案(动态定时任务、异步任务),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 为什么选择 RedBeat?
    • 方案
    • 坑事项记录

记一次工作上的问题

问题:项目上当前定时任务框架和服务端耦合,容易出现加载定时任务时间很长,影响后端服务启动,容易改动引发定时任务的问题。且能方便的动态的增加或删除定时任务而无需重启服务。
需求:将定时任务框架解耦,可以独立部署启动,不影响原来服务的功能,不会出现重复执行的定时任务和丢失定时任务
RedBeat是一个 Celery Beat 调度程序 ,它将计划任务和运行时元数据存储在Redis中。

为什么选择 RedBeat?

官方文档:https://redbeat.readthedocs.io/en/latest/intro.html
git仓库:https://github.com/sibson/redbeat

  1. 动态实时任务创建和修改,无需长时间停机
  2. 使用 Redis 绑定从任何语言外部管理任务
  3. 共享数据存储;Beat 不依赖于单个驱动器或机器
  4. 即使任务数量很多也能快速启动
  5. 防止意外运行多个 Beat 服务器
    用Celery-redbeat重构当前定时任务逻辑: Celery-redbeat是基于redis作为celery的中间件(broker)时的一个任务调度器(scheduler),有效提高调度器(scheduler)健壮性。

它最大的变化就是,它将调度器从原来Celery进程中的定时任务调度器(默认作为守护进程),改存在了Redis上。
因此,当任务创建或者发生变化的时候,调度器不再需要暂停和重载。利用Redis数据库的特性,我们只需要更新Redis中的键名,调度器就会随之发生改变。

方案

  1. 另起一个celery服务,不再跟随主服务启动
  2. 有一张数据库表用来针对动态定时任务做持久化存储以及做增删改查状态管理等。celery beat启动时会自动读取这张表的数据,将定时任务加载到redis中(每次会先清空再加载)
  3. 初始化完成后的redis数据, celery beat会根据redis里的scedule数据,如果满足执行条件,会将其推送到broker中,等待worker来消费
  4. 定时任务执行原理和之前可以保持一致,但不需要再往celery队列里插任务了,相当于直接执行celery队列中已有的任务,之前的锁逻辑还可以直接沿用
  5. 当用户对定时任务有任何更删改操作时,可以通过封装好的方法,先更新数据库中的值,然后直接更新redis中的值,从而同步更新队列中的定时任务,无需重启服务(此处需要保障数据库和redis的数据一致性,最后能有兜底or事务机制,要么都成功要么都失败)

坑事项记录

背景:发现线上服务会偶尔出现定时任务全部失效的情况,或者定时任务多次执行的情况
环境:k8s多pod部署服务来增加服务健壮性
分析线上日志,就是在某一个时间点突然报错:
LockNotOwnedError异常,表示无法释放或延长一个已经不再拥有的锁
所以一开始我们怀疑是redbeat存在bug,分析源码:
1、redbeat在启动时会触发 @beat_init.connect 装饰的 acquire_distributed_beat_lock 函数。使用 redis_client.lock() 方法创建一个分布式锁对象,通过 lock.acquire() 方法获取锁,此处会进行阻塞,直到成功获取到锁为止。最后,将获取到的锁对象赋值给调度器的 lock 属性。代码中生成的 time_task_:lock 锁用于在 Beat 启动时获取分布式锁,以实现在多个 Beat 进程或服务器之间协调任务调度的目的。这个锁对于 Beat 工作的用途是确保在分布式环境下只有一个 Beat 进程或服务器在执行任务调度。当多个 Beat 进程或服务器同时运行时,通过获取这个锁,只有获取到锁的进程或服务器可以执行任务调度,其他进程或服务器会被阻塞等待锁的释放。同时如果这个锁存在会给锁续期。(为了避免主进程 Readbeat 在执行任务时出现故障或长时间没有释放锁(例如进程崩溃、网络中断等情况),所以可能会有多个beat进程,虽然正常情况下永远只会有一个在工作。我们平台目前就只有一个beat服务)
2、然后Beat 服务会进入一个无限循环的进程,它会以一定的时间间隔进行轮询,检查是否需要执行任务。并且对time_task_:lock 锁进行续期。只有在进程终止时会释放

然后我们怀疑是,在某次续期时,这个锁会莫名其妙突然的消失,所以导致了报错问题
根据官方文档分析。time_task_:lock 锁仅仅是使用分布式锁来防止多个实例同时运行。我们当前仅设置一个实例服务,可以直接设置redbeat_lock_key = None关闭该功能。

本以为解决了问题,结果过了几天问题又再次出现,最后在偶然的灵机一动下发现
我们使用的k8s多pod服务,每个pod服务中的项目代码都是同一套一样的(不管是server还是celery还是beat),发现如果某个pod重启了,会将前面方案中的第二点中的预加载init函数(为了重置所有定时任务,防止异常数据残留)执行一次,就是会清空redis关于redbeat的数据然后重新加载数据,这就导致了所有数据和锁消失了~~

这篇关于celery-redbeat方案(动态定时任务、异步任务)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1051786

相关文章

springboot使用Scheduling实现动态增删启停定时任务教程

《springboot使用Scheduling实现动态增删启停定时任务教程》:本文主要介绍springboot使用Scheduling实现动态增删启停定时任务教程,具有很好的参考价值,希望对大家有... 目录1、配置定时任务需要的线程池2、创建ScheduledFuture的包装类3、注册定时任务,增加、删

SpringBoot基于配置实现短信服务策略的动态切换

《SpringBoot基于配置实现短信服务策略的动态切换》这篇文章主要为大家详细介绍了SpringBoot在接入多个短信服务商(如阿里云、腾讯云、华为云)后,如何根据配置或环境切换使用不同的服务商,需... 目录目标功能示例配置(application.yml)配置类绑定短信发送策略接口示例:阿里云 & 腾

Java Response返回值的最佳处理方案

《JavaResponse返回值的最佳处理方案》在开发Web应用程序时,我们经常需要通过HTTP请求从服务器获取响应数据,这些数据可以是JSON、XML、甚至是文件,本篇文章将详细解析Java中处理... 目录摘要概述核心问题:关键技术点:源码解析示例 1:使用HttpURLConnection获取Resp

Java实现优雅日期处理的方案详解

《Java实现优雅日期处理的方案详解》在我们的日常工作中,需要经常处理各种格式,各种类似的的日期或者时间,下面我们就来看看如何使用java处理这样的日期问题吧,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言一、日期的坑1.1 日期格式化陷阱1.2 时区转换二、优雅方案的进阶之路2.1 线程安全重构2

Redis消息队列实现异步秒杀功能

《Redis消息队列实现异步秒杀功能》在高并发场景下,为了提高秒杀业务的性能,可将部分工作交给Redis处理,并通过异步方式执行,Redis提供了多种数据结构来实现消息队列,总结三种,本文详细介绍Re... 目录1 Redis消息队列1.1 List 结构1.2 Pub/Sub 模式1.3 Stream 结

Spring Boot 集成 Quartz并使用Cron 表达式实现定时任务

《SpringBoot集成Quartz并使用Cron表达式实现定时任务》本篇文章介绍了如何在SpringBoot中集成Quartz进行定时任务调度,并通过Cron表达式控制任务... 目录前言1. 添加 Quartz 依赖2. 创建 Quartz 任务3. 配置 Quartz 任务调度4. 启动 Sprin

Linux之计划任务和调度命令at/cron详解

《Linux之计划任务和调度命令at/cron详解》:本文主要介绍Linux之计划任务和调度命令at/cron的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux计划任务和调度命令at/cron一、计划任务二、命令{at}介绍三、命令语法及功能 :at

使用Python实现一个优雅的异步定时器

《使用Python实现一个优雅的异步定时器》在Python中实现定时器功能是一个常见需求,尤其是在需要周期性执行任务的场景下,本文给大家介绍了基于asyncio和threading模块,可扩展的异步定... 目录需求背景代码1. 单例事件循环的实现2. 事件循环的运行与关闭3. 定时器核心逻辑4. 启动与停

C#中async await异步关键字用法和异步的底层原理全解析

《C#中asyncawait异步关键字用法和异步的底层原理全解析》:本文主要介绍C#中asyncawait异步关键字用法和异步的底层原理全解析,本文给大家介绍的非常详细,对大家的学习或工作具有一... 目录C#异步编程一、异步编程基础二、异步方法的工作原理三、代码示例四、编译后的底层实现五、总结C#异步编程

python logging模块详解及其日志定时清理方式

《pythonlogging模块详解及其日志定时清理方式》:本文主要介绍pythonlogging模块详解及其日志定时清理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录python logging模块及日志定时清理1.创建logger对象2.logging.basicCo