定时任务从 Quartz 搬出来的契机
老系统用 Quartz 集群,任务一多就出现重复触发,两台机器各跑一遍,数据算重了还得手工修。排查发现是 Quartz 的数据库锁在高峰期没兜住。今年做调度中台,我在 XXL-JOB 和 Elastic-Job 之间选,两者都能解决分布式场景,但设计取向不同,我把核心差异理了一遍,顺手做了一次选型对比。
分片广播
大数据量任务要拆到多台机器并行。XXL-JOB 的分片很直白,执行器拿到分片号和总分片数,自己决定处理哪部分:
@XxlJob("syncOrder")
public void syncOrder() {
int shard = XxlJobHelper.getShardIndex();
int total = XxlJobHelper.getShardTotal();
// 只处理 id % total == shard 的数据
orderMapper.syncByMod(shard, total);
}
Elastic-Job 用 ShardingContext 同样能拿到分片项,概念一致。区别在调度器:XXL-JOB 自带调度中心(Admin),任务配置在界面上;Elastic-Job 依赖 ZooKeeper 做协调,分片由 ZK 分配。广播模式下两者都能把任务推到所有执行器,我们用来做配置刷新。
失败重试
XXL-JOB 在 Admin 上配重试次数,失败自动重跑,重试间隔可调;Elastic-Job 通过配置 shardingItemParameters 和监听器做失败转移(failover),某台机器挂了,它的分片会被别的机器接管。我们电商对账任务用 failover,单机宕机不影响整体进度,这一点在凌晨跑大批量时很关键——曾经有台机器 OOM,任务照常跑完。
执行器部署
XXL-JOB 的执行器是个内嵌 SDK 的 Spring Boot 应用,注册到 Admin,部署简单:
xxl:
job:
admin-addresses: http://xxl-admin:8080
executor:
appname: order-executor
port: 9999
Elastic-Job 要起一套 ZooKeeper 集群,再引 elasticjob-lite 依赖,运维门槛高一点。小团队我一般推 XXL-JOB,因为要的是"今天就能跑"。但 Elastic-Job 的分片策略更灵活,支持脚本任务和更细的失效转移。
我们的取舍
| 维度 | XXL-JOB | Elastic-Job |
|---|---|---|
| 依赖 | MySQL | ZooKeeper |
| 控制台 | 自带 Web | 无,靠代码 |
| 分片策略 | 简单取模 | 灵活、可自定义 |
| 上手成本 | 低 | 中高 |
小结
XXL-JOB 胜在上手快、自带控制台、适合绝大多数业务;Elastic-Job 强在基于 ZK 的强一致调度和弹性分片,适合对调度可靠性要求极高的场景。选哪个看团队有没有 ZooKeeper 运维能力。我们最终用 XXL-JOB,把调度中心独立部署,执行器随业务服务发布,半天上手。