八股已死、场景当立(场景篇-分布式定时任务篇)
废话不多说,今天更新场景篇-分布式定时任务的知识点,做好了开始发车喽!
一、场景篇-分布式定时任务
1、Q:什么是分布式定时任务?它在微服务/分库分表体系中出现的原因是什么?
A:出现的原因如下:
- 分布式定时任务是指在 多台机器、多个进程 中按照预定时间或周期触发业务逻辑,并且保证 同一任务在同一调度周期内只执行一次。
- 在微服务拆分、分库分表后,单机的本地调度(Timer、ScheduledExecutorService)只能控制本机任务,无法保证全局唯一性,容易出现 重复执行、漏执行 的问题。因此需要一种 跨节点协同 的调度方案来实现全局一致的任务触发。
2、Q: 列举目前 Java 生态中常用的分布式定时任务框架,并说明它们的定位差异?
A:差异如下:
| 框架 | 核心实现方式 | 主要定位 |
|---|---|---|
| Quartz(集群模式) | 基于数据库行锁实现调度器的互斥,支持 Cron、SimpleTrigger | 功能最全、可自定义插件,适合 复杂调度 与 已有 Quartz 经验 的项目 |
| Elastic‑Job(Lite) | 基于 Zookeeper 实现分片、失效转移,内部仍使用 Quartz 作为调度引擎 | 轻量级、弹性伸缩、任务分片,适合 大规模并行处理 场景 |
| XXL‑Job | 调度中心使用 DB 锁(或 Quartz)实现任务唯一性,执行器通过 HTTP 拉取任务 | UI 管理友好、快速上手,适合 中小规模 的业务系统 |
| Spring Task + @Scheduled(配合分布式锁) | 依赖 Spring 的 TaskScheduler,结合 Redis/Zookeeper 分布式锁实现互斥 | 业务代码最简,适用于 低并发、对可靠性要求不高 的场景 |
| Timer / ScheduledExecutorService(单机) | JDK 原生实现,不适合 分布式 | 仅作对比基准 |
3、Q: Quartz 在集群环境下如何保证同一任务只被调度一次?请说明关键配置?
A:答案如下:
- 持久化 JobStore(
org.quartz.impl.jdbcjobstore.JobStoreTX)将触发器、作业信息写入同一数据库。 - 调度器在获取触发器时会 加行锁(
SELECT … FOR UPDATE),只有获取到锁的实例才能执行任务,从而实现 互斥。 - 必须配置
org.quartz.jobStore.isClustered = true、org.quartz.jobStore.clusterCheckinInterval(集群心跳)以及统一的 数据源。 - 通过
DisallowConcurrentExecution注解防止同一 JobDetail 在同一节点并发执行。
4、Q: Elastic‑Job 的核心原理是什么?它是如何实现任务分片与失效转移的?
A:答案如下:
- 注册中心:使用 Zookeeper 保存作业配置、分片信息以及节点注册信息。
- 分片机制:作业在启动时会读取
shardingTotalCount,将任务拆分为 N 份,每个实例只负责自己被分配的分片(shardingItemParameters)。 - 失效转移:当某节点失联(ZK 会话失效)后,注册中心会重新计算分片分配,将失效节点的分片重新分配给存活节点,保证任务不丢失。
