引言
前面的博文介绍了Quartz定时任务框架的相关知识,以及如何与Spring进行集成。本文将继续介绍Quartz的存储方式以及集群配置。
存储方式
一、存储方式 RAMJobStore和JDBCJobStore
Quartz提供两种基本作业存储类型。第一种类型叫做RAMJobStore,第二种类型叫做JDBC作业存储。在默认情况下Quartz默认使用RAMJobStore存储方式将任务调度的运行信息保存在内存中,这种方法提供了最佳的性能,因为内存中数据访问最快且配置容易。不足之处是缺乏数据的持久性,当程序中途停止或系统崩溃时,所有运行的信息都会丢失。但是使用JDBCJobStore 可以通过调整属性,将调度信息保存到数据库中,当系统崩溃或者停止再运行后,任务的调度进行将从中断处得到回复并继续运行。可以持久化的运行调度任务。
对比图:
类型 | 优点 | 缺点 |
---|---|---|
RAMJobStore(默认) | 不要外部数据库,配置容易,运行速度快 | 因为调度程序信息是存储在被分配给JVM的内存里面,所以,当应用程序停止运行时,所有调度信息将被丢失。另外因为存储到JVM内存里面,所以可以存储多少个Job和Trigger将会受到限制 |
JDBCJobStore | 支持集群,因为所有的任务信息都会保存到数据库中,可以控制事物,还有就是如果应用服务器关闭或者重启,任务信息都不会丢失,并且可以恢复因服务器关闭或者重启而导致执行失败的任务 | 运行速度的快慢取决与连接数据库的快慢 |
二、设置 JDBCJobStore
1、创建quartz数据库表
在应用程序中设置使用 JDBCJobStore 需要两步:首先必须创建作业仓库使用的数据库表。 JDBCJobStore与所有主流数据库都兼容,而且quartz提供了一些了创建表的SQL脚本。
SQL脚本的位置:
可以在 下载的jar包中进行解压缩获取,例如maven仓库中找到jar包:
解压缩打开之后,在quartz-2.3.0.jar\org\quartz\impl\jdbcjobstore下,针对你需要的sql文件执行即可。
我所使用的数据库为mysql数据库,所以新建quartz数据库执行tables_mysql_innodb.sql文件刷新后得到结果如下,共计十一张表。
2、创建quartz数据库运行sql导入库表之后,在quartz.properties中指定 JDBCJobStore 属性。
配置文件如图:
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
# Using RAMJobStore
## if using RAMJobStore, please be sure that you comment out the following
## - org.quartz.jobStore.tablePrefix,
## - org.quartz.jobStore.driverDelegateClass,
## - org.quartz.jobStore.dataSource
# org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
# Using JobStoreTX
## Be sure to run the appropriate script(under docs/dbTables) first to create tables
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
# Configuring JDBCJobStore with the Table Prefix
org.quartz.jobStore.tablePrefix = QRTZ_
# Using DriverDelegate
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# Using datasource
org.quartz.jobStore.dataSource = qzDS
# Define the datasource to use
org.quartz.dataSource.qzDS.driver = com.mysql.cj.jdbc.Driver
org.quartz.dataSource.qzDS.URL = jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
org.quartz.dataSource.qzDS.user = root
org.quartz.dataSource.qzDS.password = 123456
org.quartz.dataSource.qzDS.maxConnections = 30
3、spring-quartz.xml文件如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--job-->
<!-- <bean id="MyQuartzJob" class="com.hbc.springboot.quartz.MyQuartzJob"></bean>-->
<!--创建JobDetail-->
<bean id= "jobDetail"
class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<!--指定任务类-->
<property name="jobClass" value="com.hbc.springboot.quartz.MyQuartzJob"></property>
<!--当Job在没有可以使用的trigger的情况下 不删除-->
<property name="durability" value="true"></property>
</bean>
<!--注意spring quartz整合 一个trigger只可以绑定一个JobDetail 一个jobDetail可以被多个Trigger所使用-->
<bean id="trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!--绑定JobDetail-->
<property name="jobDetail" ref="jobDetail"></property>
<property name= "cronExpression" value="0-30 * * * * ?"></property>
</bean>
<bean id="trigger1"
class= "org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!--绑定JobDetail-->
<property name="jobDetail" ref="jobDetail"></property>
<property name="cronExpression" value="45-55 * * * * ?"></property>
</bean>
<!--注册trigger -->
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<!--引入配置文件quartz.properties -->
<property name="configLocation" value="classpath:quartz.properties"/>
<property name= "triggers">
<list>
<ref bean= "trigger"></ref>
<ref bean= "trigger1"></ref>
</list>
</property>
</bean>
</beans>
4、任务类 如下:
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.util.Date;
/**
* 定义要执行的任务内容
*/
public class MyQuartzJob implements Job{
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//输出系统当前时间
System.err.println("系统当前时间为+"+new Date());
}
}
5、测试
使用Spring工厂进行测试
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringQuartzTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext classPathXmlApplicationContext
= new ClassPathXmlApplicationContext("spring-quartz.xml");
}
}
6、结果可以看到JDBCJobStore持久化配置成功
并看到成功打印系统时间
集群支持
一、原理
虽然单个Quartz实例能给予你很好的Job调度能力,但它不能满足典型的企业需求,如可伸缩性、高可靠性满足。假如你需要故障转移的能力并能运行日益增多的Job, Quartz集群势必成为你应用的一部分了。使用Quartz的集群能力可以更好的支持你的业务需求,并且即使是其中一台机器在最糟的时间崩溃了也能确保所有的Job得到执行。
一个Quartz集群中的每个节点是一个独立的 Quartz应用,它又管理着其他的节点。意思是你必须对每个节点分别启动或停止。不像许多应用服务器的集群,独立的Quartz节点并不与另一其的节点或是管理节点通信。Quartz应用是通过数据库表来感知到另一应用的。
下图:表示了每个节点直接与数据库通信,若离开数据库将对其他节点一无所知
二、搭建步骤
1、准备配置文件 quartz.properties
# 调度标识名集群中每一个实例都必须使用相同的名称
org.quartz.scheduler.instanceName=TestScheduler
# ID设置为自动获取 每一个必须不同
org.quartz.scheduler.instanceId: auto
org.quartz.scheduler.skipUpdateCheck=true
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
# 线程数量
org.quartz.threadPool.threadCount = 10
# 线程优先级
org.quartz.threadPool.threadPriority = 5
# 自创建父线程
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
# 默认配置,数据保存到内存
# org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
# 持久化配置
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.isClustered = true
# 数据库表前缀
org.quartz.jobStore.tablePrefix = QRTZ_
#设置为TRUE不会出现序列化非字符串类到 BLOB 时产生的类版本问题
org.quartz.jobStore.useProperties = true
# Using DriverDelegate
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# Using datasource
org.quartz.jobStore.dataSource = qzDS
# Define the datasource to use
org.quartz.dataSource.qzDS.driver = com.mysql.cj.jdbc.Driver
org.quartz.dataSource.qzDS.URL = jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
org.quartz.dataSource.qzDS.user = root
org.quartz.dataSource.qzDS.password = 123456
org.quartz.dataSource.qzDS.maxConnections = 30
2、spring-quartz.xml以及任务类和上面一样,启动Spring工厂测试即可。
我们可以看到现在采用JDBCJobStore持久化存储方式,并且集群配置成功。
总结
以上就是定时任务框架Quartz的存储方式持久化与集群配置,文章步骤详细,操作简单,逐步按照教程操作即可。
另外对quartz库表进行相关说明:
表名称 | 说明 |
---|---|
qrtz_blob_triggers | Trigger作为Blob类型存储(用于Quartz用户用JDBC创建他们自己定制的Trigger类型,JobStore 并不知道如何存储实例的时候) |
qrtz_calendars | 以Blob类型存储Quartz的Calendar日历信息, quartz可配置一个日历来指定一个时间范围 |
qrtz_cron_triggers | 存储Cron Trigger,包括Cron表达式和时区信息。 |
qrtz_fired_triggers | 存储与已触发的Trigger相关的状态信息,以及相联Job的执行信息 |
qrtz_job_details | 存储每一个已配置的Job的详细信息 |
qrtz_locks | 存储程序的非观锁的信息(假如使用了悲观锁) |
qrtz_paused_trigger_graps | 存储已暂停的Trigger组的信息 |
qrtz_scheduler_state | 存储少量的有关 Scheduler的状态信息,和别的 Scheduler 实例(假如是用于一个集群中) |
qrtz_simple_triggers | 存储简单的 Trigger,包括重复次数,间隔,以及已触的次数 |
qrtz_triggers | 存储已配置的 Trigger的信息 |
qrzt_simprop_triggers |