如何将指定Coroutine Dispatcher的任务转移至另一Dispatcher
Dispatcher 1全量任务无损迁移到Dispatcher 2落地方案
以下方案适配绝大多数自研/开源调度系统的Dispatcher实例,落地后可保证任务不丢、不重跑、调度逻辑不偏移。
前置准备(漏做必出问题)
- 全量备份Dispatcher 1的持久化存储:不管任务元数据存在MySQL、Redis、本地RocksDB还是其他存储介质,全量导出快照做离线留存,操作失误时可直接回滚
- 预启动Dispatcher 2并做配置校验:确认Dispatcher 2和下游执行器网络连通、权限配置一致、节点时钟和Dispatcher 1误差不超过1s,启动后暂时关闭自动调度开关,禁止实例提前抢任务
- 梳理Dispatcher 1现有任务清单:按状态分为执行中任务、待触发任务(含定时、延迟、重试等待任务)、异常待处理任务(死信、人工干预任务)三类,不同类型迁移逻辑分开处理
迁移操作步骤
1. 冻结Dispatcher 1的任务写入
- 调整上游路由规则,所有新提交的任务请求全部转发到Dispatcher 2,切断Dispatcher 1的新任务入口
- 等待Dispatcher 1上所有短周期执行中任务运行完成,通过监控面板确认运行中任务数归0;支持断点续跑的长周期任务直接触发安全中断,把断点进度、执行上下文持久化到存储层
- 给Dispatcher 1加只读锁,禁止实例再更新任何任务状态,锁操作参考命令:
curl -X POST http://<dispatcher1_internal_ip>:<management_port>/api/instance/lock -d '{"mode":"readonly"}'
2. 全量同步任务数据
- 待触发类任务:批量把Dispatcher 1存储中状态为
WAITING、RETRY_WAITING、DELAY_WAITING的任务记录同步到Dispatcher 2对应存储表,同步时保留原任务的触发时间、重试规则、回调配置、任务唯一ID,不要修改核心属性 - 中断的长周期任务:把之前持久化的断点上下文、执行进度同步到Dispatcher 2的上下文存储,标记任务状态为
RESUME_PENDING - 异常待处理任务:全量同步任务的失败日志、异常栈、处理记录到Dispatcher 2的运维任务列表,保留原有人工干预入口
3. Dispatcher 2接管校验
- 打开Dispatcher 2的自动调度开关,先观察10~15分钟:
- 核对待触发任务的实际触发时间和原调度计划完全匹配,没有提前触发、漏触发
- 验证断点续跑任务从上次中断位置继续执行,没有从头重复运行
- 确认重试任务、死信任务展示正常,重试策略和原配置一致
- 手动提交5~10个不同类型的测试任务,确认调度、执行、回调全链路正常,状态流转符合预期
- 确认无异常后,断开Dispatcher 1的存储连接,实例保留冷备72小时,确认业务无影响后再做下线销毁
避坑提示
- 禁止在Dispatcher 1正常运行时直接把存储挂载给Dispatcher 2,两个实例会同时抢任务分布式锁,大概率导致任务重复执行
- 迁移过程不要修改任务唯一标识,否则上下游回调、任务状态查询会出现匹配失败的问题
- 如果Dispatcher是基于数据库行锁做任务抢占,迁移完成后一定要确认Dispatcher 1的所有数据库连接已断开,避免残留进程偷偷抢占任务
- 无幂等保护的任务必须等Dispatcher 1上执行中任务全部跑完再做切换,避免重复执行影响业务数据
内容的提问来源于stack exchange,提问作者stefano
相关产品推荐
相关产品推荐

