Quartz
Quartz 是 Java 生态中最成熟的任务调度框架,支持 Cron 表达式、简单触发器、集群调度(基于数据库锁),可嵌入任何 Java 应用。适合单体或小规模集群的定时任务场景。
分布式大规模场景推荐 XXL-Job(有 Web 管控台、执行日志、失败重试等)。
核心概念
| 概念 | 说明 |
|---|---|
| Job | 任务逻辑,实现 execute() 方法 |
| JobDetail | Job 的描述(名称、组、数据) |
| Trigger | 触发规则(何时执行) |
| Scheduler | 调度器,管理 Job 和 Trigger |
| JobDataMap | 向 Job 传递参数的 Map |
Spring Boot 集成
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>定义 Job
@Component
public class OrderCleanJob implements Job {
@Autowired
private OrderService orderService;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
String param = context.getMergedJobDataMap().getString("param");
orderService.cleanExpiredOrders();
}
}注册 JobDetail 和 Trigger
@Bean
public JobDetail orderCleanJobDetail() {
return JobBuilder.newJob(OrderCleanJob.class)
.withIdentity("orderCleanJob", "cleanGroup")
.usingJobData("param", "value")
.storeDurably()
.build();
}
@Bean
public Trigger orderCleanTrigger(JobDetail orderCleanJobDetail) {
return TriggerBuilder.newTrigger()
.forJob(orderCleanJobDetail)
.withIdentity("orderCleanTrigger", "cleanGroup")
.withSchedule(CronScheduleBuilder.cronSchedule("0 0 2 * * ?"))
.build();
}触发器类型
CronTrigger
CronScheduleBuilder.cronSchedule("0 0/30 * * * ?") // 每 30 分钟SimpleTrigger(固定间隔)
Trigger trigger = TriggerBuilder.newTrigger()
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(30)
.repeatForever())
.build();Cron 表达式
格式:秒 分 时 日 月 周 [年]
| 表达式 | 含义 |
|---|---|
0 0 2 * * ? | 每天凌晨 2:00 |
0 0/30 * * * ? | 每 30 分钟 |
0 0 9-18 * * MON-FRI | 工作日 9~18 点每小时整点 |
0 0 12 ? * WED | 每周三 12:00 |
0 0 0 1 * ? | 每月 1 日 0:00 |
0 15 10 L * ? | 每月最后一天 10:15 |
特殊字符:*(所有)、?(日/周中不指定)、/(步长)、L(最后)、#(第几个星期几)
@Scheduled 注解(简化方案)
Spring 内置,无需 Quartz 依赖,适合简单单机场景:
@Component
@EnableScheduling
public class SimpleTask {
@Scheduled(cron = "0 0 2 * * ?")
public void cleanOrders() { ... }
@Scheduled(fixedRate = 30000) // 固定频率(ms),上次开始后计时
public void syncData() { ... }
@Scheduled(fixedDelay = 10000) // 固定延迟(ms),上次结束后计时
public void checkStatus() { ... }
}集群模式
Quartz 集群依赖数据库行锁保证同一时刻只有一个节点执行任务。
建表
官方提供建表 SQL(tables_mysql_innodb.sql):
| 表名 | 作用 |
|---|---|
QRTZ_JOB_DETAILS | Job 详情 |
QRTZ_TRIGGERS | 触发器 |
QRTZ_CRON_TRIGGERS | Cron 触发器 |
QRTZ_FIRED_TRIGGERS | 正在执行的触发器 |
QRTZ_LOCKS | 集群锁 |
QRTZ_SCHEDULER_STATE | 节点心跳 |
配置
spring:
quartz:
job-store-type: jdbc
jdbc:
initialize-schema: never # 手动建表
properties:
org.quartz.scheduler.instanceId: AUTO
org.quartz.jobStore.isClustered: true
org.quartz.jobStore.clusterCheckinInterval: 10000Misfire(错过触发)处理
任务执行超时或宕机导致触发时间已过:
// CronTrigger
CronScheduleBuilder.cronSchedule("0 0 2 * * ?")
.withMisfireHandlingInstructionDoNothing() // 忽略,等下次
.withMisfireHandlingInstructionFireAndProceed() // 立即执行一次
// SimpleTrigger
SimpleScheduleBuilder.simpleSchedule()
.withMisfireHandlingInstructionFireNow() // 立即执行动态管理任务
@Autowired
private Scheduler scheduler;
// 新增
scheduler.scheduleJob(jobDetail, trigger);
// 暂停 / 恢复
scheduler.pauseJob(JobKey.jobKey("orderCleanJob", "cleanGroup"));
scheduler.resumeJob(JobKey.jobKey("orderCleanJob", "cleanGroup"));
// 修改 Cron
TriggerKey key = TriggerKey.triggerKey("orderCleanTrigger", "cleanGroup");
CronTrigger newTrigger = TriggerBuilder.newTrigger()
.withSchedule(CronScheduleBuilder.cronSchedule("0 0 3 * * ?"))
.build();
scheduler.rescheduleJob(key, newTrigger);
// 删除
scheduler.deleteJob(JobKey.jobKey("orderCleanJob", "cleanGroup"));Quartz vs XXL-Job
| 维度 | Quartz | XXL-Job |
|---|---|---|
| 部署方式 | 嵌入应用 | 独立调度中心 + 执行器 |
| 管控台 | 无 | 内置 Web UI |
| 执行日志 | 无 | 完整日志查询 |
| 失败重试 | 需自行实现 | 内置 |
| 分片执行 | 不支持 | 支持分片广播 |
| 路由策略 | 无 | 轮询、故障转移等多种 |
| 适用规模 | 单体 / 小集群 | 中大型分布式系统 |