架构(十一)从0到1实现动态定时任务
一、引言
作者的平台项目最近需要实现一个功能,用户可选择这个任务什么时候执行,执行频率是什么?
这其实就是一个定时任务,只不过需要动态的,让用户自由选择。
二、原生实现
要实现这样的功能,可以直接依赖现有的中间件,比如作者就是使用qConfig+qSchedule实现的。但是在这之前,作者是想要原生的去实现,毕竟要调研很麻烦,另外各位读者使用框架不一定支持。
那么我们看看原生的需要怎么实现。首先需要定一下方案,一般的定时任务要么通过消息(mq、netty、http等)通知,要么直接客户端起一个线程不断轮训,随时通知需要执行的任务代码
既然做原生的不依赖任何外部,那就本地起个定时线程不断跑,看哪些任务需要跑了,把他们丢进线程池
1、首先用户可选的话,就要让用户可以填一个cron表达式,或者直接在配置文件里面加好各种选项,比如:1分钟一次、30分钟一次、一小时一次等等,展示给用户的是文字,配置文件里面文字是描述,实际上的key是cron表达式。
SCHEDULE_LIST=[{"code": "0 */15 * ? * *", "name": "每15分钟运行一次"},
{"code": "0 0 * ? * *", "name": "每小时运行一次"},
{"code": "0 0 0 ? * *", "name": "每天运行一次"},
{"code": "FALSE", "name": "不执行"}]
2、在任务表里面要有个字段,放这个cron表达式
3、启动一个定时任务
@Scheduled(fixedRate = 1000*60) public void schedule() {handle();}
4、在定时任务里面把需要执行的数据扔到线程池
这里需要注意,由于定时轮训的通知机制和处理速度,不管原生还是使用中间件,都是有可能导致一定误差的,这个误差可以做成配置,作者认为几万的数据量的话也就是前后三秒左右
所以这里还需要没有五秒以内的定时任务,正常也没有哪些任务需要那么高的频率,一般都是一分钟以上的
public void handle() {
// 查询所有任务数据
List<Task> tasks = queryTask();
for (Task task : tasks) {doHandle(task);
}
}public void doHandle(Task task) {String cronExpression = task.getCron();Date now = new Date();CronExpression cron = new CronExpression(cronExpression);Date nextExecutionTime = cron.getNextValidTimeAfter(now);Date previousExecutionTime = cron.getPreviousValidTimeBefore(now);Date fiveSecondsBefore = new Date(now.getTime() - 5000);Date fiveSecondsAfter = new Date(now.getTime() + 5000);if ((nextExecutionTime.after(fiveSecondsBefore) && nextExecutionTime.before(fiveSecondsAfter))|| (previousExecutionTime.after(fiveSecondsBefore) && previousExecutionTime.before(fiveSecondsAfter))) {doExecute(task);}
}
三、优化
这里也能看到上面还是有一些优化空间的,比如以下几点:
1、查询耗时
查数据库的任务再去判断是否执行,数量量不大还好,多了的话真是又占内存,要耗时间,可以做一层缓存,把任务的id和cron表达式存储在本地,然后由快速的做内存遍历,投入到线程池之后再去查明细
就是io会高一点,但是同一个时间执行的任务本身就不会很多,除非做的是集团那种规模的,定时任务几十万那种,基本没必要,因为能用中间件,各位读者自己就用了,直接看第四章好了
2、批量执行
判断这个任务的cron是否可以执行是非常快的,所以没必要一个个判断再投入线程池,完全可以20个一批投进去,根据执行情况调整批次数量
List<List<Task>> batches = Lists.partition(tasks, batchSize);for (List<Task> batch : batches) {doHandle(batch);
}
四、依赖框架
作者使用的是QSchedule和QConfig的组合,主要是把定时任务给放在配置中心之后,需要qschedule去拉取,然后生成对应的定时任务。
QSchedule是集团内部使用的定时任务,和集团的配置中心紧密结合,用起来很方便,配置好之后代码加个注解就行了,JobList.t就是配置中心文件的名字
@QScheduleList("jobList.t")public void scheduleHandle(Parameter parameter) {handleSchedule(parameter.getJobName());}
不过QSchedule没开源,QConfig倒是开源了https://github.com/qunarcorp/qconfig
实现原理也不复杂,就是注解的切面拉取配置文件,再发给服务端生成定时任务,服务端每次通知客户端都会把名称、拓展信息相关的都带过来,根据名称再去数据库拉取要执行的任务。
减少了判断和多次的数据库io,而且定时任务有管理机制,可用性高。
五、总结
最小成本的快速实现需要根据自身环境,有成型的框架就直接用,没有自己写一个也不复杂。
相关文章:
架构(十一)从0到1实现动态定时任务
一、引言 作者的平台项目最近需要实现一个功能,用户可选择这个任务什么时候执行,执行频率是什么? 这其实就是一个定时任务,只不过需要动态的,让用户自由选择。 二、原生实现 要实现这样的功能,可以直接依赖…...
Mybatis 批量插入数据 SQL
温故而知新,这里记录一下 案例1 批量插入时,xxxMapper.java 中方法的参数都必须是 List ,泛型可以是 bean ,也可以是 Map 。配合使用 mybatis 的 foreach 即可。示例如下: public Integer batchInsertDemo(List<D…...
【学员分享-考试心得】国产数据库潜力无限,云贝教育OBCP认证培训帮您解难题
近年来,随着国产化转型的推进,国外数据库的岗位需求逐渐减少,让许多IT从业者倍感压力。在这种情况下,了解国产数据库成为了求职市场上的竞争力。云贝老师们将聚焦于OceanBase、PostgreSQL、TDSQL等IT培训,探讨其对国产…...
【Mysql】事务的隔离级别与 MVCC
事务隔离级别 我们知道 MySQL 是一个 C/S 架构的服务,对于同一个服务器来说,可以有多个客户端与之连接,每个客户端与服务器连接上之后,就是一个会话( Session )。每个客户端都可以在自己的会话中向服务器发…...
MongoDB从入门到实战之MongoDB快速入门
前言 上一章节主要概述了MongoDB的优劣势、应用场景和发展史。这一章节将快速的概述一下MongoDB的基本概念,带领大家快速入门MongoDB这个文档型的NoSQL数据库。 MongoDB从入门到实战的相关教程 MongoDB从入门到实战之MongoDB简介👉 MongoDB从入门到实战…...
Linux服务详解
如有错误或有补充,以及任何改进的意见,请在评论区留下您的高见,同时文中给出大部分命令的示例,即是您暂时无法在Linux中查看,您也可以知道各种操作的功能以及输出 如果觉得本文写的不错,不妨点个赞&#x…...
闲聊电脑(4)硬盘分区
夜深人静,万籁俱寂,老郭趴在电脑桌上打盹,桌子上的小黄鸭和桌子旁的冰箱又开始窃窃私语…… 小黄鸭:冰箱大哥,上次你说的那个“分区”和“格式化”是什么意思? 冰箱:分区么,就是分…...
光耦合器的结构与原理解析
光耦合器是一种重要的电光转换器件,广泛应用于电子设备、通信系统以及工业控制等领域。本文将深入分析光耦合器的结构与原理,旨在为读者提供清晰而全面的了解。 光耦合器作为一种关键的电子元件,扮演着信号隔离和传输的重要角色。它的设计结构…...
代码随想录day17--二叉树的应用5
LeetCode654.最大二叉树 题目描述: 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点,其值为 nums 中的最大值。递归地在最大值 左边 的 子数组前缀上 构建左子树。递归地在最大值 右边 的 子数组后…...
跟着cherno手搓游戏引擎【19】抽象纹理
引入: 导入stb_image: GitHub - nothings/stb: stb single-file public domain libraries for C/C 下载复制stb_image.h的内容(8000多行),然后粘到如图位置 stb_image.cpp: #include"ytpch.h" #define STB_IMAGE_IM…...
CentOS 7中搭建NFS文件共享服务器的完整步骤
CentOS 7中搭建NFS文件共享服务器的完整步骤 要求:实现镜像文件共享,并基于挂载的共享目录配置yum源。 系统环境: 服务器:172.20.26.167-CentOS7.6 客户端:172.20.26.198-CentOS7.6 1、在服务器和客户端上&#x…...
【华为OD机试】 最小矩阵宽度【2024 C卷|100分】
【华为OD机试】-真题 !!点这里!! 【华为OD机试】真题考点分类 !!点这里 !! 题目描述 给定一个矩阵,包含 N * M 个整数,和一个包含 K 个整数的数组。 现在要求在这个矩阵中找一个宽度最小的子矩阵,要求子矩阵包含数组中所有的整数。 输入描述 第一行输入两个正整数 N,M,…...
Ingress
文章目录 环境准备什么是 Ingress认识 Ingress 资源Ingress 控制器(controller)Ingress 规则pathType 路径类型多重匹配Ingress 类TLS生成证书创建密钥 环境准备 下面的 yaml 文件内容,是使用 sts 创建两个 web 服务,并配置对应的 servcie。web 服务的首…...
MySQL数据库安全加固方案
数据库版本:MySQL8.0.22 按照本安全加固方案进行的数据库加固,一般安全扫描工具扫描出来几乎无漏洞。 1.2 帐号安全 1.2.1 避免不同用户间共享帐号 参考以下步骤。 A. 创建用户。 mysql>CREATE USER ‘用户名’@‘用户 host’ IDENTIFIED BY ‘密码’; 执行以上命令可以…...
实践:读取html文本提取相应内容按照格式导出到excel中
最近在做一个需求,需要将html文本中的内容提取出来,然后导出到excel里面,实现交代情景,html文本中存在许多标签,且很乱,因此需要之间将标签里面的文本提取出来,再进行处理。 ............String…...
oracle 修改表结构语句
oracle 修改表结构语句 Oracle中可以使用ALTER TABLE语句来修改表的结构。 添加列: ALTER TABLE table_name ADD column_name data_type; 示例:ALTER TABLE employees ADD email VARCHAR2(50); 删除列: ALTER TABLE table_name DROP COL…...
LabVIEW核能设施监测
LabVIEW核能设施监测 在核能领域,确保设施运行的安全性和效率至关重要。LabVIEW通过与硬件的紧密集成,为高温气冷堆燃料装卸计数系统以及脉冲堆辐射剂量监测与数据管理系统提供了解决方案。这些系统不仅提高了监测和管理的精确度,也保证了核…...
使用Process.Start()打开文件夹时出现访问被拒绝异常
默认的打开形式 Process.Start(folderPath); 解决方案 System.Diagnostics.Process.Start(Environment.GetEnvironmentVariable("WINDIR") "\explorer.exe", folderPath); 参考文献 c# - 使用 Process.Start() 打开文件夹时访问被拒绝异常 - IT工具网…...
spdk技术原理简介和实践经验
一、导读 与机械硬盘相比,NVMe-ssd在性能、功耗和密度上都有巨大的优势,并且随着固态存储介质的高速发展,其价格也在大幅下降,这些优势使得NVMe-ssd在分布式存储中使用越来越广泛。由于NVMe-ssd的性能比传统磁盘介质高出很多&…...
【开源】基于JAVA+Vue+SpringBoot的用户画像活动推荐系统
目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 兴趣标签模块2.3 活动档案模块2.4 活动报名模块2.5 活动留言模块 三、系统设计3.1 用例设计3.2 业务流程设计3.3 数据流程设计3.4 E-R图设计 四、系统展示五、核心代码5.1 查询兴趣标签5.2 查询活动推荐…...
记录模式 vs Lombok vs Record类,全维度性能与可维护性对比测试(含JMH压测数据)
第一章:Java记录模式的核心概念与演进背景Java记录模式(Record Patterns)是JDK 21中正式引入的预览特性(JEP 440),并在JDK 22中进一步增强(JEP 441),旨在为结构化数据解构…...
3D元器件库在PCB设计中的关键作用与应用
1. 为什么你需要一套完整的3D元器件库作为一名电子工程师,我深知在PCB设计过程中,3D元器件库的重要性。传统的2D设计虽然能满足基本需求,但在实际生产装配时往往会遇到各种意想不到的机械干涉问题。记得我刚开始做硬件设计时,就曾…...
个人知识库构建:OpenClaw+千问3.5-27B自动整理碎片化笔记
个人知识库构建:OpenClaw千问3.5-27B自动整理碎片化笔记 1. 为什么需要智能知识管理 作为一个常年被信息过载困扰的技术写作者,我的笔记系统曾经像一座杂乱无章的仓库。微信收藏夹里躺着2000未读文章,Obsidian里有500多个零散笔记ÿ…...
连续“罢工“后编码风格突变!释放多个Agent相关岗位,DeepSeek大招来了?
文章目录前言编码风格突变,像换了个脑回路疯狂招兵买马,一口气放出17个Agent岗位Vibe Coding是个啥?给大脑装上灵活的"手脚"DeepSeek到底在憋什么大招?写在最后前言 你有没有试过,正在跟AI聊得火热…...
2026最权威的十大降AI率神器实际效果
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 随着人工智能生成内容也就是 AIGC 被广泛应用,文本的机器化特征越发明显地呈现出…...
基于西门子PLC的空压机组储气风冷机组自动控制系统:“手动自动切换、多机控制及实时监测报警系统
基于西门子plc的空压机组储气风冷机组自动控制系统 可以实现手动自动切换 三组空压机分别自动控制,自动检测三路压力 风冷机运行实时检测 报警查寻,参数设置等上周刚把车间那套跑了快十年的空压机组控制系统给换了,用的是西门子S7-1200&#…...
管理员命令提示符 命令提示符 cmd
命令提示符区别...
数据仓库核心概念:事实表和维度表详解与实战应用
数据仓库核心概念:事实表和维度表详解与实战应用一、引言二、定义:什么是事实表?什么是维度表?2.1 事实表:定义2.2 维度表:定义三、结构流程图:事实表与维度表关联关系3.1 标准星型模型关联流程…...
新手入门福音:用快马AI生成你的第一个Python版游戏账号管理工具
作为一个刚接触Python编程的新手,最近想尝试开发一个简单的游戏账号管理工具。这个需求其实挺常见的,比如我平时玩多个游戏,账号密码经常记混,如果能有个小工具统一管理就方便多了。在朋友的推荐下,我尝试用InsCode(快…...
Qwen3-VL-30B部署避坑指南:从下载到运行一气呵成
Qwen3-VL-30B部署避坑指南:从下载到运行一气呵成 1. 为什么选择Qwen3-VL-30B Qwen3-VL-30B是目前通义千问系列中最强大的视觉-语言模型,它在多个方面实现了显著提升: 更优秀的文本理解和生成:能够处理复杂语义和长文本更深入的…...
