很多团队在业务初期都用 crontab 管定时任务。一台服务器上躺着几十条脚本,哪天机器出问题,没人说得清哪些任务跑过,哪些漏掉了。业务量上来以后,任务从“能跑”变成“要管得住”,这时才需要认真考虑调度方案。阿里云上承载定时任务的方式不少,迁移时最容易出问题的,往往是前面的设计环节。

单机定时任务为什么撑不住
crontab 的短板很具体。宿主机一挂,任务整体停摆,常常要等下游数据对不上才发现。失败之后没有统一的执行记录,只能登录机器翻日志。并发和重试也很难控制:同一个任务如果在两台机器上各跑一次,结果可能是重复扣费,或者同一批用户被重复发券。
这些问题有一个共同根源,就是定时触发和任务执行绑在同一台机器上。把两者拆开,是分布式任务调度的出发点。触发交给调度服务,执行交给可以水平扩展的 worker,任务状态集中存放,出了问题就有地方查。
阿里云上可以怎么承载任务
选型先看任务性质,大致可以这样区分:
- 分布式任务调度服务:适合需要统一管理、跨机器分片执行、带失败重试和执行台账的业务任务。如果任务要和业务代码紧密配合,这类方案通常更顺手。
- 函数计算的定时触发器:适合轻量、无状态、按时间或频率触发的小任务,没有常驻服务器的维护负担。但要留意单次执行时长和无状态的限制,需要保存中间结果的任务不适合直接放进去。
- 批量计算:适合大批量、可以并行切分的离线计算,比如全量数据清洗、批量渲染。
- 工作流编排:适合多个任务有先后依赖的场景,比如先同步数据,再生成报表,最后推送通知。
产品的功能边界、计费方式和地域支持都会随版本调整。正式选型前,以阿里云官方文档和控制台的最新信息为准,别只依赖二手资料。
一个示意性的对账场景
下面这个场景是为了说明思路而构造的,不是某个真实项目的复盘。假设某电商团队每天凌晨要做三件事:拉取支付渠道账单、和订单库对账、把差异结果推给财务。最初他们用一台服务器的 crontab 把三段脚本串起来。某次磁盘写满,账单拉取失败,但对账脚本照常跑完,报表显示“零差异”。财务过了两天才发现数据对不上。
这类事故出在三段脚本互相不知道对方的状态上。改造时可以从三处下手。第一,把三个步骤拆成独立任务,用工作流声明依赖关系,上游失败时下游挂起,不再带着错误数据继续跑。第二,给账单拉取配置失败重试和超时告警,并设定连续失败多少次才通知值班人员,避免一次网络抖动就把人叫起来。第三,把每次执行的开始时间、耗时、返回码统一落库,出了问题可以按任务名和日期直接查。
改完之后,最明显的变化是排查变快了。以前要登录几台机器逐个翻日志,现在在控制台按任务和日期就能定位到是哪一步出的问题。这个案例并不复杂,难点在于先把“谁依赖谁、失败怎么办、结果存哪里”三件事说清楚,工具反而是其次。
设计任务时的几条经验
幂等要放在第一位。调度系统再可靠,网络抖动和重试都可能让同一个任务执行两次。做法是为每次业务操作生成唯一业务键,写入前先查一下是否已经处理过。发券、扣款这类操作尤其要这样做,否则一次重试就可能变成一次资损。
切分粒度也要想清楚。任务切得太大,失败后重跑的代价高;切得太碎,调度开销和依赖关系又会变得难管。一个比较实用的标准是:失败后能不能单独重跑,产出能不能单独校验。两个都满足,粒度大体就对了。
告警要克制。只对真正影响业务的失败发通知,消息里带上任务名、所属业务和处理入口。如果什么日志都推送,值班的人很快就会习惯忽略,真正的故障反而被埋掉。
权限和资源最好隔离。不同业务的任务放进独立的项目或命名空间,再通过 RAM 角色限定访问范围。这样一个任务的误操作,就不会波及其他团队的数据和配额。
小结
把定时任务迁到阿里云,实际上是把“什么时候执行、怎么执行、结果在哪”从单台机器里拿出来。选型先看任务性质,再用幂等、合理切分和克制告警把细节做实。做到这一步,定时任务才不再是需要半夜盯着的负担。