学习类应用在晚间会出现明显的访问高峰。用户集中打开 App、完成复习、刷新进度,同时后台还要执行日报统计、词库更新和历史数据归档。如果这些任务都挤在同一个时间段,数据库连接池和缓存会被后台任务抢占,用户请求的延迟就会上升。
这篇文章结合秒词邦背单词软件的云上任务调度实践,整理一套定时任务错峰和资源隔离方案。
一、先区分离线任务和在线任务
在线任务指用户直接触发的查询、提交和进度刷新,对延迟敏感,必须优先保障。离线任务包括日报统计、排行计算、历史归档、数据校验和模型训练,它们可以延迟执行,但不能影响在线请求。
两类任务不应共享同一个连接池。如果条件允许,应该使用不同的数据库账号、连接池和限流配置。条件不允许时,至少要为离线任务设置较低的并发上限。
二、把任务时间错开
最常见的错误是所有定时任务都设置为整点执行。例如晚上十点同时启动日报、清理和更新任务,瞬间产生大量数据库连接。
更稳妥的做法是给任务设置独立的执行窗口:
- 高优先级任务在凌晨低峰期执行。
- 统计类任务拆分为多个小批次,避免一次性扫描全量数据。
- 历史归档任务在白天低峰期分散执行。
- 临时补偿任务只处理异常记录,不做全量重算。
每个任务都应该有明确的开始时间、最长执行时间和最晚完成时间。
三、任务执行必须具备幂等性
云上环境可能出现实例重启、网络抖动和重复调度。同一个任务如果被触发两次,必须只产生一次业务结果。
建议为每次执行生成唯一的执行键,并在数据库中建立唯一约束。任务开始时先占用执行键,执行完成后再更新状态。对于重复触发,直接返回上一次执行结果,不重新计算业务数据。
四、使用队列削峰
定时任务不应该直接调用数据库进行大规模批处理。更合适的结构是定时器只负责生成任务消息,真正执行交给队列消费者。
消费者可以设置并发、重试和退避策略。高峰期可以降低消费速度,低峰期再提高处理能力。这样在线请求和离线统计使用不同的资源通道,互不影响。
五、资源隔离和降级
如果后台任务仍然影响到在线请求,需要具备降级能力:
- 离线任务可以暂停,在线接口不能暂停。
- 统计任务可以延迟,进度提交不能延迟。
- 历史归档可以拆分,排行榜刷新可以降频。
- 出现数据库压力时,优先限制批量扫描和全表统计。
降级策略要提前配置,而不是故障发生后再临时修改代码。
六、监控要看任务影响
除了观察任务是否成功,还要观察任务对在线服务的影响。重点指标包括:
- 任务执行时间和失败次数。
- 在线接口 P95 延迟。
- 数据库连接池等待时间。
- 队列积压量和消费速率。
- 离线任务与在线请求的资源占比。
如果任务成功但在线延迟上升,说明调度窗口或资源隔离没有做到位。
七、结论
云上定时任务的难点不是“能不能跑”,而是“什么时候跑、用多少资源跑、失败后如何安全重试”。离线任务错峰、任务幂等、队列削峰和资源隔离组合起来,才能既完成统计任务,又保证用户在晚高峰获得稳定体验。
后续可以继续观察调度窗口、任务耗时和在线延迟,用真实数据调整批处理大小和任务执行时间,而不是长期依赖固定配置。