1、Quartz存储
Quartz的存储方式有两种:RAMJobStore和JDBCJobStore。从名字就能看出,存在内存中和存在数据库当中。在默认情况下Quartz将任务调度的运行信息保存在内存中,这种方法提供了最佳的性能,因为内存中数据访问最快。不足之处是缺乏数据的持久性,当程序路途停止或系统崩溃时,所有运行的信息都会丢失。
比如我们希望安排一个执行100次的任务,如果执行到50次时系统崩溃了,系统重启时任务的执行计数器将从0开始。如果持久化任务调度信息,Quartz允许你通过调整其属性文件,将这些信息保存到数据库中。使用数据库保存任务调度信息后,即使系统崩溃后重新启动,任务的调度信息将得到恢复。如前面所说的例子,执行50次崩溃后重新运行,计数器将从51开始计数。使用了数据库保存信息的任务称为持久化任务。
类型 | 优点 | 缺点 |
RAMJobStore | 不要外部数据库,配置容易,运行速度快 | 因为调度程序信息是存储在被分配给JVM的内存里面,所以,当应用程序停止运行时,所有调度信息将被丢失。另外因为存储到JVM内存里面,所以可以存储多少个Job和Trigger将会受到限制 |
JDBC作业存储 | 支持集群,因为所有的任务信息都会保存到数据库中,可以控制事物,还有就是如果应用服务器关闭或者重启,任务信息都不会丢失,并且可以恢复因服务器关闭或者重启而导致执行失败的任务 | 运行速度的快慢取决与连接数据库的快慢 |
1.1 RAMJobStore存储
使用RamJobStore时,如果未设置Quartz的配置文件quartz.properties,则编写Quartz程序默认使用RAMJobStore;如果需要在quartz.properties中进行设置"org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore",可参考如下:
#============================================================================
# Configure Main Scheduler Properties
#============================================================================
org.quartz.scheduler.instanceName: TestScheduler
org.quartz.scheduler.instanceId: AUTO
org.quartz.scheduler.skipUpdateCheck: true
#============================================================================
# Configure ThreadPool
#============================================================================
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 3
org.quartz.threadPool.threadPriority: 5
#============================================================================
# Configure JobStore
#============================================================================
org.quartz.jobStore.misfireThreshold: 60000
#指明了存储方式是RAMJobStore
org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
#============================================================================
# Configure Plugins
#============================================================================
org.quartz.plugin.triggHistory.class: org.quartz.plugins.history.LoggingJobHistoryPlugin
org.quartz.plugin.jobInitializer.class: org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
org.quartz.plugin.jobInitializer.fileNames: quartz_data.xml
org.quartz.plugin.jobInitializer.failOnFileNotFound: true
org.quartz.plugin.jobInitializer.scanInterval: 120
org.quartz.plugin.jobInitializer.wrapInUserTransaction: false
1.2 JDBCJobStore存储
JDBCJobStore是将Quartz涉及的Job、Trigger、Scheduler通过JDBC存储到数据库中。与RAMJobStore相比,JDBCJobStore的配置稍微复杂些,且效率相对低。但其优点在于可以将Quartz的运行信息持久化。JDBCJobStore基于对所有的数据库有效,包括:Oracle, PostgreSQL, MySQL, MS SQL Server, HSQLDB, DB2等。当使用JDBCJobStore时,需要设置配置文件、以及创建相关的数据库表(数据库表在官网下载的quartz的目录docs\dbTables目录下有各个数据库相关的建表脚本)。
1.2.1 设置quartz.properties
在quartz.preperties中设置JDBCJobStore,只需设置"org.quartz.jobStore.class = org.quartz.simpl.JDBCJobStore",以及设置对应的数据表即可。具体配置信息参考如下(下表为mysql的配置信息):
#============================================================================
# Configure Main Scheduler Properties
#============================================================================
#调度标识名 集群中每一个实例都必须使用相同的名称 (区分特定的调度器实例)
org.quartz.scheduler.instanceName: DefaultQuartzScheduler
#ID设置为自动获取 每一个必须不同 (所有调度器实例中是唯一的)
org.quartz.scheduler.instanceId: AUTO
org.quartz.scheduler.skipUpdateCheck: true
#============================================================================
# Configure ThreadPool
#============================================================================
#ThreadPool 实现的类名
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
#线程数量
org.quartz.threadPool.threadCount: 50
##线程优先级(threadPriority 属性的最大值是常量java.lang.Thread.MAX_PRIORITY,等于10。最小值为常量 java.lang.Thread.MIN_PRIORITY,为1)
org.quartz.threadPool.threadPriority: 5
#自创建父线程
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
#============================================================================
# Configure JobStore
#============================================================================
#数据保存方式为持久化
org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#设置为TRUE不会出现序列化非字符串类到 BLOB 时产生的类版本问题
org.quartz.jobStore.useProperties: false
#表的前缀
org.quartz.jobStore.tablePrefix: QRTZ_
#数据库别名
org.quartz.jobStore.dataSource: qzDS
#是否加入集群 true 为集群 false不是集群
org.quartz.jobStore.isClustered: true
#调度实例失效的检查时间间隔
org.quartz.jobStore.clusterCheckinInterval = 60000
#容许的最大作业延长时间,触发器超时时间(ms),超过这个时间,按照触发器的misfire策略处理
org.quartz.jobStore.misfireThreshold: 60000
#============================================================================
# Configure Datasources
#============================================================================
# 设置数据源
org.quartz.dataSource.qzDS.driver:com.mysql.jdbc.Driver
org.quartz.dataSource.qzDS.URL:jdbc:mysql://localhost:3306/SSM_quartz
org.quartz.dataSource.qzDS.user:root
org.quartz.dataSource.qzDS.password:123
#org.quartz.dataSource.qzDS.maxConnection:10
#============================================================================
# Configure Plugins
#============================================================================
org.quartz.plugin.shutdownHook.class: org.quartz.plugins.management.ShutdownHookPlugin
org.quartz.plugin.shutdownHook.cleanShutdown: true
#org.quartz.plugin.triggHistory.class: org.quartz.plugins.history.LoggingJobHistoryPlugin
注意:
org.quartz.jobStore.class:属性为 JobStoreTX,将任务持久化到数据中。因为集群中节点依赖于数据库来传播 Scheduler 实例的状态,你只能在使用 JDBC JobStore 时应用 Quartz 集群。这意味着你必须使用 JobStoreTX 或是 JobStoreCMT 作为 Job 存储;你不能在集群中使用 RAMJobStore。
org.quartz.jobStore.isClustered:属性为 true,你就告诉了 Scheduler 实例要它参与到一个集群当中。这一属性会贯穿于调度框架的始终,用于修改集群环境中操作的默认行为。
org.quartz.jobStore.clusterCheckinInterval:属性定义了Scheduler 实例检入到数据库中的频率(单位:毫秒)。Scheduler 检查是否其他的实例到了它们应当检入的时候未检入;这能指出一个失败的 Scheduler 实例,且当前 Scheduler 会以此来接管任何执行失败并可恢复的 Job。通过检入操作,Scheduler 也会更新自身的状态记录。clusterChedkinInterval 越小,Scheduler 节点检查失败的 Scheduler 实例就越频繁。默认值是 15000 (即15 秒)。
1.2.2 创建数据表
将数据库及表的创建写入sql文件,导入即可。相关的表如下所示:
表名 | 说明 |
QRTZ_FIRED_TRIGGERS | 存存放已触发的触发器 |
QRTZ_PAUSED_TRIGGER_GRPS | 存放暂停掉的触发器 |
QRTZ_SCHEDULER_STATE | 调度器状态 |
QRTZ_LOCKS | 存储程序的悲观锁的信息 |
QRTZ_SIMPLE_TRIGGERS | 简单触发器的信息 |
QRTZ_SIMPROP_TRIGGERS |
|
QRTZ_CRON_TRIGGERS | 存放cron类型的触发器 |
QRTZ_BLOB_TRIGGERS | 以Blob 类型存储的触发器 |
QRTZ_TRIGGERS | 触发器的基本信息 |
QRTZ_JOB_DETAILS | 存放一个jobDetail信息 |
QRTZ_CALENDARS | 存放日历信息 |
1.2.3 JDBC插入表顺序
主要的JDBC操作类,执行sql顺序。
Simple_trigger 类型:插入顺序
qrtz_job_details —> qrtz_triggers —> qrtz_simple_triggers——>qrtz_fired_triggers
Cron_Trigger 类型:插入顺序
qrtz_job_details —> qrtz_triggers —> qrtz_cron_triggers —> qrtz_fired_triggers
2、Quartz集群
Quartz集群架构如下,集群中的每个节点是一个独立的Quartz应用,且独立的Quartz节点并不与另一节点通信,而是通过相同的数据库表来感知另一Quartz应用。简而言之,Quartz应用、数据库支撑、多节点部署即可搭建起Quartz的应用集群。
Quartz集群共用同一个数据库,由数据库中的数据来确定任务是否正在执行,如果该任务正在执行,则其他服务器就不能去执行该调度任务。Quartz集群的特点如下:
1) 持久化
Quartz可以将调度器scheduler、触发器trigger以及任务Job的运行时信息存储至数据库中,采用JDBCJobStore,如果服务器异常时,可以基于数据库中的存储信息进行任务恢复。
2) 高可用性
如果相关服务器节点挂掉的话,集群的其他节点则会继续执行相关任务。
3) 伸缩性
如果集群中的节点数过少,导致相关任务无法及时执行,可以增加额外的服务器节点,只需将其他节点上的脚本及配置信息拷贝至新部署的节点上运行即可。
4) 负载均衡
Quartz使用随机的负载均衡算法,任务job是以随机的方式由不同的节点上Scheduler实例来执行。但当前不存在一个方法指派一个Job到集群中的特定节点。
参考文章地址: