在单体应用时代写定时任务简直是送分题。在 Spring 里打个Scheduled(cron 0 0 2 * * ?)每天凌晨两点代码准时执行。但当你把这套代码放到微服务集群里部署了 10 台机器灾难降临了到了凌晨 2 点10 台机器同时触发定时任务同一个用户的账户里被重复发了 10 张优惠券老板连夜把你叫醒财务让你赔钱。为了解决“重复执行”的问题架构师们开始了定时任务的演进之路。 一、中小厂的王者XXL-JOB 与数据库锁的上限既然不能让 10 台机器一起干那就选出一个“倒霉蛋”去干。这是目前业界最流行的分布式调度框架XXL-JOB的核心逻辑在大多数常规场景下。XXL-JOB 有一个专门的调度中心。到了时间点调度中心会去拉取你的集群列表然后通过“轮询”或“一致性 Hash”策略挑出其中一台机器把任务发给它“今天这 10 万个订单就交给你来扫描了”致命瓶颈单机的物理极限如果数据量不是 10 万而是1000 万呢被选中的那台机器看着 1000 万条数据陷入了沉思。它疯狂查库、处理CPU 满载跑了整整 2 个小时还没跑完。而此时集群里的另外 9 台机器在干嘛它们在旁边喝茶看戏CPU 占用率 0%。这就是集中式调度最大的痛点算力闲置单机遭遇性能天花板。⚔️ 二、算力大爆发ElasticJob 与“分片”哲学为了打破单机天花板当当网开源了极其硬核的分布式调度框架ElasticJob现已捐赠给 Apache。它引入了一个在数据库领域非常熟悉的词分片 (Sharding)。既然 1 台机器干不完那我就把 1000 万数据切成 10 份让 10 台机器同时并发干1. 去中心化的架构Zookeeper 坐镇ElasticJob 极其激进地干掉了“中心化的调度服务端”。它只依赖Zookeeper (ZK)作为注册中心。所有的业务机器启动时都会向 ZK 报到。ZK 会记录下当前有几台机器在线。2. 神奇的分片路由策略假设我们将任务设置为10 个分片分片项为0, 1, 2, 3, 4, 5, 6, 7, 8, 9。当前集群有3 台机器(A, B, C)。ElasticJob 会通过 ZK 瞬间完成分配方案机器 A 分到0, 1, 2, 3机器 B 分到4, 5, 6机器 C 分到7, 8, 9到了凌晨 2 点3 台机器同时触发任务但它们在查数据库时会带上自己的分片参数。比如机器 A 的 SQL 是这样的SELECT * FROM order WHERE status 未支付 AND MOD(id, 10) IN (0, 1, 2, 3)。震撼的结果1000 万条数据被完美切割3 台机器同时狂飙原本需要 2 小时的任务现在只需要 20 分钟如果老板嫌慢你只需要再加 7 台机器时间还能再缩短几倍️ 三、高可用极致拉扯机器挂了怎么办大厂架构师永远会问一个问题“如果跑着跑着机器挂了怎么办”在 ElasticJob 的世界里Zookeeper 扮演了极其冷酷的监工角色。场景推演如果机器 B拿着分片 4, 5, 6突然断电宕机了。心跳丢失ZK 瞬间发现机器 B 与自己断开了临时节点连接。触发重新分片 (Resharding)ZK 立刻在集群里广播“兄弟们先停一下B 阵亡了我们重新分家产”瞬间接管剩下的机器 A 和 C 重新分配这 10 个分片。机器 A 分到0, 1, 2, 3, 4机器 C 分到5, 6, 7, 8, 9继续执行A 和 C 带着新的分片参数无缝接管了机器 B 没干完的活继续执行。这就是 ElasticJob 最迷人的地方极致的弹性扩缩容与故障转移 (Failover)。 四、总结技术选型的权衡之道在真实的业务战场上没有绝对的碾压只有最合适的选择。XXL-JOB (实用主义者)自带 Web UI 管理后台轻量级支持动态改 Cron 表达式能满足 90% 互联网公司的日常需求。虽然它也支持分片广播但底层重度依赖数据库锁。ElasticJob (重型装甲车)重度依赖 Zookeeper缺少花里胡哨的管理后台但它的去中心化设计和极致的分片模型是处理金融级、海量级批处理任务的绝对王者。一句话总结当你只面对几十万数据时请用 XXL-JOB 享受开发的便捷但当你的定时任务每次要扫过亿行表、甚至要把任务分发给 100 台机器并行狂奔时ElasticJob 的分片魔法才是你唯一的救命稻草。