注册
登录
开源地址: https://github.com/funnyzpc/quartz
这是除了mee_admin之外,投入时间精力最多的一次开源了,quartz集群增强版前前后后花费了我四月有余的时间精力开发而来,实属不易~
先简要的说下:quartz集群增强版由quartz的 2.3.2 版本改造,对原有功能进行了部分缩减, 同时也对现有的痛点做了大量的增强,这些增强包括但不限于如下:
将默认参数存储方式由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字符串
这是很大的改变,如果是执行端使用,只需添加依赖 quartz-core,如果是后管配置则只需要连接执行库(数据库)后使用依赖 quartz-client 来配置,管理集群或分布式的执行端也只需要
使用此来配置即可(前提是连接同一个库表), 这个改变在原版的quartz中是不可想象的,原版的quartz执行端与配置端耦合这种不太美妙的方式着实令人头疼与不解
这同样也是重大的变化,原版采用lock表行级悲观锁,每次变更都要竞争同一个 STATE_ACCESS 或 TRIGGER_ACCESS ,同时每次执行加锁释放锁的过程还需配合线程本地变量(ThreadLocal)来使用,看起来有些没必要而十分的笨重的同时系统开销也比较大
quartz集权增强版不再使用 lock 表悲观锁,而是使用 UPDATE ... WHERE ... 方式(乐观锁),虽同样存在一定的查询开销,但写db的开销大大地减少了。
同时,需要说明的是使用乐观锁似乎还是有些不够,可目前并没有测试出bug(也许是测试不够严格吧...),如果有好的idea 恳请告知哈~
由于底层去掉了trigger及 memory 单机等相关逻辑,故表结构及逻辑也做了相应的简化,由原版的11张表简化为4张表,对,没错~,就是四张表,四张表就ok
表的整体设计主要参考了 mee_timed 这个同样由我写的定时任务组件,目前 这四张表为:
group(组) 这是个不太有用的概念,组在绝大数使用quartz的开发者来说十分困惑(至少我经历的项目大多是这样),group的使用如有不慎会跟预期存在差异,因为有 group 这一层的存在,配置任务也略显有些臃肿。。。🤨🤨
去掉了 group 的同时也去掉了 TriggerKey 及相关的逻辑,这样就基本淡化了 group 的概念及使用,好处不言而喻。
对于常用的springboot框架,集成方式与原版的quartz的方式并无太大区别,主要区别是只需导入 quartz集群增强版 提供的表即可,starter(autoconfigure)中无用的配置类及方法都做了兼容
还有就是原有的context稍有变化,主要是去掉了TriggerKey以及增强json传值带来的变更,基本使用就无任何区别~
首先,这个变更也蛮大的。。。
先说下缺火是什么,由于quartz内所有执行时间点都是通过对应类型的 Trigger(eg: CronTriggerImpl、 SimpleTriggerImpl) 计算出来的,一旦出现不可预知的错误以及停机,则执行时间点无法向前推进,如果补偿或恢复机制,则 fireTrigger 的任务扫描无法扫到造成任务无法继续执行,这就是缺火(Misfire),
解释的并不好,请大神给斧正哈
因为原版的quartz在这两块存在并发(集群) 以及全局悲观锁的存在,一旦触发 Misfire 则可能导致任务存在不可知的问题,同时 MisfireHandler、ClusterManager 为两个独立不同的线程任务(轮询),但使用的锁是同一把,逻辑处理就存在时效性问题(延迟)
所以对于本 quartz集群增强版 就不同了, 现在我将这两招合一, 使用 ClusterMisfireHandler 来处理 Misfire 任务以及节点check及清理任务,同样是使用数据库锁,但是在 ClusterMisfireHandler 内部做了并发优化,以保证同一时间一个应用下只有一个节点执行,这点而很重要!
SimpleThreadPool

quartz-client+后管集成效果

quartz-client) 虽已经过测试通过,可能存在未知bug及设计缺陷