quartz集群增强版🎉
quartz集群增强版
这是除了mee_admin之外,投入时间精力最多的一次开源了,quartz集群增强版前前后后花费了我四月有余的时间精力开发而来,实属不易~
先简要的说下:quartz集群增强版由quartz的 2.3.2 版本改造,对原有功能进行了部分缩减, 同时也对现有的痛点做了大量的增强,这些增强包括但不限于如下:
1. 修改任务参数序列化及存储
将默认参数存储方式由blob大字段方式修改为定长字符串方式,保证后管修改即所得,同时内部使用 org.json 库对json字符串序列化及反序列化,使用起来更便捷
同时也将传参配置由原版的 K/V(对象序列化) 改为(Map)对象(eg:{"aa":1})或(Array)列表(eg:[11,true,{"bb":"her"}]) 的方式,使用时视json结构,可使用
context.getJobDataMap() 或 context.getJobDataList() 直接获取配置的json参数,更简单快捷;顺带一提:也可通过 context.getJobData() 拿出原始存储的json字符串
2. 分离了执行端及配置管理端
这是很大的改变,如果是执行端使用,只需添加依赖 quartz-core,如果是后管配置则只需要连接执行库(数据库)后使用依赖 quartz-client 来配置,管理集群或分布式的执行端也只需要
使用此来配置即可(前提是连接同一个库表), 这个改变在原版的quartz中是不可想象的,原版的quartz执行端与配置端耦合这种不太美妙的方式着实令人头疼与不解
3. 使用乐观锁
这同样也是重大的变化,原版采用lock表行级悲观锁,每次变更都要竞争同一个 STATE_ACCESS 或 TRIGGER_ACCESS ,同时每次执行加锁释放锁的过程还需配合线程本地变量(ThreadLocal)来使用,看起来有些没必要而十分的笨重的同时系统开销也比较大
quartz集权增强版不再使用 lock 表悲观锁,而是使用 UPDATE ... WHERE ... 方式(乐观锁),虽同样存在一定的查询开销,但写db的开销大大地减少了。
同时,需要说明的是使用乐观锁似乎还是有些不够,可目前并没有测试出bug(也许是测试不够严格吧...),如果有好的idea 恳请告知哈~
4. 简化了表结构以及数量
由于底层去掉了trigger及 memory 单机等相关逻辑,故表结构及逻辑也做了相应的简化,由原版的11张表简化为4张表,对,没错~,就是四张表,四张表就ok
表的整体设计主要参考了 mee_timed 这个同样由我写的定时任务组件,目前 这四张表为:
- QRTZ_APP 应用表: 用于定义应用,尤其是对于管理分布式应用十分有用,同时执行端启动时会自动新增或更新 无需手动添加数据
- QRTZ_NODE 节点表:用于定义应用下的执行节点,这是对于集群应用十分有用,比如你需要增量发布时可通过启停节点以增量更新执行端,同样表数据也是自动新增或更新,十分方便
- QRTZ_JOB 任务配置表: 配置任务的基本信息(不包含执行事件项,一个job任务对应多个执行配置/时间项),此表主要定义任务的执行类以及关联的应用信息
- QRTZ_EXECUTE 执行配置表: 执行配置必须关联一个任务配置(job),执行配置也有独立的状态可供后管操作
5. 去掉了group(组)
这是个不太有用的概念,组在绝大数使用quartz的开发者来说十分困惑(至少我经历的项目大多是这样),group的使用如有不慎会跟预期存在差异,因为有 group 这一层的存在,配置任务也略显有些臃肿。。。
去掉了 group 的同时也去掉了 TriggerKey 及相关的逻辑,这样就基本淡化了 group 的概念及使用,好处不言而喻。
6. 兼容原版quartz的配置项及集成方式
对于常用的springboot框架,集成方式与原版的quartz的方式并无太大区别,主要区别是只需导入 quartz集群增强版 提供的表即可,starter(autoconfigure)中无用的配置类及方法都做了兼容
还有就是原有的context稍有变化,主要是去掉了TriggerKey以及增强json传值带来的变更,基本使用就无任何区别~
7. 缺火/熄火(MisfireHandler)及集群(ClusterManager)处理
首先,这个变更也蛮大的。。。
先说下缺火是什么,由于quartz内所有执行时间点都是通过对应类型的 Trigger(eg: CronTriggerImpl、 SimpleTriggerImpl) 计算出来的,一旦出现不可预知的错误以及停机,则执行时间点无法向前推进,如果补偿或恢复机制,则 fireTrigger 的任务扫描无法扫到造成任务无法继续执行,这就是缺火(Misfire),
解释的并不好,请大神给斧正哈
因为原版的quartz在这两块存在并发(集群) 以及全局悲观锁的存在,一旦触发 Misfire 则可能导致任务存在不可知的问题,同时 MisfireHandler、ClusterManager 为两个独立不同的线程任务(轮询),但使用的锁是同一把,逻辑处理就存在时效性问题(延迟)
所以对于本 quartz集群增强版 就不同了, 现在我将这两招合一, 使用 ClusterMisfireHandler 来处理 Misfire 任务以及节点check及清理任务,同样是使用数据库锁,但是在 ClusterMisfireHandler 内部做了并发优化,以保证同一时间一个应用下只有一个节点执行,这点而很重要!
8. 其他
- 简化了线程池的管理同时也兼容原有的
SimpleThreadPool - 由于传参的变化也无需对存储参数的大字段的操作做各个厂商的数据库的兼容
架构设计
quartz-client+后管集成效果
目前可能存在及已知的问题
- 不管是 ClusterMisfireHandler 维护集群及缺火,还是 QuartzSchedulerThread 扫任务 都是按频度来的,其中 QuartzSchedulerThread 是5s一次循环 ,ClusterMisfireHandler 则是15s一次循环,这样问题就来了
- 添加任务时,若您是10点整添加的任务则任务最快也得10点过5s后才可执行,这是目前 任务扫描的频度及当前架构而为之的
- QuartzSchedulerThread 在扫描批次任务后不断循环以到执行时间点时,若关闭节点及应用也只有等当前次执行完成后才会停止任务
- QuartzSchedulerThread 的锁的处理(集群环境下如何保证一个任务只被一个节点执行)可能存在缺陷,但目前排查不出问题,这需要使用者花时间测试以排查根本原有
- 去掉 group 对于 group 的使用者来说这是不好的消息,这算一个吧
- 目前仅支持 postgresql、mysql、oracle 这三个厂商的数据库支持,并经过测试通过,这是使用限制
- client sdk (
quartz-client) 虽已经过测试通过,可能存在未知bug及设计缺陷
quartz集群增强版🎉的更多相关文章
- Quartz集群
为什么选择Quartz: 1)资历够老,创立于1998年,比struts1还早,但是一直在更新(27 April 2012: Quartz 2.1.5 Released),文档齐全. 2)完全由Jav ...
- 项目中使用Quartz集群分享--转载
项目中使用Quartz集群分享--转载 在公司分享了Quartz,发布出来,希望大家讨论补充. CRM使用Quartz集群分享 一:CRM对定时任务的依赖与问题 二:什么是quartz,如何使用, ...
- 使用sqlserver搭建高可用双机热备的Quartz集群部署【附源码】
一般拿Timer和Quartz相比较的,简直就是对Quartz的侮辱,两者的功能根本就不在一个层级上,如本篇介绍的Quartz强大的序列化机制,可以序列到 sqlserver,mysql,当然还可以在 ...
- Springboot2.X集成Quartz集群
为什么要使用Quzrtz集群 在项目进行集群部署时,如果业务在执行中存在互斥关系,没有对定时任务进行统一管理,就会引起业务的多次执行,不能满足业务要求.这时就需要对任务进行管理,要保证一笔业务在所有的 ...
- 双机热备的Quartz集群
sqlserver搭建高可用双机热备的Quartz集群部署[附源码] 一般拿Timer和Quartz相比较的,简直就是对Quartz的侮辱,两者的功能根本就不在一个层级上,如本篇介绍的Quartz ...
- quartz集群报错but has failed to stop it. This is very likely to create a memory leak.
quartz集群报错but has failed to stop it. This is very likely to create a memory leak. 在一台配置1核2G内存的阿里云服务器 ...
- Quartz集群配置
先看看quartz的持久化基本介绍: 引用 1 大家都清楚quartz最基本的概念就是job,在job内调用具体service完成具体功能,quartz需要把每个job存储起来,方便调度,quartz ...
- Quartz集群原理及配置应用
1.Quartz任务调度的基本实现原理 Quartz是OpenSymphony开源组织在任务调度领域的一个开源项目,完全基于Java实现.作为一个优秀的开源调度框架,Quartz具有以下特点: (1) ...
- quartz集群调度机制调研及源码分析---转载
quartz2.2.1集群调度机制调研及源码分析引言quartz集群架构调度器实例化调度过程触发器的获取触发trigger:Job执行过程:总结:附: 引言 quratz是目前最为成熟,使用最广泛的j ...
- (4) Spring中定时任务Quartz集群配置学习
原 来配置的Quartz是通过spring配置文件生效的,发现在非集群式的服务器上运行良好,但是将工程部署到水平集群服务器上去后改定时功能不能正常运 行,没有任何错误日志,于是从jar包.JDK版本. ...
随机推荐
- MySQL 亿级数据平滑迁移实战
作者:来自 vivo 互联网服务器团队- Li Gang 本文介绍了一次 MySQL 数据迁移的流程,通过方案选型.业务改造.双写迁移最终实现了亿级数据的迁移. 一.背景 预约业务是 vivo 游戏中 ...
- 在 Python 中通过读取 .env 文件获得环境变量
在编写 Python 脚本时,我们会使用一些私密数据,如调用 API 时使用的 token.为了避免隐私泄露,这些私密数据一般不直接写入脚本文件中.而是写入一个文件,并通过读取文件的方式获取私密数据内 ...
- Java取模和取余,你真的弄懂了吗?
前言 Java 中常见的取模和取余(求余)计算,在我们日常的很多业务领域都有用到.比如当我们做数据加密时,密码学中不同的加密方案底层会采用不同的模运算来决定其复杂度:做游戏的同学游戏引擎中的取余求最高 ...
- 设计模式 | 中介者模式/调停者模式(Mediator)
定义: 用一个中介对象来封装以系列的对象交互.中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地变化他们之间的交互. 结构:(书中图,侵删) 一个抽象中介者 若干具体中介者 一个抽象 ...
- MMDetection
安装了mmdetection,想跑一下有几篇文章的工作.总觉得发展很快,一转眼几年时间,好多东西都变了.可再仔细看,感觉又没变啥,还是faster rcnn, ssd, yolo等,这几年变化的主要是 ...
- ASP.NET Core – Work with Environment (Development, Staging, Production)
前言 这篇讲一讲发布和环境 (development, staging, production) 介绍 我的网站是 host 在 Azure 的 Virtual Machine, 跑 IIS, 没有使 ...
- Java如何将Object转换成指定Class对象
在Java中,将Object转换为指定类型的Class对象实际上是两个不同概念的操作: 将Object实例转换为特定类型的实例:这通常涉及到类型转换(如(MyType) myObject)或者通过反射 ...
- TS体操类型学习记录
Easy 1. Easy - 4 - Pick 从类型 T 中选出符合 K 的属性,构造一个新的类型 type MyPick<T, K extends keyof T> = { [key ...
- 《Vue.js 设计与实现》读书笔记 - 第7章、渲染器的设计
第7章.渲染器的设计 7.1 渲染器与响应系统的结合 渲染器需要有跨平台的能力. 在浏览器端会渲染为真实的 DOM 元素. const { effect, ref } = VueReactivity ...
- 冒泡排序和一点优化(php)
function maopao($arr){ $len = count($arr);//获取数组的长度 //有多少个数组元素就最多就要排n-1次 for ($j=0;$j<$len-1;$j++ ...



