记一次Quartz重复调度(任务重复执行)的问题排查
公司前期改用quartz做任务调度,一日的调度量均在两百万次以上。随着
调度量的增加,突然开始出现job重复调度的情况,且没有规律可循。网上
也没有说得较为清楚的解决办法,于是我们开始调试Quartz源码,并最终
找到了问题所在。如果没有耐性看完源码解析,可以直接拉到文章最末,
有直接简单的解决办法。注:本文中使用的quartz版本为2.3.0,且使用JD
BC模式存储Job。
2. 准备
首先,因为本文是代码级别的分析文章,因而需要提前了解Quartz的用途
和用法,网上还是有很多不错的文章,可以提前自行了解。
其次,在用法之外,我们还需要了解一些Quartz框架的基础概念:
1. Quartz把触发job,叫做fire。TRIGGER_STATE是当前trigger的状态
,PREV_FIRE_TIME是上一次触发时间,NEXT_FIRE_TIME是下一次
触发时间,misfire是指这个job在某一时刻要触发,却因为某些原因没
有触发的情况。
2. Quartz在运行时,会起两类线程(不止两类),一类用于调度job的调
度线程(单线程),一类是用于执行job具体业务的工作池。
3. Quartz自带的表里面,本文主要涉及以下3张表:
triggers表。triggers表里记录了,某个trigger的PREV_FIRE_TIME(
上次触发时间),NEXT_FIRE_TIME(下一次触发时间),TRIGGER_
STATE(当前状态)。虽未尽述,但是本文用到的只有这些。