celery-redbeat方案(动态定时任务、异步任务)
文章目录
- 为什么选择 RedBeat?
- 方案
- 坑事项记录
记一次工作上的问题
问题:项目上当前定时任务框架和服务端耦合,容易出现加载定时任务时间很长,影响后端服务启动,容易改动引发定时任务的问题。且能方便的动态的增加或删除定时任务而无需重启服务。
需求:将定时任务框架解耦,可以独立部署启动,不影响原来服务的功能,不会出现重复执行的定时任务和丢失定时任务
RedBeat是一个 Celery Beat 调度程序 ,它将计划任务和运行时元数据存储在Redis中。
为什么选择 RedBeat?
官方文档:https://redbeat.readthedocs.io/en/latest/intro.html
git仓库:https://github.com/sibson/redbeat
- 动态实时任务创建和修改,无需长时间停机
- 使用 Redis 绑定从任何语言外部管理任务
- 共享数据存储;Beat 不依赖于单个驱动器或机器
- 即使任务数量很多也能快速启动
- 防止意外运行多个 Beat 服务器
用Celery-redbeat重构当前定时任务逻辑: Celery-redbeat是基于redis作为celery的中间件(broker)时的一个任务调度器(scheduler),有效提高调度器(scheduler)健壮性。
它最大的变化就是,它将调度器从原来Celery进程中的定时任务调度器(默认作为守护进程),改存在了Redis上。
因此,当任务创建或者发生变化的时候,调度器不再需要暂停和重载。利用Redis数据库的特性,我们只需要更新Redis中的键名,调度器就会随之发生改变。
方案
- 另起一个celery服务,不再跟随主服务启动
- 有一张数据库表用来针对动态定时任务做持久化存储以及做增删改查状态管理等。celery beat启动时会自动读取这张表的数据,将定时任务加载到redis中(每次会先清空再加载)
- 初始化完成后的redis数据, celery beat会根据redis里的scedule数据,如果满足执行条件,会将其推送到broker中,等待worker来消费
- 定时任务执行原理和之前可以保持一致,但不需要再往celery队列里插任务了,相当于直接执行celery队列中已有的任务,之前的锁逻辑还可以直接沿用
- 当用户对定时任务有任何更删改操作时,可以通过封装好的方法,先更新数据库中的值,然后直接更新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方案(动态定时任务、异步任务)
文章目录 为什么选择 RedBeat?方案坑事项记录 记一次工作上的问题 问题:项目上当前定时任务框架和服务端耦合,容易出现加载定时任务时间很长,影响后端服务启动,容易改动引发定时任务的问题。且能方便的动态的增加或删除…...

js解析成语法树以及还原
const {parse} require("babel/parser"); const traverse require("babel/traverse").default; const generator require("babel/generator").default;// 1.定义要处理的代码 const jscode function square(n) {return n * n; };// 2.使用ba…...
基于python可伸缩JSON格式列表实现
对于消息体为一个json格式列表,列表长度变化的代码设计,如下实现可供参考。 1、python语言实现(直接取值) #codingutf-8n 2 # 行项目数 productCode [11111,222222,333333] unit [H06,H07,H08] qty [6,7,8] items []for i in range(0, n):item …...
h5相机功能
h5相机功能 利用vant input file <template><div class"mb10"><divv-for"(item, index) in info.imgList":key"index"class"imgItem f32 mr20"click"preview(item, index)"><img :src"doFileUrl…...

IDEA | 安装通义灵码插件,开启智能编码旅程
安装步骤 从插件市场安装,点击导航-插件,打开应用市场,搜索通义灵码(TONGYI Lingma),找到通义灵码后点击安装。 https://tongyi.aliyun.com/lingma/download 使用方式 https://help.aliyun.com/documen…...
技术人员如何克服在使用行列视(RCV)过程中遇到的挑战?
技术人员在使用行列视(RCV)过程中可能会遇到多种挑战,以下是一些建议,帮助他们克服这些挑战: 1. 深入了解系统架构和功能: - 熟练掌握RCV的架构设计,包括数据中心层、计算服务层、函数层、人机…...

手把手教你安装 Vivado2019.2(附安装包)
一、Vivado 2019.2优点 Vivado 2019.2 作为 Xilinx 公司发布的一款设计套件版本,具有多个显著的优点,以下是对其优点的详细归纳: 集成度高:开发工具丰富并行综合功能灵活的许可证策略用户友好的界面强大的仿真和验证功能丰富的文…...

Sql-labs的第一关
前言 我们在使用Sql-libs靶场进行Sql注入实验的时候,前提要求我们对mysql数据库结构要有一个大概的了解,因为mysql5.0以上的版本都会自带一个名为information_schema的数据库,这个数据库下面会有columns和tables两个表。 tables这个表的table…...
10_1 Linunx Web服务管理
10_1 Linunx Web服务管理 文章目录 10_1 Linunx Web服务管理[toc]1. 环境准备2. Web服务2.1 Web服务简介 2.2 Web配置2.2.1 提供的默认配置2.2.2 Web服务的主配置文件2.2.3 /etc/httpd/conf/httpd.conf 文件反映出来的”访问控制信息“2.2.4 修改监听端口,访问2.2.5…...

苹果WWDC 2024:十三大亮点公布,一切都有关AI|TodayAI
在刚刚结束的苹果全球开发者大会(WWDC 2024)上,苹果公司展示了一系列令人瞩目的新功能,特别是在人工智能(AI)领域的重大进展。以下是本次大会的十三大亮点。 1. 苹果推出首个AI系统 苹果宣布推出其首个AI系统——Apple Intelligence,这一系统将强大的生成模型直接集成到…...
Nginx访问日志
Nginx日志是Nginx Web服务器产生的记录文件,主要用于跟踪和分析服务器的访问情况以及错误信息。Nginx日志主要分为两大类:访问日志 (access_log): 访问日志记录了每一次客户端对Nginx服务器的HTTP请求的详细信息,这对于统计分析、流量监控、用…...

Java使用Hutool工具类轻松生成验证码
一、效果展示 二、Hutool工具类实现验证码生成 2.1 引入依赖 <!--hutool工具包--> <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.15</version> </dependency2.2 简单实现方…...
leetcode 40. 组合总和 II
题目 给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次 。 注意:解集不能包含重复的组合。 原题链接:https://leetc…...

AMEYA360代理品牌:ROHM开发出世界超小CMOS运算放大器,适用于智能手机和小型物联网设备等应用
全球知名半导体制造商ROHM(总部位于日本京都市)开发出一款超小型封装的CMOS运算放大器“TLR377GYZ”,该产品非常适合在智能手机和小型物联网设备等应用中放大温度、压力、流量等的传感器检测信号。 智能手机和物联网终端越来越小型化,这就要求搭载的元器…...

第1章Hello world 4/5:对比Rust/Java/C++创建和运行Hello world全过程:运行第一个程序
讲动人的故事,写懂人的代码 1.7 对比Rust/Java/C++创建和运行Hello world全过程 有了会听懂人类的讲话,还能做记录的编程助理艾极思,他们三人的讨论内容,都可以变成一份详细的会议纪要啦。 接下来,我们一起看看艾极思是如何记录下赵可菲创建和运行Java程序Hello world,…...
golang优雅代码【lock实现】
golang优雅代码【lock实现】 1.局部锁1.1 具体实现方式 本文代码风格来源参考 database/sql 包 更加深刻理解go语言圣经中函数是一等公民 1.局部锁 database/sql源码中使用 withLock(dc, func(){...}) 方法实现局部锁,完美利用了 golang 的 defer 关键字对 入参dc…...
Dijkstra算法(迪杰斯特拉算法)
迪杰斯特拉算法通常用在图的最短路径问题上 而迷宫的最短路径可以用BFS来做,虽然BFS不能用于带权值的迷宫,但是可以对BFS稍微改进,只需要把判断是否走过的数组改为最短路径的数组,在判断是否可走时判断是否比最短的小即可 Dijks…...

用函数指针求a和b中的大者
指针变量也可以指向一个函数。一个函数在编译时被分配给一个入口地址。这个函数入口地址就称为函数的指针。可以用一个指针变量指向函数,然后通过该指针变量调用此函数。 先按一般方法编写程序: 可以用一个指针变量指向max函数,然后通过该指…...

鸿蒙轻内核M核源码分析系列六 任务及任务调度(2)任务模块
任务是操作系统一个重要的概念,是竞争系统资源的最小运行单元。任务可以使用或等待CPU、使用内存空间等系统资源,并独立于其它任务运行。鸿蒙轻内核的任务模块可以给用户提供多个任务,实现任务间的切换,帮助用户管理业务程序流程。…...

解决找不到MSVCR120.dll,无法执行代码
msvcr120.dll是Microsoft Visual C 2013 Redistributable Package的一部分,它提供了运行使用Microsoft Visual C 2013编译器编译的程序所需的运行时环境。这个DLL文件包含了在运行使用Visual C编译器(特别是2013版)编译的应用程序时所必需的一…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...