找回密码
 立即注册
首页 业界区 安全 Quartz定时任务持久化(服务重启后自动恢复) ...

Quartz定时任务持久化(服务重启后自动恢复)

讲怔 8 小时前
Quartz 定时任务持久化(重启后自动恢复)

声明: 本文内容由 ChatGPT 协助生成,仅作为个人学习与记录之用。
Quartz 默认使用 RAMJobStore(内存存储),服务重启后任务会丢失。
要让定时任务在重启后仍然有效,必须启用:JDBCJobStore(数据库持久化)
本文说明如何在 Spring Boot 项目中配置 Quartz 持久化,使任务存入数据库并在重启后自动恢复。
1. 启用 Quartz 持久化(application.yml)

示例配置:
  1. spring:
  2.   quartz:
  3.     job-store-type: jdbc   # 启用数据库持久化
  4.     jdbc:
  5.       initialize-schema: always   # 第一次启动自动建表,之后改为 never
  6.     properties:
  7.       org.quartz.scheduler.instanceName: QuartzScheduler
  8.       org.quartz.scheduler.instanceId: AUTO
  9.       org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
  10.       org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
  11.       org.quartz.jobStore.useProperties: false
  12.       org.quartz.jobStore.tablePrefix: QRTZ_
  13.       org.quartz.threadPool.threadCount: 10
复制代码
注意:

  • initialize-schema: always 只在第一次启动时用
第二次以后必须改为 never,避免自动重建表导致任务丢失。

  • 数据库需先创建好,Quartz 会自动建表(第一次)。
2. 初始化数据库(Quartz 表结构)

Quartz 内置表结构 SQL,可在 quartz-x.x.jar 中找到:
路径:
org/quartz/impl/jdbcjobstore/
根据数据库选择:
数据库SQL 文件MySQLtables_mysql_innodb.sqlPostgreSQLtables_postgres.sqlOracletables_oracle.sql执行后会生成 11 张表,例如:

  • QRTZ_JOB_DETAILS
  • QRTZ_TRIGGERS
  • QRTZ_CRON_TRIGGERS
  • QRTZ_SIMPLE_TRIGGERS
  • QRTZ_FIRED_TRIGGERS
  • QRTZ_SCHEDULER_STATE
  • QRTZ_LOCKS
...
这些表记录 Job/Trigger,实现持久化。
3. 可选:为 Job 启用持久化注解(存储 JobDataMap)

如果你的 Job 需要持久化任务状态,添加:
  1. @PersistJobDataAfterExecution
  2. @DisallowConcurrentExecution
  3. public class MyJob implements Job {
  4.     ...
  5. }
复制代码
功能说明:
注解作用@PersistJobDataAfterExecution执行后的JobDataMap数据状态写回数据库@DisallowConcurrentExecution任务串行执行,避免读写冲突@DisallowConcurrentExecution 的作用

防止同一个 Job 的多个实例并发执行。
也就是说:
Quartz 会等待当前 Job 执行完,才会执行下一次触发。
为什么需要这个注解?

Quartz 默认行为是:

  • 假设你的 Job 计划每 5 秒 执行一次
  • 但你的任务实际执行时间是 10 秒
那么:

  • Quartz 会在第 5 秒再并发启动一个 Job 实例
  • 第 10 秒再启动一个
  • 这样会导致同一个 Job 多实例并发执行
这在很多业务场景是危险的:

  • 写数据库时造成脏数据
  • 写文件导致冲突
  • 调接口重复提交
  • 修改共享变量时出并发问题
加上 @DisallowConcurrentExecution 后

Quartz 保证:
✔ 第一个任务没执行完
✔ Quartz 不会再启动第二个
✔ 任务之间严格串行执行
✔ 安全性强
@PersistJobDataAfterExecution 的作用

让你在 Job 里面修改的参数(JobDataMap)能被保存下来,下次执行还能继续用。
举个最简单的例子

你有个定时任务,每次执行想让计数器 count +1:
  1. int count = data.getInt("count");
  2. data.put("count", count + 1);
复制代码
如果 没有 @PersistJobDataAfterExecution:

  • 每次执行 count 都从 0 开始
  • 因为 Quartz 不会把你更新的值保存下来
如果 加上 @PersistJobDataAfterExecution:

  • count 会变成 1、2、3、4...
  • Quartz 会把更新后的值写回数据库
  • 服务重启后 count 也不会丢
只要你在 job 里对 JobDataMap 做写操作,想保存结果 → 就一定要加 @PersistJobDataAfterExecution + @DisallowConcurrentExecution。(防止并发造成的数据覆盖和丢失)
如果你只需要任务被保存,而不需要保存 JobDataMap,可以不加这两个注解。
4. 创建 Job 时必须设置 .storeDurably()

持久化 Job 的关键:
  1. JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
  2.         .withIdentity("job1", "group1")
  3.         .storeDurably()    // ★★★★★ 必须,Job 才会存入数据库
  4.         .build();
复制代码
不加 storeDurably() 的 Job 会被当成“临时 Job”,服务重启后会丢失。
Trigger 默认会持久化,不需要额外配置。
5. 服务重启后自动恢复机制

Quartz 启动时会自动从以下表中加载任务:

  • QRTZ_JOB_DETAILS
  • QRTZ_TRIGGERS
  • QRTZ_CRON_TRIGGERS / QRTZ_SIMPLE_TRIGGERS
无需额外代码。
6. 如何验证持久化是否生效


  • 创建一个 Job + Trigger
  • 启动服务 → 任务执行正常
  • 查看数据库 QRTZ_ 前缀的表,是否有记录
  • 停止服务
  • 再次启动
  • 任务是否自动恢复执行
如能恢复,即持久化成功。
参考文章:
【Quartz】(一)定时框架Quartz的持久化配置: https://blog.csdn.net/Jeffhan_java/article/details/123532049

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册