Quartz是一个Java编写的开源任务调度框架,在实际的项目中可能有很多的费时的批处理作业需要完成,可以使用Quartz将这种任务安排到用户活跃量少的时候执行。
Quartz API的关键接口是:
- Scheduler - 与调度程序交互的主要API。
- Job - 由希望由调度程序执行的组件实现的接口。
- JobDetail - 用于定义作业的实例。
- Trigger(即触发器) - 定义执行给定作业的计划的组件。
- JobBuilder - 用于定义/构建JobDetail实例,用于定义作业的实例。
- TriggerBuilder - 用于定义/构建触发器实例。
我认为Quartz 的使用可分为三种方式:
- 1.只使用Quartz的jar包通过api开发。
- 2.Quartz整合Spring的非Web开发。
- 3.Quartz整合SpringBoot的开发。
当然321是包含的关系,第一种方式可以查看文档很好实现。
如果要整合Spring和SpringBoot 那就不得不将Quartz 中的对象交给Spring管理,不然就失去了意义不是?可是如何将Quartz交给Spring管理呢?的业务代码需要写在Job中,和Spring整合之后这个类的实例就需要交给Spring 管理。这里有两种方式来处理:
- 1.不实现Job的接口,自己定义一个类,指定调用方法
@Component
public class CommonJob {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private UserService userService;
/**
* @Author: wks
* @Description: 执行任务通用方法
* @Param: [quartzTask]
* @return: void
* @throw: 请描述异常信息
*/
public void execute(QuartzTask quartzTask) {
userService.getUserInfo(String userId);
//业务代码
}
@Component
public class QuartzTaskHandler {
@Autowired
@Qualifier("myScheduler")
private Scheduler scheduler;
@Autowired
private CommonJob commonJob;
@Autowired
private QuartzTaskMapper quartzTaskMapper;
/**
* @Author: zhaomeinan
* @Description: 新增任务
* @Date: 15:17 2019/1/3
* @Modificd By:
* @Param: [quartzTask]
* @return: void
* @throw: 请描述异常信息
*/
public void addJob(QuartzTask quartzTask)
throws SchedulerException, NoSuchMethodException, ClassNotFoundException {
if (quartzTask == null) {
return;
}
//任务启用状态 1启用 2暂停
if (quartzTask.getInitiateMode() == 2) {
return;
}
TriggerKey triggerKey = TriggerKey
.triggerKey(quartzTask.getJobName(), quartzTask.getJobGroup());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (null == trigger) {
//定义jobdetail
MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
jobDetail.setConcurrent(false); // 是否并发执行
jobDetail.setName(quartzTask.getJobName()); // 设置任务的名字
jobDetail.setGroup(quartzTask.getJobGroup()); // 设置任务的分组,在多任务的时候使用
jobDetail.setTargetObject(commonJob); // 需要执行的对象
jobDetail.setTargetMethod("execute"); //非常重要,执行CommonJob类中的需要执行方法
jobDetail.setArguments(quartzTask); //执行CommonJob类中的需要执行方法传入的参数
jobDetail.afterPropertiesSet();
//定义corn
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
.cronSchedule(quartzTask.getCronExpression()).withMisfireHandlingInstructionDoNothing();
trigger = TriggerBuilder.newTrigger()
.withIdentity(quartzTask.getJobName(), quartzTask.getJobGroup())
.withSchedule(scheduleBuilder).build();
//将任务加入工厂中
scheduler.scheduleJob(jobDetail.getObject(), trigger);
}
}
}
通过MethodInvokingJobDetailFactoryBean
实现了不通过实现Job接口的方式来实现任务调度
- 2.通过继承
QuartzJobBean
类实现
@Component
public class CommonJob extends QuartzJobBean {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private UserService userService;
@Value("${server.port}")
private String port;
/**
* @Author: wks
* @Description: 执行任务通用方法
* @Modificd By:
* @Param: [quartzTask]
* @return: void
* @throw: 请描述异常信息
*/
@Override
public void executeInternal(JobExecutionContext jobExecutionContext) {
//获得传过来的参数
JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
QuartzTask quartzTask = (QuartzTask)jobDataMap.get("quartzTask");
userService.getUserInfo(String userId);
//业务代码
}
}
进入到QuartzJobBean
类中
public abstract class QuartzJobBean implements Job {
/**
* This implementation applies the passed-in job data map as bean property
* values, and delegates to {@code executeInternal} afterwards.
* @see #executeInternal
*/
@Override
public final void execute(JobExecutionContext context) throws JobExecutionException {
try {
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.addPropertyValues(context.getScheduler().getContext());
pvs.addPropertyValues(context.getMergedJobDataMap());
bw.setPropertyValues(pvs, true);
}
catch (SchedulerException ex) {
throw new JobExecutionException(ex);
}
executeInternal(context);
}
/**
* Execute the actual job. The job data map will already have been
* applied as bean property values by execute. The contract is
* exactly the same as for the standard Quartz execute method.
* @see #execute
*/
protected abstract void executeInternal(JobExecutionContext context) throws JobExecutionException;
}
发现他将Job对象包装为BeanWrapper 并保存了context.getScheduler().getContext()
,和context.getMergedJobDataMap()
这样子CommonJob
对象就能拿到Quartz 的上下文信息,
这也就是为什么第一种方式为什么不可以直接实现Job接口了,因为这样子只是将CommonJob
交给了Spring 但是关于Quartz 的上下文信息并没有。
@Component
public class QuartzTaskHandler {
@Autowired
private Scheduler scheduler;
@Autowired
private QuartzTaskMapper quartzTaskMapper;
@PostConstruct
public void startScheduler() {
try {
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Author: zhaomeinan
* @Description: 新增任务
* @Date: 15:17 2019/1/3
* @Modificd By:
* @Param: [quartzTask]
* @return: void
* @throw: 请描述异常信息
*/
public void addJob(QuartzTask quartzTask)
throws SchedulerException, NoSuchMethodException, ClassNotFoundException {
if (quartzTask == null) {
return;
}
//任务启用状态 1启用 2暂停
if (quartzTask.getInitiateMode() == 2) {
return;
}
TriggerKey triggerKey = TriggerKey
.triggerKey(quartzTask.getJobName(), quartzTask.getJobGroup());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (null == trigger) {
//定义jobdetail
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("quartzTask", quartzTask);
JobDetail jobDetail = JobBuilder.newJob(CommonJob.class)
.withIdentity(quartzTask.getJobName(), quartzTask.getJobGroup())
.usingJobData(jobDataMap)
.build();
//定义corn
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
.cronSchedule(quartzTask.getCronExpression()).withMisfireHandlingInstructionDoNothing();
trigger = TriggerBuilder.newTrigger()
.withIdentity(quartzTask.getJobName(), quartzTask.getJobGroup())
.withSchedule(scheduleBuilder).build();
//将任务加入工厂中
scheduler.scheduleJob(jobDetail, trigger);
}
}
}
如何实现Quartz集群呢?
Quartz的集群功能通过故障转移和负载平衡功能为您的调度程序带来高可用性和可扩展性。
目前,群集仅适用于JDBC-Jobstore(JobStoreTX或JobStoreCMT),并且基本上通过使群集的每个节点共享相同的数据库来工作。
负载平衡自动发生,群集的每个节点都尽可能快地触发jobs。当Triggers的触发时间发生时,获取它的第一个节点(通过在其上放置一个锁定)是将触发它的节点。
每次射击只能有一个节点开火。我的意思是,如果工作有一个重复的Triggers,告诉它每10秒钟发射一次,那么在12:00:00,正好一个节点将运行这个工作,在12:00:10,一个节点将运行作业等。它不一定是每次相同的节点 - 它或多或少是随机的,哪个节点运行它。负载平衡机制对于繁忙的调度器(大量的Triggers)是近似随机的,但是对于非忙(例如,很少的Triggers)调度器而言,有利于同一个节点。
当其中一个节点在执行一个或多个作业期间失败时发生故障切换。当节点出现故障时,其他节点会检测到该状况并识别数据库中在故障节点内正在进行的作业。任何标记为恢复的作业(在JobDetail上都具有“请求恢复”属性)将被剩余的节点重新执行。没有标记为恢复的作业将在下一次相关的Triggers触发时简单地被释放以执行。
集群功能最适合扩展长时间运行和/或cpu密集型作业(通过多个节点分配工作负载)。如果需要扩展以支持数千个短期运行(例如1秒)作业,则可以考虑通过使用多个不同的调度程序(包括HA的多个群集调度程序)对作业集进行分区。调度程序使用集群范围的锁,这种模式会在添加更多节点(超过三个节点 - 取决于数据库的功能等)时降低性能。
通过将“org.quartz.jobStore.isClustered”属性设置为“true”来启用聚类。集群中的每个实例都应该使用相同的quartz.properties文件。这样做的例外是使用相同的属性文件,具有以下允许的异常:不同的线程池大小,以及“org.quartz.scheduler.instanceId”属性的不同值。集群中的每个节点必须具有唯一的instanceId,通过将“AUTO”作为此属性的值,可以轻松完成(不需要不同的属性文件)。有关更多信息,请参阅有关JDBC-JobStore的配置属性的信息。
不要在单独的机器上运行群集,除非它们的时钟使用某种形式的时间同步服务(守护进程)进行同步,而这些时间同步服务(守护进程)运行非常有限(时钟必须在彼此之间)。如果您不熟悉如何执行此操作,请参阅http://www.boulder.nist.gov/timefreq/service/its.htm。
不要针对任何其他实例运行(start()ed)的同一组数据库表启动(scheduler.start())非集群实例。您可能会收到严重的数据损坏,一定会遇到不正常的行为。
附上建表语句,因为有的数据库设计可能存在大小写敏感
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for qrtz_BLOB_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_BLOB_TRIGGERS`;
CREATE TABLE `qrtz_BLOB_TRIGGERS` (
`SCHED_NAME` varchar(120) NOT NULL,
`TRIGGER_NAME` varchar(200) NOT NULL,
`TRIGGER_GROUP` varchar(200) NOT NULL,
`BLOB_DATA` blob,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
KEY `SCHED_NAME` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
CONSTRAINT `qrtz_BLOB_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Trigger 作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创建他们自己定制的 Trigger 类型,<span style="color:#800080;">JobStore</span> 并不知道如何存储实例的时候)';
-- ----------------------------
-- Table structure for qrtz_CALENDARS
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_CALENDARS`;
CREATE TABLE `qrtz_CALENDARS` (
`SCHED_NAME` varchar(120) NOT NULL,
`CALENDAR_NAME` varchar(200) NOT NULL,
`CALENDAR` blob NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`CALENDAR_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='以 Blob 类型存储 Quartz 的 Calendar 信息';
-- ----------------------------
-- Table structure for qrtz_CRON_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_CRON_TRIGGERS`;
CREATE TABLE `qrtz_CRON_TRIGGERS` (
`SCHED_NAME` varchar(120) NOT NULL,
`TRIGGER_NAME` varchar(200) NOT NULL,
`TRIGGER_GROUP` varchar(200) NOT NULL,
`CRON_EXPRESSION` varchar(120) NOT NULL,
`TIME_ZONE_ID` varchar(80) DEFAULT NULL,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
CONSTRAINT `qrtz_CRON_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='存储 Cron Trigger,包括 Cron 表达式和时区信息';
-- ----------------------------
-- Table structure for qrtz_FIRED_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_FIRED_TRIGGERS`;
CREATE TABLE `qrtz_FIRED_TRIGGERS` (
`SCHED_NAME` varchar(120) NOT NULL,
`ENTRY_ID` varchar(95) NOT NULL,
`TRIGGER_NAME` varchar(200) NOT NULL,
`TRIGGER_GROUP` varchar(200) NOT NULL,
`INSTANCE_NAME` varchar(200) NOT NULL,
`FIRED_TIME` bigint(13) NOT NULL,
`SCHED_TIME` bigint(13) NOT NULL,
`PRIORITY` int(11) NOT NULL,
`STATE` varchar(16) NOT NULL,
`JOB_NAME` varchar(200) DEFAULT NULL,
`JOB_GROUP` varchar(200) DEFAULT NULL,
`IS_NONCONCURRENT` varchar(1) DEFAULT NULL,
`REQUESTS_RECOVERY` varchar(1) DEFAULT NULL,
PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`),
KEY `IDX_QRTZ_FT_TRIG_INST_NAME` (`SCHED_NAME`,`INSTANCE_NAME`),
KEY `IDX_QRTZ_FT_INST_JOB_REQ_RCVRY` (`SCHED_NAME`,`INSTANCE_NAME`,`REQUESTS_RECOVERY`),
KEY `IDX_QRTZ_FT_J_G` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_FT_JG` (`SCHED_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_FT_T_G` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
KEY `IDX_QRTZ_FT_TG` (`SCHED_NAME`,`TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='存储与已触发的 Trigger 相关的状态信息,以及相联 Job 的执行信息';
-- ----------------------------
-- Table structure for qrtz_JOB_DETAILS
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_JOB_DETAILS`;
CREATE TABLE `qrtz_JOB_DETAILS` (
`SCHED_NAME` varchar(120) NOT NULL,
`JOB_NAME` varchar(200) NOT NULL,
`JOB_GROUP` varchar(200) NOT NULL,
`DESCRIPTION` varchar(250) DEFAULT NULL,
`JOB_CLASS_NAME` varchar(250) NOT NULL,
`IS_DURABLE` varchar(1) NOT NULL,
`IS_NONCONCURRENT` varchar(1) NOT NULL,
`IS_UPDATE_DATA` varchar(1) NOT NULL,
`REQUESTS_RECOVERY` varchar(1) NOT NULL,
`JOB_DATA` blob,
PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_J_REQ_RECOVERY` (`SCHED_NAME`,`REQUESTS_RECOVERY`),
KEY `IDX_QRTZ_J_GRP` (`SCHED_NAME`,`JOB_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='存储每一个已配置的 Job 的详细信息';
-- ----------------------------
-- Table structure for qrtz_LOCKS
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_LOCKS`;
CREATE TABLE `qrtz_LOCKS` (
`SCHED_NAME` varchar(120) NOT NULL,
`LOCK_NAME` varchar(40) NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='存储程序的悲观锁的信息(假如使用了悲观锁)';
-- ----------------------------
-- Table structure for qrtz_PAUSED_TRIGGER_GRPS
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_PAUSED_TRIGGER_GRPS`;
CREATE TABLE `qrtz_PAUSED_TRIGGER_GRPS` (
`SCHED_NAME` varchar(120) NOT NULL,
`TRIGGER_GROUP` varchar(200) NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='存储已暂停的 Trigger 组的信息';
-- ----------------------------
-- Table structure for qrtz_SCHEDULER_STATE
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_SCHEDULER_STATE`;
CREATE TABLE `qrtz_SCHEDULER_STATE` (
`SCHED_NAME` varchar(120) NOT NULL,
`INSTANCE_NAME` varchar(200) NOT NULL,
`LAST_CHECKIN_TIME` bigint(13) NOT NULL,
`CHECKIN_INTERVAL` bigint(13) NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`INSTANCE_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='存储少量的有关 Scheduler 的状态信息,和别的 Scheduler 实例(假如是用于一个集群中)';
-- ----------------------------
-- Table structure for qrtz_SIMPLE_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_SIMPLE_TRIGGERS`;
CREATE TABLE `qrtz_SIMPLE_TRIGGERS` (
`SCHED_NAME` varchar(120) NOT NULL,
`TRIGGER_NAME` varchar(200) NOT NULL,
`TRIGGER_GROUP` varchar(200) NOT NULL,
`REPEAT_COUNT` bigint(7) NOT NULL,
`REPEAT_INTERVAL` bigint(12) NOT NULL,
`TIMES_TRIGGERED` bigint(10) NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
CONSTRAINT `qrtz_SIMPLE_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='存储简单的 Trigger,包括重复次数,间隔,以及已触的次数';
-- ----------------------------
-- Table structure for qrtz_SIMPROP_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_SIMPROP_TRIGGERS`;
CREATE TABLE `qrtz_SIMPROP_TRIGGERS` (
`SCHED_NAME` varchar(120) NOT NULL,
`TRIGGER_NAME` varchar(200) NOT NULL,
`TRIGGER_GROUP` varchar(200) NOT NULL,
`STR_PROP_1` varchar(512) DEFAULT NULL,
`STR_PROP_2` varchar(512) DEFAULT NULL,
`STR_PROP_3` varchar(512) DEFAULT NULL,
`INT_PROP_1` int(11) DEFAULT NULL,
`INT_PROP_2` int(11) DEFAULT NULL,
`LONG_PROP_1` bigint(20) DEFAULT NULL,
`LONG_PROP_2` bigint(20) DEFAULT NULL,
`DEC_PROP_1` decimal(13,4) DEFAULT NULL,
`DEC_PROP_2` decimal(13,4) DEFAULT NULL,
`BOOL_PROP_1` varchar(1) DEFAULT NULL,
`BOOL_PROP_2` varchar(1) DEFAULT NULL,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
CONSTRAINT `qrtz_SIMPROP_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Table structure for qrtz_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_TRIGGERS`;
CREATE TABLE `qrtz_TRIGGERS` (
`SCHED_NAME` varchar(120) NOT NULL,
`TRIGGER_NAME` varchar(200) NOT NULL,
`TRIGGER_GROUP` varchar(200) NOT NULL,
`JOB_NAME` varchar(200) NOT NULL,
`JOB_GROUP` varchar(200) NOT NULL,
`DESCRIPTION` varchar(250) DEFAULT NULL,
`NEXT_FIRE_TIME` bigint(13) DEFAULT NULL,
`PREV_FIRE_TIME` bigint(13) DEFAULT NULL,
`PRIORITY` int(11) DEFAULT NULL,
`TRIGGER_STATE` varchar(16) NOT NULL,
`TRIGGER_TYPE` varchar(8) NOT NULL,
`START_TIME` bigint(13) NOT NULL,
`END_TIME` bigint(13) DEFAULT NULL,
`CALENDAR_NAME` varchar(200) DEFAULT NULL,
`MISFIRE_INSTR` smallint(2) DEFAULT NULL,
`JOB_DATA` blob,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
KEY `IDX_QRTZ_T_J` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_T_JG` (`SCHED_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_T_C` (`SCHED_NAME`,`CALENDAR_NAME`),
KEY `IDX_QRTZ_T_G` (`SCHED_NAME`,`TRIGGER_GROUP`),
KEY `IDX_QRTZ_T_STATE` (`SCHED_NAME`,`TRIGGER_STATE`),
KEY `IDX_QRTZ_T_N_STATE` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
KEY `IDX_QRTZ_T_N_G_STATE` (`SCHED_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
KEY `IDX_QRTZ_T_NEXT_FIRE_TIME` (`SCHED_NAME`,`NEXT_FIRE_TIME`),
KEY `IDX_QRTZ_T_NFT_ST` (`SCHED_NAME`,`TRIGGER_STATE`,`NEXT_FIRE_TIME`),
KEY `IDX_QRTZ_T_NFT_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`),
KEY `IDX_QRTZ_T_NFT_ST_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_STATE`),
KEY `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
CONSTRAINT `qrtz_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `qrtz_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='存储已配置的 Trigger 的信息';
附上yml配置文件
spring:
datasource:
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.1.10:3306/quartz_db?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
username: root
password: root
quartz:
job-store-type: jdbc #数据库方式
jdbc:
initialize-schema: never #不初始化表结构
properties:
org:
quartz:
scheduler:
instanceId: AUTO #默认主机名和时间戳生成实例ID,可以是任何字符串,但对于所有调度程序来说,必须是唯一的 对应qrtz_scheduler_state INSTANCE_NAME字段
#instanceName: clusteredScheduler #quartzScheduler
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX #持久化配置
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate #仅为数据库制作了特定于数据库的代理
useProperties: false #以指示JDBCJobStore将JobDataMaps中的所有值都作为字符串,因此可以作为名称 - 值对存储而不是在BLOB列中以其序列化形式存储更多复杂的对象。从长远来看,这是更安全的,因为您避免了将非String类序列化为BLOB的类版本问题。
tablePrefix: qrtz_ #数据库表前缀
misfireThreshold: 60000 #在被认为“失火”之前,调度程序将“容忍”一个Triggers将其下一个启动时间通过的毫秒数。默认值(如果您在配置中未输入此属性)为60000(60秒)。
clusterCheckinInterval: 5000 #设置此实例“检入”*与群集的其他实例的频率(以毫秒为单位)。影响检测失败实例的速度。
isClustered: true #打开群集功能
threadPool: #连接池
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true