定时任务方案选择指南:crontab、K8s CronJob、Airflow、XXL-JOB

项目刚开始,定时任务少,crontab -e 一行搞定。没人纠结------能跑就行。

后来任务多了。三个变十几个,散在不同机器上。没人知道哪个在跑、哪个停了、哪个重复了。要补跑、要暂停、要看日志,每次都先 ssh 上去找脚本在哪。然后你开始看调度框架:Airflow 能画 DAG,XXL-JOB 有 UI,K8s CronJob 跟着集群走。每个都像解法,每个都带来新问题。

选方案不是比谁先进,是想清楚你现在卡在哪一层。


代码内调度

还没到 crontab 之前,很多人先把任务写在代码里。

Python 有 scheduleAPScheduler,Java 有 @Scheduled 和 Quartz。一条注解或几行代码,任务就定好了,不用出进程。

python 复制代码
import schedule, time

schedule.every().day.at("03:00").do(backup)

while True:
    schedule.run_pending()
    time.sleep(1)

好处是跟着代码走。git 管理,版本可控,不会出现「服务器上有个 crontab 不知道谁写的」。调度逻辑和业务代码在同一个进程里,改业务顺带改调度,不散在系统层的 cron 里。

暗面:进程崩了全没。 你的调度器和业务代码在同一个进程里。进程崩了------定时任务也没了,不跑了,无声无息。crontab 是系统级的,进程崩了不影响它;代码内调度是进程级的,进程崩了它跟着死。

while True 挂后台,没日志,没监控,跑飞了你也不知道。更关键的是:你的 Web 服务是八实例部署,每个实例里都有一份调度代码,八份同时在跑。 防重复执行靠分布式锁------但锁本身又是个新问题。

一句话总结: 代码内调度跟着代码走,版本可控,git 管理。但进程崩了全没,多实例部署需要自己加锁。适用场景是任务和业务代码紧密耦合、单进程跑就行,不需要跨服务调度。


crontab

Linux 自带,一行表达式一条命令。不装任何东西,机器在它就跑。

复制代码
0 3 * * * /data/scripts/backup.sh

暗面:不可见。 没有 UI,没有状态面板。看一个任务跑了没,得 grep CRON /var/log/syslog。任务多了,最大的问题不是执行失败,是你不知道它存不存在。

翻车现场:同事写了个 cron 做每日同步,离职半年后脚本还在跑,没人知道。磁盘被日志写满,服务崩了,排查的人翻 crontab 才发现------从头到尾没出过错。错的是没人知道它在。

还有时区:0 3 * * * 是凌晨三点,服务器跨时区部署了,这个三点是 UTC 的三点,比你本地晚八个小时。时区不在 cron 表达式里,在系统 TZ 里,没设就默认。

一句话总结: crontab 简单到极致------零依赖,系统自带,一行就够。但没有任何管理能力,任务一多你就不知道谁在跑。适用场景是任务数少、单机、不需要界面。


K8s CronJob

云原生版 crontab:YAML 定义,跟着集群调度。机器挂了 K8s 重新调度,日志跟着集群走,不用 ssh。

yaml 复制代码
apiVersion: batch/v1
kind: CronJob
schedule: "0 3 * * *"

暗面:并发默认不拦。 concurrencyPolicy 默认 Allow------上一个 Pod 没跑完,下一个准时启动。两个 Pod 同时跑同一个任务,数据库里出重复数据。

更隐蔽的:它管启动时间,不管完成时间。上一个任务超时了,下一个照样到点起------两个任务在数据库里打架。startingDeadlineSecondsconcurrencyPolicy 是防这个的,但大部分人出问题才去看。

一句话总结: 有自愈能力、日志统一,比 crontab 强一档。但并发默认不拦,任务超时得自己管。适用场景是你已经在 K8s 里------不是为了 cron 上 K8s,是上了 K8s 就别额外搭调度平台。


Airflow

crontab 只管「什么时候启动」,Airflow 管「启动之后怎么走」。核心是 DAG:任务间有依赖,A 跑完跑 B,B 失败下游全停。

复制代码
backup_db >> clean_logs >> send_report

crontab 里依赖靠时间差------「A 一点跑,B 一点半跑」,A 慢 B 就撞。Airflow 里依赖是代码,A 跑完 B 才启动,不猜时间。

暗面:重。 scheduler、webserver、worker、metadata DB 四个进程起跑,内存吃掉一个 G。二十个定时任务,每个跑几秒,调度器的内存是任务的好几倍。

翻车现场:团队上了 Airflow,DAG 图很漂亮,老板投屏好看。写了三十几个 DAG,每个就一两个 Task------没依赖,没分支,就是把小脚本包装成 DAG。有 DAG 的能力,没 DAG 的需求。

一句话总结: 依赖关系显式化,有 UI,失败重试和暂停都内置。但太重了,部署运维成本比任务本身还高。适用场景是任务间真的有依赖------DAG 图不是装饰。


XXL-JOB

国内最流行的轻量调度框架,Spring Boot 一套,自带 UI。和 crontab 比有界面,和 Airflow 比不要求你写 DAG。

核心是执行器 + 调度中心:调度中心管策略、路由、分片、重试,执行器管跑。之间 HTTP 通信。

crontab 查执行记录靠 grep。XXL-JOB 打开页面,调度记录、耗时、失败次数全在界面上。分片也实用:一个任务拆多片,十个执行器同时跑,单机二十分钟的事两分钟跑完。

暗面:概念多。 路由策略、分片广播、故障转移、阻塞处理策略------十几个概念,每个都要理解。你只是跑一个 curl,crontab 一行够,XXL-JOB 要配执行器、配路由策略、配阻塞策略------任务一行,配置十行。

翻车现场:分片广播配好了,一个执行器挂了。没报错------调度中心把分片匀给剩下的执行器,数据照样跑,少了一台,你没发现。路由策略选「故障转移」才对,但默认是「分片广播」。

一句话总结: 有 UI、有管理能力,分片和重试都内置,是 crontab 和 Airflow 之间的中间地带。但概念多,理解负担重,简单任务用它就是杀鸡用牛刀。适用场景是任务多到需要管理,团队有 Java 技术栈。


怎么选

没有最好。每个都有最擅长的战场,和最翻车的坑。

问自己三句话:

  1. 任务数有多少? 十以内------crontab,别为十个任务上调度中心。几十个、散在不同机器------上调度中心。
  2. 任务间有依赖吗? 没有------别上 Airflow。有------Airflow 或 XXL-JOB。
  3. 已经在什么生态里? 在 K8s------用 CronJob。不在------crontab 或 XXL-JOB,不为了 cron 上 K8s。

卡在规模,上调度中心。卡在依赖,上 Airflow。卡在轻量,退回去用 crontab------不是它好,是你还没复杂到需要更多。

相关推荐
秋风点枝21 分钟前
第一篇:认识 Argo CD —— 从传统发布到云原生 GitOps
git·云原生·argocd
虎王物联43 分钟前
Docker WASM 边缘计算:12ms 冷启动如何重塑 IoT 网关部署
物联网·docker·容器·边缘计算·wasm
猫吃了源码1 小时前
Ubuntu24系统安装部署最新版K8s(Kubernetes)1.36保姆级详细教程
云原生·容器·kubernetes
深念Y2 小时前
微服务抽取路线图:从胖单体到 ARM 集群
前端·arm开发·数据库·后端·微服务·云原生·架构
2301_旺仔2 小时前
【Docker 镜像仓库】
docker·云原生·仓库
2401_834636992 小时前
Docker 容器化技术全解:从镜像构建到容器编排的完整教案1
java·docker·容器
秋风点枝2 小时前
第二篇:安装 Argo CD + 第一次部署应用
kubernetes·github·argocd
2601_967264282 小时前
全新云原生系统精讲与全流程落地实践 - 慕课网
云原生
承渊政道3 小时前
给云原生排障助手装上“大脑“和“身体“:蓝耘元生代MaaS×魔珐星云数字人实战
云原生·数字人·魔珐星云·glm-5.2·蓝耕元生代·播报