Quartz框架(一)—Quartz的基本配置
Quartz框架(二)—jobstore数据库表字段详解
Quartz框架(三)—任务的并行/串行执行
Quartz框架(四)—misfire处理机制
Quartz框架(五)— 有状态的job和无状态job
Quartz框架(六)— Trigger状态转换
Quartz框架(七)— Quartz集群原理
Quartz框架(八)— Quartz实现异步通知
Quartz框架(九)— 动态操作Quartz定时任务
Quartz框架(十)监听
在Quartz框架中,Trigger是一个重要的对象,定时任务的调度、触发都是通过Trigger的操作来实现的。
Trigger按照类型的不同,可以划分为SIMPLE、CORN、BLOB等类型,数据库中也有对应的表存储。除此之外QRTZ_TRIGGERS和QRTZ_FIRED_TRIGGERS是两张存储Trigger调度的表。
正常获取、触发任务执行的流程:
一个触发器只能绑定一个Job,但是一个Job可以有多个触发器
调度器线程执行的时候,首先从triggers表中获取状态为WAITING,并且将要触发的Trigger。然后将WAITING状态更新为ACQUIRED,表示该触发器抢占到了,防止其他调度器(实例)抢占。然后插入触发器信息以及实例名到FRIED_TRIGGERS表中,状态为ACQUIRED。前面的更新和后面的插入是在一个事务中进行的。
该触发器抢占到任务后,等待触发时间的到来。
执行时间到来后,每触发一次任务,都会在FIRED_TRIGGERS表中创建一条记录,并且状态为EXECUTING。如果任务允许并发执行,此时TRIGGERS表里的状态更新为WAITING,PAUSED,COMPLETE(不需要执行)。
如果任务不允许并发执行,还会把Triggers表里的状态更新为BLOCK或PAUSED_BLOCK。
注意:Triggers表更新时根据 任务名和任务所属组名 而不是 触发器名称和触发器组名来更新的。这就解决了一个任务有多个触发器的并发问题;然后触发器线程会创建一个执行环境来执行任务,以便在任务执行完成后更新触发器的状态。任务执行完成后,在一个事务中触发器状态更新为WAITING,删除FIRED_TRIGGERS表里对应的记录。
如何避免多个节点执行同一个任务
qrtz_trigger表中有NEXT_FIRE_TIME
字段(下一次触发时间)。每个任务在即将执行的时候,获取qrtz_locks表中的行级锁,开启一个事务(更新qrtz_trigger表状态为ACQUIRED,并且插入qrtz_fire_trigger一条数据,起始状态为ACQUIRED)。