遗留系统数据迁移实战(十一):迁移进度表和异步 Run 接口设计
为什么同步 run 接口不够用
迁移初期,一个 run 接口直接完成:
dry-run -> execute -> validate小客户没问题。但大客户迁移可能跑几十分钟甚至几个小时。
同步 HTTP 请求会遇到:
- 网关超时
- 浏览器超时
- 调用方不知道后台是否还在跑
- 多人测试时难以判断进度
- 失败后不知道停在哪个阶段
所以需要异步化。
异步 run 的基本思路
接口调用后不等待迁移完成,而是立即返回:
{"progressId":"xxx"}后台继续执行迁移。
调用方通过查询进度接口获取:
当前阶段 总进度 阶段进度 已处理数量 总数量 是否完成 是否失败 失败原因进度表为什么要精简
进度表不是业务表,不应该设计得太复杂。
字段够用即可,例如:
id business_account root_dept_code task_type stage status processed_count total_count progress_percent message error_message start_time update_time finish_time核心是回答:
谁在跑? 跑什么? 跑到哪一步? 完成多少? 是否失败?分阶段统计比总进度更靠谱
实时、冻结、告警不是一个业务量级。
如果简单用总数统计,可能出现:
实时很快完成 冻结跑很久 告警数据很少用户看到总进度可能不直观。
更合理的是按阶段统计:
REALTIME_MIG FREEZE_MIG ALARM_MIG TARGET_WRITE VALIDATE每个阶段有自己的:
processed_count / total_count / percentWalkBy 怎么统计
WalkBy 数据结构更多,但数据量通常没有冻结那么夸张。
可以按表统计:
rm_record rm_record_hi rm_task rm_plan rm_book rm_pub_record relation tables或者更简单地按阶段:
WALKBY_DRY_RUN WALKBY_EXECUTE WALKBY_VALIDATE如果业务只关心“是否还在跑”,阶段级别就够用。
进度更新失败不能影响迁移
这是一个重要原则。
进度表是辅助能力,不能因为更新进度失败导致主迁移失败。
所以进度更新应该:
失败只打 warn 日志 不抛出阻断主流程否则就会出现很尴尬的情况:真实数据已经迁完,但因为进度表写失败导致接口失败。
日志和进度表的关系
进度表给前端或调用方看。
日志给研发排查问题。
两者互补:
进度表:用户知道跑到哪 日志:研发知道每一步细节不要试图把所有日志都塞进进度表,否则表会变得很重。
断点续跑和进度表
进度表不是天然的断点续跑机制。
断点续跑应该依赖业务数据状态,例如:
中间表已经写到哪个表号 目标表已经写入多少 唯一键幂等能否覆盖进度表只能辅助展示和判断,不应该成为唯一断点依据。
总结
异步 run 接口解决的是调用体验和可观测性问题。
它的核心设计是:
接口快速返回 progressId 后台执行迁移 进度表记录阶段和数量 日志记录详细链路 进度失败不影响主流程对生产迁移工具来说,这比让调用方一直等 HTTP 响应可靠得多。
