天天微动态丨【定时调度】- 01 quartz的基础你真的了解吗
概述
Quartz一款功能丰富、历史悠久,完全基于Java实现的开源任务调度框架,Java调度领域知名度非常高。其简单易用、稳定可靠的特性,使其被很多第三方应用将其当成调度框架基础依赖,如spring boot已内置集成quartz,elastic-job调度框架则将quartz作为其底层基础实现进行封装,xxl-job曾经历史版本也是集成quartz作为其触发实现机制基础,不过在最新版本采用时间轮实现已将quartz移除。
核心三叉戟
使用quartz api时,最核心三件套如下:
Scheduler
SchedulerFactory和Scheduler从名称就很容易识别这里采用工厂设计模式,Scheduler是quartz暴露出来供开发使用的一个最重要组件,从开发者视角来看它就是quartz的门面,对quartz的各种操作都是通过Scheduler进行串联,类似于quartz的大管家、代言人角色。
【资料图】
“这种设计模式在开源框架中很常见,比如
mybatis中SqlSessionFactory和SqlSession,通过给开发者提供大管家组件,通过一个组件串联起所有核心功能,简化了开发人员上手框架难度。
一般一个应用只会对应一个Scheduler实例,不同Scheduler实例之间通过schedulerName进行隔离,所有的quartz数据库表设计中都有sched_name这一列字段,这样Scheduler处理任务时只会操作数据库表中对应schedulerName下的数据。quartz集群就是利用多个Scheduler实例配置相同schedulerName名称,实现多机器同时处理同一个schedulerName下任务来达到集群效果。
“
schedulerName可以通过org.quartz.scheduler.instanceName进行配置,默认名称为QuartzScheduler。
Scheduler操作的主要是JobDetail和Trigger两个组件,JobDetail封装的是任务配置信息,而Trigger触发器封装了任务触发信息,它们是1:N关系,即一个JobDetail可以关联多个Trigger触发器,但是一个Trigger触发器只能绑定到一个Job上。
JobDetail
JobDetail组件封装了quartz调度任务定义信息,下面是JobDetail组件常规使用方式如下:
// JobDataMap实现Map接口,任务调度时存储到JobExecuteContext中,可以传递给Job实例JobDataMap jobDataMap = new JobDataMap();jobDataMap.put("name", "zhangsan");jobDataMap.put("time", System.currentTimeMillis());JobDetail jobDetail = JobBuilder // 绑定任务类 .newJob(QuartzCronJob.class) .storeDurably() // job对应ID .withIdentity("job2", "DEFAULT") .usingJobData(jobDataMap) .build();JobKey jobKey = jobDetail.getKey();if (scheduler.checkExists(jobKey)) { log.warn("调度任务已存在,删除后重新添加:{}", jobKey); scheduler.interrupt(jobKey);//停止JOB /** * deleteJob操作在删除Job之前,会执行unscheduleJob()取消job和trigger关联 */ scheduler.deleteJob(jobKey);}// 将JobDetail任务定义信息插入quartz表scheduler.addJob(jobDetail, true);JobDetail操作比较简单,主要有两点需要注意:1、newJob(Class extends Job> jobClass)操作绑定任务类,任务类就是封装用户业务逻辑类;2、withIdentity(String name, String group)给该任务设置一个身份ID,后续可以通过该身份ID进行管理,为方便灵活管理quartz抽象出group概念,这样可以批量对一组作业进行批量操作,身份ID使用JobKey进行封装。
使用Scheduler类addJob(JobDetail jobDetail, boolean replace)方法就将创建的Job定义信息添加到quartz中,一般采用数据库持久化模式,即这里就会将Job定义信息插入到qrtz_job_details表中(见下图)。
下面来看下几个关键字段:
sched_name:上面说过,用来关联对应的Scheduler实例is_durable:是否持久化is_nonconcurrent:是否允许同一个作业可以同时多个实例执行,比如一个任务间隔1秒,但其执行时间为2秒,通过该属性控制是否允许同一个作业有多个任务同时允许,参见@DisallowConcurrentExecutionis_update_data: 任务已经执行中,是否允许更新JobDataMap持久化信息,参见@PersistJobDataAfterExecutionrequests_recovery: 故障恢复使用,具体参见后续源码分析job_data:JobDataMap序列化后存储到字段中Trigger
任务定义完成,但是任务按照怎么周期性规则进行触发执行,这就要看Trigger触发器的脸色了
Trigger组件常规使用方式如下:
JobDataMap jobDataMap = new JobDataMap();jobDataMap.put("name", "lisi");jobDataMap.put("address", "China");Trigger trigger = TriggerBuilder .newTrigger() .withIdentity("trigger1", "DEFAULT") .usingJobData(jobDataMap) .startAt(new Date()) .endAt(new Date(System.currentTimeMillis()+38 * 60 * 1000)) .withSchedule(CronScheduleBuilder.cronSchedule("*/10 * * * * ?")) .forJob(new JobKey("job1", "DEFAULT")) .build();//时间TriggerKey triggerKey = trigger.getKey();if(scheduler.checkExists(triggerKey)){ scheduler.unscheduleJob(triggerKey);}//必须绑定jobscheduler.scheduleJob(trigger);和JobDetail类似,主要有两点需要注意:1、同withIdentity(String name, String group),同理给该触发器设置一个身份ID,对应TriggerKey;2、startAt()、endAt()对应启止时间;3、withSchedule(CronScheduleBuilder.cronSchedule("*/10 * * * * ?"));4、forJob(JobKey keyOfJobToFire)将Trigger与Job进行关联,这样才知道触发哪个任务。
最后通过Scheduler类scheduleJob(Trigger trigger)方法就将创建的Trigger定义信息添加到quartz中,一般采用数据库持久化模式,即这里就会将Trigger定义信息插入到触发器相关表中,示例中使用cron触发器,则插入到qrtz_cron_triggers表中(见下图)。
下面我们就来看下任务是咋个触发的。Scheduler类scheduleJob(Trigger trigger)将触发器持久化后,你会发现qrtz_cron_triggers中没有起止时间以及和Job绑定内容,所以,接下来我们看一张非常重要表:qrtz_triggers。scheduleJob()方法在持久化Trigger信息后会同时向qrtz_triggers表插入一条记录(见下图):
qrtz_job_details和qrtz_cron_triggers可以看成静态表,那qrtz_triggers就是运行动态表,保存着任务运行期间数据,且随着运行记录在动态变更,是quartz调度任务运行最重要的一张表,下面我们来看下这张表中几个关键字段:
start_time、end_time: trigger定义时设置的起止时间next_fire_time: 下次触发时间戳prev_fire_time: 上次触发时间戳trigger_state: trigger状态,最常见状态WAITING、ACQUIRED和EXECUTING,分别对应等待(下次触发时间还早) -> 加载到内存中等待(下次触发时间快到了) --> 执行(下次触发时间到了,需要触发任务),具体参见后续源码分析misfire_instr: trigger触发时间过期处理策略,比如本来是10:23:50时间点进行触发,但是由于某些原因在10:23:53秒才检索出来,这是该触发时间点已经过期,misfire_instr就是控制采用什么策略处理该过期任务,是直接丢弃重新计算下次触发时间点、还是一定时间范围内过期的理解执行等等,具体参见后续源码分析job_data: 和JobDetail一样,Trigger也可绑定一个JobDataMap,用于向Job实例传递参数,该字段就是存储Trigger关联的JobDataMap序列化内容quartz基本上就是围绕qrtz_triggers中这几个关键字段实现任务触发,我们连蒙带猜大致可以想出quartz任务调度触发机制粗略流程:
1、通过配置的trigger触发器,计算出下次触发时间,更新到next_fire_time字段,同时更新trigger_state状态为WAITING;
2、quartz线程扫描该表,从表中查询出未来很短一段时间将要触发的记录(比对next_fire_time和当前时间)放入到内存排队队列中,然后将trigger_state更新成ACQUIRED;
3、然后阻塞直到内存排队队列中触发任务到时间点,再触发任务之前,重新计算下次触发时间点,更新到next_fire_time,同时将trigger_state更新为WAITING,然后执行当前任务;
4、由于next_fire_time和trigger_state值更新,重新开始步骤1,就这样循环往复触发下去。
总结
这节从一个使用者角度简单分析quartz核心运行机制,由于只是简单的从外层而未深入剖析源码,只是简单结合数据库表信息对quartz大致的运行机制做个简单猜想,一些重要属性也没展开,带着这些疑问下一节通过源码分析找到真实的答案,一步步加深对quartz运行机制的理解。
标签:
推荐
- 天天微动态丨【定时调度】- 01 quartz的基础你真的了解吗
- 焦点精选!商南县城关小学开展趣味数学特色课程
- 焦点资讯:清淡饮食有哪些?日常清淡食物列举
- 世界快资讯丨购车好时机!南宁市各大车企将陆续推出超大额让利
- 今日热闻!古诗小池全部解释_古诗小池的全文
- 世界热点评!混乱中立都是些什么人_混乱中立什么职业
- 观点:如何让记忆力变强36种方法_增强记忆力的方法
- 天天关注:“火热”数据折射中国经济“热度” 尽显开放中国的魅力
- 【全球独家】2022高考三天穿什么颜色衣服吉利 高考考试忌讳穿什么颜色的
- 焦点简讯:“一个都不能少”一堂特别的法治课
- 环球快资讯:长沙今年中考中招政策有三个微调 初中毕业生约9.71万
- 【独家焦点】3月24日两市散户减持前50只个股
- 快看点丨人教版语文二年级第七单元词语修饰词填空
- 焦点消息!越降价越不敢买!2000多家4S店闭店,经销商扛不住了!去库存压力巨大,近百家企业建议:延后国六B执行时间!
- 热文:开始与结束的优美句子
- 世界聚焦:全国保险公众宣传日2022_全国保险公众宣传日
- 最资讯丨“山西造”新能源机车家族再添新成员
- 天天热推荐:山西无人驾驶快递车首次上路试运行
- 环球速读:区域观察家|专访石敏俊:干部真正理解营商环境,企业就不会轻易离开
- 环球观天下!蒙牛乳业(02319.HK):3月23日南向资金增持7000股
- 世界热推荐:泗洪县属于哪个市管辖_泗洪县属于哪个市
- 每日报道:毕生一定要去的:中国十大最美城市
- 世界观察:挑的组词-用挑组词
- 世界消息!央媒看海南丨新华社:博鳌零碳示范区开始“试验”
- 天天快报!上海高速公路收费站推广智能发卡 提升车辆通行效率
- 每日速看!沈阳创业担保贷款受理部门+联系方式
- 全球快消息!起亚3月20日发布新能源战略 EV6 GT等三款新车亮相国内
- 时讯:世界最大的猴子
- 世界新资讯:绘王Inspiroy 2系列数位板发布,诠释潮流配色+创意设计魅力
- 天天关注:百度回应文心一言文生图“套壳”质疑:为完全自研的大语言模型
- 【世界热闻】宝应县气象台发布霾黄色预警【Ⅲ级/较重】
- 世界百事通!《红楼梦》贾宝玉被害后三次出门,林妹妹都说“死”字是为什么?
- 世界今头条!“网红”电解质消毒液真有杀菌功效吗
- 环球视讯!西部数据移动硬盘如何保修
- 全球今亮点!电子信息工程是最差的专业吗_电子信息工程专业就业前景
- 【世界报资讯】咖啡色裤子搭配黑色及灰色上衣_咖啡色裤子搭配
- 当前快看:内蒙古自治区气象台解除大风蓝色预警【IV级/一般】
- 【天天播资讯】小班语言太阳和月亮教案及反思_小班语言优秀公开课教案
- 【新视野】踏雪寻梅的意思是
- 热门看点:广西自然资源档案博物馆
- 天天快播:葛斯齐会放过,想一笑泯恩仇的汪小菲吗?
- 环球看点!2023年春季策略及投资展望:港股将受益于中国经济复苏 估值洼地有望修复
- 每日速看!上海电影3月22日盘中涨停
- 全球热门:《Delivery Man》打破八集定律,尹灿荣与方珉雅上演意外之吻
- 每日热文:樱花树下绘樱花 普陀区这所中学的家长送了孩子们一条“樱花大道”
- 【速看料】良信股份:3月21日获融资买入373.84万元,占当日流入资金比例9.65%
- 世界要闻:吃一次即是在胃上打8个洞,许多人还嘴馋,医生教训:无知,在自毁肠胃
- 世界聚焦:郑州银行: 郑州银行股份有限公司2023年第一次临时股东大会会议材料
- 热文:教育动态城北区教育局联合区爱卫办开展“甲流健康知识讲座”主题宣传教育活动
- 环球滚动:封神榜_老版36集全剧情_封神榜第二部
- 世界热讯:氧化钾概念股票_氧化钾
- 世界热头条丨手机微信付款怎么付_微信付款怎么付
- 每日看点!比亚迪回应将推出智能手表:情况属实将于4月发布
- 世界焦点!和讯个股快报:2023年03月21日 西麦食品 (002956),该股股价成功突破年线压力位
- 每日速读!数字化、绿色化注入产业发展强劲动能
- 当前信息:第三方检测机构有哪些_第三方物流公司有哪些
- 世界微速讯:“小”数据里看新趋势①丨一台空调里藏着的消费回暖“密码”
- 环球热推荐:个人兴趣爱好怎么写_个人兴趣
- 焦点快报!中东石油运输三大路线地图_中东石油运输三大路线
- 【时快讯】如果您在机遇区追逐节税 请确保您的团队提出正确的问题
- 焦点速读:三码是指哪三码_三码
- 【全球新视野】陈光明: 今年不应该太悲观,此时看空是对常识的谬视,要在两方面下功夫
- 今日聚焦!永善县气象台发布大风预警信号蓝色预警【Ⅳ级/一般】【2023-03-20】
- 世界头条:中信证券:预计美联储3月和5月议息会议各加息25bps
- 微资讯!河北省气象部门举办“世界气象日”科普活动
- 环球播报:生物医药板块反弹拉升,海创药业 欧林生物涨超10%
- 全球速递!智享新科技,解锁新驾趣,长安智电iDD给你超感体验
- 环球信息:寒春易感冒,饮食留意少酸多辛,多吃“3白3红3黄”,顺利过春寒
- 全球播报:[Jo×沈韵] 2
- 世界速看:4AM比赛中整活,却不小心来了场“教学局”?粉丝直呼韦神重回巅峰
- 【世界新要闻】济南的冬天说课稿一等奖人教版_济南的冬天说课稿
- 当前报道:鹿鼎记游戏单机2002_鹿鼎记游戏单机
- 环球头条:herschel_hers
- 环球微头条丨武大华科2023年硕士研究生复试分数线公布
- 每日速递:楚汉春秋
- 热讯:华夏兴阳一年持有混合基金经理变动:孙轶佳不再担任该基金基金经理
- 环球观察:流感,外散在卫分风热,内清在肺热毒,银翘散治各种温病,甚效
- 每日关注!五年级水浒传读后感_水浒传 读后感400字小学五年级的
- 环球百事通!若鸟社媒晒枪手合照激励球队:输赢一起扛,我们还有11场决赛要踢
- 速看:蜡烛图的使用
- 天天短讯!6岁娃看店,游客花98元买走价值3000元虫草
- 微头条丨蚂蚁财富上线理财分 600分以上用户占2成
- 天天时讯:记者暗访日租女友行业 背后内幕曝光令人震惊!!
- 环球新消息丨合肥长虹电视机厂倒闭辞退员工?厂方辟谣
- 每日看点!汽车零部件:麦格纳中国成立座椅和部件合资公司
- 世界观热点:一按眼球疼是怎么回事_眼球疼是怎么回事
- 当前视讯!法国欧预赛名单:姆巴佩领衔 吉鲁格子在列 本泽马缺席
- 当前焦点!多家上市公司发布机器人布局新动向 应用场景丰富 人形机器人研制仍较少
- 世界观察:桃李芬芳 教泽绵长_桃李芬芳教泽绵长意思
- 速读:尹锡悦:日韩不应再为历史恩怨对抗 两国国民应共同迈向未来
- 新资讯:张本智和爆冷0-3惨败出局!罕见被限制发不出声,非洲霸主怒吼
- 最资讯丨2023年3月8日全国硅藻土价格最新行情预测
- 环球热资讯!国内商品期货早盘开盘普跌,原油跌逾5%
- 世界资讯:被驳回是什么意思_驳回是什么意思
- 当前焦点!浙江41分狂胜江苏!王世龙太狠,李楠主动投降也不给面子
- 全球今日报丨hidkeyboard驱动正常 键盘失灵_hid keyboard device驱动下载
- 天天日报丨守护民众金融安全 陆金所控股开展315消费者权益保护宣传活动
- 热消息:瑞斯康达董秘回复:公司在全千兆接入延伸的产品主要包括三类:面向家庭客户FTTR
- 每日热文:中信建投(601066)3月15日主力资金净卖出413.24万元
- 天天热推荐:2023郑州供暖时间几月到几月份结束?
