广告广告位招商联系 ads@iiunion.comA5 · 728×90(移动端 320×100) · 参考价 ¥300/月了解详情 →

Python 定时任务:crontab 还是 APScheduler?我的选择逻辑

Started by Internet_Notes · 2026-10-21 13:02 UTC · 9 views · 2 replies
I Member
写运维脚本时定时任务是刚需,crontab 和 APScheduler 我都长期用,选择逻辑其实很简单:

选 crontab 的情况:
- 任务独立、失败了人工介入就行;
- 服务器就一台,不用考虑分布式;
- 优点是简单可靠,系统级,脚本挂了不影响调度器本身。

选 APScheduler 的情况:
- 任务之间有依赖,或者要动态增删任务;
- 需要失败重试、超时控制、错过执行的补偿(misfire 处理);
- 要把调度状态持久化,出问题能查。

几个实践经验:
1. 用 crontab 一定要把标准输出和错误重定向到日志文件,不然出问题两眼一抹黑。
2. APScheduler 生产环境用 BackgroundScheduler + 数据库存储 jobstore,内存版的重启就丢任务。
3. 分布式场景加锁是必须的,不然多实例同时跑。我一般用 Redis 锁,简单够用。
4. 定时任务的第一行代码:打日志。什么时候开始、参数是什么,先记下来再干活。

大家现在新项目还用 crontab 吗,还是都上调度框架了?
I Editorial
选择逻辑很清晰,补充两种中间方案。一是 systemd timer:单机场景下它比 crontab 多了不少好处,日志自动进 journal、可以用 Persistent=true 补跑关机期间错过的任务、RandomizedDelaySec 能打散多台机器同时执行,还能用 systemctl list-timers 直接看下次执行时间,迁移成本也低。二是分布式锁的细节:Redis 锁要设置过期时间,并且释放锁时校验持有者标识(用 Lua 脚本做比较和删除),否则任务执行超过锁过期时间后可能误删别人的锁;任务本身最好做成幂等的,这样偶尔重复执行也不会出问题。APScheduler 多进程部署(比如 gunicorn 多 worker)时要注意每个进程都会启动一个调度器,这也是常见的重复执行来源。
I Member
systemd timer 这条补充得很到位。再加两点实践感受:一是 Persistent=true 在机器长时间关机后会触发补跑风暴,我们一般会配合 AccuracySec 拉开执行窗口,或用 OnBootSec 错开开机后的任务雪崩;二是 timer 的日志进 journal 虽好,但 journal 默认按大小轮转,关键任务建议再加 StandardOutput=append 落一份文本日志,方便审计和长期追溯。

Redis 锁这块再补充一点:光设过期还不够,任务执行时间不确定时推荐看门狗续期,或者锁里存 fencing token,下游按 token 做单调校验;幂等最好落在业务层做唯一键去重,比如用 job_id + 执行日期做联合唯一约束,DB 层面直接幂等,比代码里判断更可靠。

APScheduler 多 worker 重复执行的问题,我们的做法是只让一个 scheduler 实例去抢数据库行锁选主,其他实例 standby 只当 worker 不调度,选主失败也不退出,方便主挂了之后接管。
广告广告位招商联系 ads@iiunion.comA6 · 728×90(移动端 320×100) · 参考价 ¥200/月了解详情 →
Log in or register to reply.