做后端总绕不开“定时任务”:对账、数据清理、发券、补偿、同步……
但一到微服务/多实例部署,很多同学就开始踩坑:同一任务在每台机器都跑一遍(重复执行)、某台机器挂了任务就断了(单点故障)、任务太久把调度线程卡死(后面全堵)……
“单机闹钟”还是“分布式调度”?
- • 单机定时任务:应用只部署 1 台(或明确只允许 1 台跑任务)。✅ 这类任务追求“简单、快、少依赖”。
- • 分布式/集群定时任务:应用部署 N 台、会扩缩容、会故障转移。✅ 这类任务追求“只执行一次、可观测、可运维”。
在集群里,单机方案默认=每台都执行,不做控制就会重复跑。
三个方案
1)@Scheduled:Spring 自带的轻量方案(单机优先)
就是给方法加个注解:cron / fixedRate / fixedDelay,立刻能跑。 优点:零额外中间件、和 Spring 生态贴合。
短板:天生不管集群(多实例就多份闹钟)、基本没可视化、想改规则通常要走发布流程。
提醒:同一个方法可以声明多个 @Scheduled,触发器彼此独立,甚至可能并发/连续触发。
2)Quartz:老牌、灵活、可集群(但“偏框架”)
Quartz 的核心是 Scheduler(调度器)+ Job(任务)+ Trigger(触发器),能力非常全。 它也支持集群,但需要 JDBC JobStore + 共享数据库 + 锁 来保证同一触发点只跑一次:多个节点抢到锁的那个节点执行。
优点:能力强、模型成熟、可深度定制。 短板:原生不带管理后台,集群配置/运维成本更高。
3)XXL-Job:开箱即用的分布式调度平台(偏“产品”)
XXL-Job 更像“带后台的调度系统”:
- • Web 页面直接 CRUD 任务,修改后即时生效
- • 调度中心、执行器都支持集群 HA
- • 支持分片广播、故障转移、在线日志等
- • 通过 DB 锁保证“一次调度只触发一次执行”
优点:上手快、可视化强、分布式能力齐。 局限:任务模型/运行方式相对固定,超深度定制可能要读源码或二开。
核心维度对比(快速看懂版)
| 维度 | @Scheduled | Quartz | XXL-Job |
|---|---|---|---|
| 依赖/引入成本 | 最低(Spring 内置) | 中(引入框架 + 持久化/集群要配 DB) | 中(调度中心 + 执行器) |
| 可视化/运维 | 基本没有 | 原生没有(通常要自建) | 自带 Web 管理后台 |
| 集群下“只跑一次” | 不支持(需你自己加锁/选主) | 支持(JDBC 集群 + DB 锁) | 原生支持(DB 锁一致性) |
| 动态修改规则 | 通常要发布/重启 | 支持 API 动态改 Trigger | 页面改完即时生效 |
| 适合场景 | 单机、小任务、快速实现 | 老系统/强定制/复杂触发需求 | 分布式、想省运维、团队人手不多 |
常见“坑点”与避坑建议
A. @Scheduled 的坑(最容易被忽略)
-
- 默认调度线程少,任务会互相堵 Spring Boot 默认的调度器(ThreadPoolTaskScheduler)默认只有 1 个线程,一个任务跑久了,后面的定时任务可能排队等。 ✅ 建议:显式配置 scheduling 线程池大小(至少让“慢任务”不拖死全局)。
-
- fixedRate vs fixedDelay 用错,节奏就乱了
-
• fixedRate:按“固定频率”触发(更像每隔 X 秒就开始一次)
-
• fixedDelay:按“上一次结束后再等 X 秒” ✅ 建议:想“准点”用 fixedRate/cron;想“串行且留间隔”用 fixedDelay。
-
- 集群重复执行 多实例部署时,每台都会触发。 ✅ 建议(择一):分布式锁、Leader 选举、或把任务迁移到分布式调度平台。
B. Quartz 的坑(集中在集群与稳定性)
-
- 集群必须用 JDBC JobStore + 共享 DB Quartz 的集群依赖共享数据库与锁机制;而且节点越多,锁竞争越明显,文档也提醒扩到很多节点性能会下降。 ✅ 建议:Quartz 集群别盲目加节点,先评估调度密度与 DB 承载。
-
- 时间不同步会出大事 官方明确提醒:集群机器时钟必须同步到“秒级”。 ✅ 建议:NTP/chrony 做好时间同步,别拿“差几秒没事”赌系统稳定。
-
- Misfire(错过触发)没理解,任务可能“补跑/不跑” Quartz 文档解释:当持久化 Trigger 因为调度器关闭或线程不足等原因错过触发时间,就会发生 misfire,并按 misfire 策略处理。 ✅ 建议:对关键任务明确配置 misfire 策略,别完全依赖默认“smart policy”。
C. XXL-Job 的坑(集中在“平台化落地”)
-
- 调度中心/执行器尽量版本一致 这是大量团队的真实经验:版本不一致时容易出现协议/字段不匹配等“玄学问题”。 ✅ 建议:统一版本发布,至少保持同一大版本。
-
- 分片/路由策略选错,容易负载不均 XXL-Job 支持“分片广播”“故障转移”等路由能力 ✅ 建议:
-
• 大批量处理:优先分片广播 + 设计好分片参数
-
• 强可用:用故障转移,但要关注健康检查与超时
-
- 日志与数据留存 它支持在线 Rolling 日志查看 ✅ 建议:配好日志保留/归档策略,别让“任务日志”变成数据库/磁盘隐形炸弹。
3 条“通用铁律”
-
- 任务幂等性:同一任务跑两次,也不能把钱扣两次/发两次券。
-
- 超时 + 告警:慢任务要能被发现、被终止或降级。
-
- 时间同步:尤其是集群调度,机器时间不准会让问题变得非常难排查。