收盘后更新行情的任务平时十分钟结束,有一天接口变慢跑了半个多小时。下一次调度到点后又启动一份,两边同时写数据库,最后出现重复记录。我原来以为“每天16:10执行”已经足够,后来才明白:Cron只回答何时触发,不负责处理上一次还没结束怎么办。
用 APScheduler 3.x,可以先把单进程内的重叠规则写进任务定义:
from apscheduler.schedulers.background import BackgroundScheduler
scheduler = BackgroundScheduler()
scheduler.add_job(
update_daily,
"cron",
hour=16,
minute=10,
id="daily_update",
replace_existing=True,
max_instances=1,
coalesce=True,
misfire_grace_time=600,
)
max_instances=1 表示同一任务已有实例运行时,不再并发启动第二个。coalesce=True 用于程序停机后恢复:如果积压了多个应执行时间,只合并运行一次。misfire_grace_time=600 则把允许迟到的窗口限制为十分钟。三个参数管的是不同问题,不能只开其中一个就当成“防重复”。
这套限制还有边界:它只约束当前调度器实例。如果两个进程或两台机器都启动调度器,仍可能各跑一次。APScheduler 官方说明也不建议多个调度器共享同一持久化任务库。部署时应保证调度器单实例,或者再加数据库锁、Redis锁等跨进程互斥手段。
我还会给每次运行生成“任务名+交易日”的唯一键,写入前先检查;行情表保留股票代码和交易日的唯一约束。调度层阻止重叠,数据层最后兜底,比只盯着任务是否按时启动更可靠。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。