1. 弹性资源服务下的服务迁移到底在解决什么问题
1.1 从一个真实场景说起
去年下半年,我接手了一个内部系统的运维优化工作。这套系统跑在弹性资源服务上,平时流量平稳,但每到月初结算周期,负载会突然飙升到平日的三到四倍。最初的做法是提前手动扩容,把实例数拉满,等高峰过去再缩回来。听起来没什么问题,但实际操作中经常出现两种情况:一是扩容速度跟不上流量爬升的速度,用户端已经出现超时了,新实例还在初始化;二是高峰过后忘了缩容,资源白白空转了好几天,月底一看账单心疼得不行。
后来我们开始认真研究弹性资源服务里的服务迁移能力,才意识到之前很多问题不是靠“加机器”能解决的,而是需要让服务在资源池之间、节点之间、甚至不同规格的实例之间灵活迁移。服务迁移这个词听起来很大,但落到弹性资源服务的语境里,它其实是一组很具体的能力:把运行中的服务实例从一台机器挪到另一台机器、从一个可用区挪到另一个可用区、从一种资源规格调整到另一种规格,而且整个过程尽量不影响对外服务。
这篇文章想聊的就是我在学习和实践弹性资源服务中服务迁移相关能力时,踩过的坑、总结的方法、以及一些我认为比较关键的细节。如果你正在用弹性资源服务跑在线业务,或者正在为潮汐流量、资源利用率、故障转移这些问题头疼,那这篇内容应该能给你一些直接能用的参考。
1.2 服务迁移在弹性资源服务中的定位
弹性资源服务的核心价值就两个字:弹性。但弹性不只是“能扩能缩”这么简单。真正的弹性至少包含三层含义:第一层是容量弹性,也就是根据负载动态调整实例数量;第二层是位置弹性,也就是服务实例可以在不同节点、不同机架、不同可用区之间灵活调度;第三层是规格弹性,也就是同一个服务可以在不同配置的实例类型之间切换,比如从通用型切到计算优化型。
服务迁移主要解决的是第二层和第三层的问题。容量弹性靠的是扩缩容策略,而位置弹性和规格弹性靠的就是迁移能力。举个例子,当某个节点出现硬件隐患需要下线维修时,如果服务没有迁移能力,就只能等节点彻底挂掉再重新调度,这中间必然有服务中断。但如果有了迁移能力,就可以在节点真正故障之前,把上面的服务实例主动迁移到健康节点上,用户完全无感知。
再比如,当业务从测试阶段进入正式阶段,资源需求从“便宜够用”变成“稳定优先”,这时候就需要把服务从低配实例迁移到高配实例。如果没有规格迁移能力,就只能重建实例,重建意味着重新部署、重新预热、重新建立连接,这个过程中的服务抖动是很难避免的。
1.3 哪些场景下必须考虑服务迁移
不是所有场景都需要服务迁移。如果你的服务是无状态的、启动速度极快的、而且对短暂中断完全不敏感的,那直接重建实例可能比迁移更简单。但以下几类场景,服务迁移几乎是必选项。
第一类是长连接服务。比如即时通讯、推送、在线协作这类服务,客户端和服务器之间维持着大量长连接。一旦实例重建,所有连接都会断开,客户端需要重新连接、重新鉴权、重新同步状态。这个过程对用户体验的伤害很大,而迁移可以在保持连接不断的前提下把服务挪走。
第二类是有状态服务。比如缓存节点、消息队列节点、数据库代理节点,这些服务在内存里维护着大量状态数据。重建意味着状态丢失,而迁移可以把状态一起带走。
第三类是启动成本极高的服务。比如需要加载大模型、需要预热大量缓存、需要建立复杂索引的服务。这类服务启动一次可能要几分钟甚至十几分钟,重建的代价太高,迁移是更合理的选择。
第四类是对可用性要求极高的服务。比如金融交易、在线支付这类场景,任何中断都是不可接受的。迁移可以在故障发生前主动把服务挪到健康节点,实现“零中断”运维。
2. 服务迁移的核心机制与方案选型
2.1 迁移的三种基本模式
在弹性资源服务里,服务迁移大致可以分成三种模式:冷迁移、热迁移和温迁移。这三种模式的区分标准很简单:迁移过程中服务是否可用、状态是否保留、中断时间有多长。
冷迁移是最简单的模式。先把服务停掉,然后把镜像、配置、数据搬到目标节点,再重新启动。这种模式的中断时间最长,从几十秒到几分钟不等,但实现起来最简单,对服务本身几乎没有要求。适合那些对中断不敏感、启动速度快的无状态服务。
热迁移是最复杂的模式。服务在迁移过程中始终保持运行,客户端完全感知不到迁移的发生。内存状态、网络连接、文件句柄都要一起迁移过去。这种模式的中断时间可以做到毫秒级甚至零中断,但对底层基础设施的要求极高,需要操作系统、虚拟化层、网络层的深度配合。适合那些绝对不能中断的核心服务。
温迁移是介于两者之间的模式。迁移过程中服务会有短暂的中断,但状态可以保留。比如先把内存状态做快照,然后暂停服务、迁移快照、恢复服务。中断时间通常在几百毫秒到几秒之间。这种模式在实现复杂度和中断时间之间取了一个平衡点,适合大多数有状态服务。
注意:选择迁移模式时,不要盲目追求热迁移。热迁移的实现成本和运维复杂度都很高,如果你的服务能接受秒级中断,温迁移往往是性价比更高的选择。
2.2 迁移触发策略的设计
迁移不是无缘无故发生的,需要有触发条件。常见的触发策略有三类:主动触发、被动触发和计划触发。
主动触发是指运维人员手动发起迁移。比如要下线某个节点进行硬件维护,就手动把上面的服务迁移走。这种策略最可控,但依赖人工判断,不适合大规模场景。
被动触发是指系统根据监控指标自动发起迁移。比如当节点负载超过阈值、当节点健康检查失败、当资源利用率长期偏低时,系统自动把服务迁移到更合适的节点。这种策略最省心,但需要设计好触发阈值,否则容易出现迁移震荡。
计划触发是指按照预设的时间表发起迁移。比如每天凌晨低峰期把服务从高配节点迁移到低配节点,白天再迁回来。这种策略适合有明显潮汐特征的业务,可以显著降低成本。
我在实际使用中比较推荐的组合是:被动触发兜底、主动触发应急、计划触发降本。三层策略叠加,既能保证可用性,又能控制成本。
2.3 迁移目标节点的选择逻辑
迁移不是随便找个节点就搬过去。目标节点的选择需要考虑多个维度:资源余量、网络拓扑、数据亲和性、成本因素。
资源余量是最基本的。目标节点必须有足够的CPU、内存、磁盘空间来承载迁移过来的服务。如果目标节点本身已经接近满载,迁移过去只会把问题从一个节点转移到另一个节点。
网络拓扑决定了迁移后的服务性能。如果服务对网络延迟敏感,就应该尽量迁移到同机架或同可用区的节点,避免跨区域迁移带来的延迟增加。如果服务对网络带宽需求大,就要考虑目标节点的网络出口带宽是否充足。
数据亲和性是指服务依赖的数据源在哪里。如果服务需要频繁访问某个存储节点,就应该迁移到离存储节点更近的计算节点,减少数据传输开销。
成本因素往往被忽略,但实际很重要。不同规格、不同可用区的节点成本可能差很多。如果业务对延迟不敏感,把服务迁移到成本更低的节点上,长期下来能省不少钱。
2.4 迁移过程中的流量切换方案
服务迁移最难的部分不是搬数据,而是切流量。流量切换方案设计不好,迁移过程中就会出现请求丢失、连接断开、会话失效等问题。
常见的流量切换方案有三种:DNS切换、负载均衡切换和连接迁移。
DNS切换是最简单的,改一下域名解析,把流量指向新节点。但DNS有缓存,切换生效时间不可控,从几分钟到几小时都有可能。适合对切换时间不敏感的场景。
负载均衡切换是把新节点注册到负载均衡器,然后从负载均衡器上摘除旧节点。这种方案切换速度快,可控性强,是大多数场景的首选。但需要注意连接排空的问题,也就是旧节点上已有的连接要等它们自然结束,不能直接切断。
连接迁移是最彻底的方案,直接把旧节点上的连接迁移到新节点。这种方案对客户端完全透明,但实现难度最大,需要底层网络协议的支持。
实操心得:负载均衡切换时,一定要设置合理的连接排空时间。我见过太多案例,迁移时直接摘除旧节点,导致大量长连接被强制断开。排空时间要根据服务的连接平均存活时间来定,通常建议设置为连接平均存活时间的1.5到2倍。
3. 服务迁移的实操流程与关键细节
3.1 迁移前的准备工作
迁移前的准备工作做得好不好,直接决定了迁移能不能顺利完成。我总结了一个迁移前检查清单,每次迁移前都会过一遍。
第一项检查是服务状态确认。确认服务当前是健康的,没有正在处理的异常请求,没有未完成的后台任务。如果服务本身就不健康,迁移过去只会把问题带过去。
第二项检查是依赖关系梳理。确认服务依赖的所有外部组件都是可访问的,包括数据库、缓存、消息队列、配置中心等。迁移后这些依赖关系不能断。
第三项检查是数据一致性确认。如果服务有本地状态数据,要确认这些数据已经同步到最新,迁移过程中不会丢失。对于有状态服务,最好在迁移前做一次数据快照。
第四项检查是回滚方案准备。迁移不一定一次成功,必须准备好回滚方案。回滚方案包括:回滚触发条件、回滚操作步骤、回滚后的验证方法。没有回滚方案的迁移就是在赌博。
第五项检查是通知相关方。迁移可能会影响上下游服务,提前通知相关方,让他们有所准备。如果是面向用户的服务,还要考虑是否需要提前发布公告。
3.2 迁移执行的具体步骤
迁移执行阶段是整个过程中最紧张的环节。我通常会把迁移分成几个小步骤,每步都验证通过后再进行下一步。
第一步是目标节点预检。在正式迁移前,先对目标节点做一次全面检查,确认资源余量、网络连通性、依赖组件可访问性都符合要求。这一步可以在迁移前几小时就做,提前发现问题。
第二步是服务实例创建。在目标节点上创建新的服务实例,但先不接入流量。这一步相当于“预热”,让新实例完成启动、加载配置、建立连接池等初始化工作。
第三步是数据同步。如果服务有状态数据,把数据从旧实例同步到新实例。同步方式取决于数据量和实时性要求,可以是全量同步,也可以是增量同步。
第四步是流量切换。把流量从旧实例逐步切换到新实例。我通常采用灰度切换的方式,先切10%的流量,观察一段时间,确认没问题后再切50%,最后切100%。这样即使出问题,影响范围也可控。
第五步是旧实例回收。确认新实例稳定运行后,把旧实例下线回收。回收前要确保旧实例上的所有连接都已经排空,没有残留的请求。
# 以某弹性资源服务平台的命令行工具为例,迁移相关操作的典型命令序列 # 1. 查看当前服务实例分布 resource-cli service describe --service-name my-service --region cn-north # 2. 预检目标节点资源余量 resource-cli node describe --node-id target-node-001 --metrics cpu,memory,disk # 3. 在目标节点创建新实例(不接入流量) resource-cli service create-instance --service-name my-service --node-id target-node-001 --no-traffic # 4. 等待新实例就绪 resource-cli service wait-ready --service-name my-service --instance-id new-instance-001 --timeout 300 # 5. 灰度切换流量(先切10%) resource-cli traffic switch --service-name my-service --from old-instance-001 --to new-instance-001 --weight 10 # 6. 观察一段时间后,切换剩余流量 resource-cli traffic switch --service-name my-service --from old-instance-001 --to new-instance-001 --weight 100 # 7. 排空旧实例连接 resource-cli service drain --instance-id old-instance-001 --timeout 120 # 8. 回收旧实例 resource-cli service delete-instance --instance-id old-instance-0013.3 迁移后的验证与观察
迁移完成不等于万事大吉。迁移后的验证和观察同样重要,很多问题是在迁移后一段时间才暴露出来的。
验证的第一项是服务可用性。确认服务能正常响应请求,响应时间在正常范围内,错误率没有上升。这一步可以通过监控面板快速确认。
验证的第二项是数据一致性。如果服务有状态数据,确认迁移后的数据是完整的、正确的。可以通过抽样比对的方式验证。
验证的第三项是依赖连通性。确认服务能正常访问所有依赖组件,没有因为迁移导致网络策略变化而出现访问失败。
验证的第四项是性能基线对比。把迁移后的性能指标和迁移前做对比,确认没有明显下降。如果性能下降明显,可能是目标节点的资源配置或网络拓扑不如原节点。
观察期通常建议至少持续24小时,覆盖一个完整的业务周期。有些问题只在特定时段出现,比如定时任务触发时、流量高峰时,短期观察很难发现。
3.4 迁移过程中的监控指标
迁移过程中需要重点关注的监控指标有哪些?我整理了一个表格,方便对照检查。
| 指标类别 | 具体指标 | 正常范围 | 异常处理 |
|---|---|---|---|
| 服务可用性 | 请求成功率 | 与迁移前持平 | 低于阈值时暂停迁移 |
| 服务可用性 | 平均响应时间 | 波动不超过20% | 持续上升时回滚 |
| 资源使用 | 目标节点CPU使用率 | 低于70% | 超过80%时考虑换节点 |
| 资源使用 | 目标节点内存使用率 | 低于75% | 超过85%时考虑换节点 |
| 网络 | 网络延迟 | 与迁移前持平 | 明显上升时检查网络拓扑 |
| 网络 | 连接数 | 平稳过渡 | 突增突降时检查连接排空 |
| 数据 | 数据同步延迟 | 接近零 | 持续增大时暂停切换 |
| 错误 | 错误日志数量 | 无明显增加 | 突增时立即排查 |
提示:迁移过程中最容易出问题的时间点是流量切换的瞬间。建议在切换前把监控面板打开,切换后紧盯几分钟,确认没有异常再离开。
4. 常见问题与排查技巧实录
4.1 迁移失败后的回滚操作
迁移失败不可怕,可怕的是失败后不知道怎么回滚。我经历过一次迁移失败,当时新实例启动后一直无法连接数据库,排查发现是目标节点的网络策略没有放通数据库端口。幸好回滚方案准备充分,五分钟内就把流量切回了旧实例,用户几乎无感知。
回滚操作的关键是快和准。快是指回滚决策要快,发现异常后不要犹豫,立即回滚。准是指回滚操作要准,不能回滚到一半又发现回滚不了。
回滚的标准操作流程是:第一步,把流量切回旧实例;第二步,确认旧实例服务正常;第三步,排查新实例的问题;第四步,问题修复后重新尝试迁移。
回滚时需要注意一点:如果迁移过程中已经做了数据同步,回滚后要确认旧实例的数据是最新的。如果新实例在迁移期间产生了新数据,这些数据需要同步回旧实例,否则会丢数据。
4.2 迁移后性能下降的排查思路
迁移后性能下降是常见问题,排查思路可以按照从外到内的顺序进行。
先排查网络层面。对比迁移前后的网络延迟、带宽、丢包率。如果目标节点和依赖组件之间的网络路径变长了,延迟自然会增加。这种情况需要考虑换一个网络拓扑更优的节点。
再排查资源层面。对比迁移前后的CPU、内存、磁盘IO使用情况。如果目标节点的资源竞争更激烈,性能也会下降。这种情况需要考虑换一个资源更充裕的节点。
然后排查配置层面。确认迁移后的服务配置和迁移前完全一致,包括JVM参数、线程池大小、连接池配置等。有时候迁移过程中配置没有完全同步,导致性能差异。
最后排查代码层面。确认迁移后的服务版本和迁移前一致,没有因为迁移导致版本错乱。这种情况比较少见,但一旦发生就很难排查。
4.3 有状态服务迁移的数据一致性保障
有状态服务迁移最怕的就是数据不一致。我总结了几条保障数据一致性的经验。
第一条经验是迁移前做数据快照。不管后续用什么同步方式,先做一个全量快照兜底。快照可以在迁移失败时快速恢复。
第二条经验是迁移中做增量同步。全量同步完成后,持续把旧实例的增量数据同步到新实例,直到流量切换完成。增量同步的延迟要控制在秒级以内。
第三条经验是切换时做数据校验。流量切换前,对新旧实例的数据做一次抽样校验,确认关键数据一致。校验不通过就不切换。
第四条经验是切换后做双向同步。流量切换完成后,短时间内保持新旧实例的双向同步,防止有残留请求写到旧实例导致数据丢失。
4.4 迁移过程中的连接排空问题
连接排空是迁移过程中最容易被忽略的环节。很多人以为流量切换完成就万事大吉了,直接把旧实例关掉,结果导致大量长连接被强制断开。
连接排空的正确做法是:流量切换完成后,旧实例不再接收新连接,但已有的连接继续服务,直到连接自然结束或超时。排空时间要根据服务的连接特性来定。
对于短连接服务,排空时间可以很短,几十秒就够了。对于长连接服务,排空时间可能需要几分钟甚至更长。如果连接有心跳机制,排空时间至少要覆盖一个心跳周期。
排空过程中要监控旧实例的连接数变化。如果连接数下降缓慢,说明还有大量连接没有释放,可能需要延长排空时间。如果连接数突然归零,可能是连接被强制断开了,需要检查排空配置。
4.5 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| 迁移后服务无法启动 | 目标节点资源不足 | 检查目标节点CPU、内存、磁盘 | 换资源更充裕的节点 |
| 迁移后服务无法访问依赖 | 网络策略未放通 | 检查安全组、防火墙规则 | 放通相关端口和协议 |
| 迁移后响应时间变长 | 网络拓扑变差 | 对比迁移前后网络延迟 | 换同可用区或同机架节点 |
| 迁移后数据不一致 | 同步不完整 | 抽样比对新旧实例数据 | 重新同步,校验通过再切换 |
| 迁移过程中请求丢失 | 流量切换太激进 | 检查切换时的错误日志 | 改用灰度切换,逐步切流 |
| 迁移后连接数异常 | 连接排空未生效 | 检查旧实例连接数变化 | 调整排空时间,重新排空 |
| 迁移后性能下降 | 资源配置不一致 | 对比迁移前后配置参数 | 同步配置,重新迁移 |
| 迁移后监控数据缺失 | 监控Agent未迁移 | 检查目标节点监控Agent状态 | 重新安装配置监控Agent |
实操心得:每次迁移后,不管成功还是失败,都要做一次复盘。把迁移过程中的操作、观察到的现象、遇到的问题、解决的方法都记录下来。这些记录在下一次迁移时就是最宝贵的参考。我自己的迁移操作手册就是从一次次复盘中积累出来的,现在每次迁移前都会翻一遍,能避开很多之前踩过的坑。
4.6 迁移自动化的一些尝试
手动迁移做多了之后,自然会想能不能自动化。我尝试过几种自动化方案,这里分享一下经验。
最简单的自动化是脚本化。把迁移的各个步骤写成脚本,每次迁移时执行脚本。这种方式实现简单,但灵活性差,遇到异常情况还是需要人工介入。
进阶一点的自动化是流程编排。用工作流引擎把迁移步骤编排成流程,每个步骤有明确的输入输出和异常处理。这种方式灵活性好一些,但需要维护工作流定义。
更进一步的自动化是策略驱动。定义好迁移策略,系统根据监控指标自动触发迁移,自动选择目标节点,自动执行迁移流程。这种方式最省心,但实现复杂度最高,需要完善的监控体系和决策逻辑。
我目前的建议是:先从脚本化开始,把迁移流程跑顺;然后逐步流程化,把异常处理完善;最后再考虑策略驱动,实现真正的自动化迁移。不要一上来就追求全自动,基础不牢的话,自动化只会让问题更难排查。
5. 迁移能力建设的长期思路
5.1 从单次迁移到迁移常态化
服务迁移不应该是一次性的应急操作,而应该是常态化的运维能力。当迁移变得像重启服务一样简单时,很多运维难题都会迎刃而解。
要让迁移常态化,首先要把迁移流程标准化。每次迁移都按照同样的步骤执行,减少人为差异。其次要把迁移操作工具化。有趁手的工具,迁移效率会高很多。最后要把迁移经验文档化。把每次迁移的经验教训记录下来,形成团队的知识资产。
迁移常态化之后,很多之前不敢做的事情就可以做了。比如可以定期把服务在节点之间轮换,均衡资源使用;可以在业务低峰期主动做迁移演练,验证迁移方案的可靠性;可以在节点出现隐患时果断迁移,而不是等到故障发生。
5.2 迁移能力与弹性伸缩的配合
迁移能力和弹性伸缩是弹性资源服务的两个核心能力,两者配合好了能产生一加一大于二的效果。
弹性伸缩解决的是“需要多少实例”的问题,迁移解决的是“实例放在哪里”的问题。当弹性伸缩触发扩容时,新实例应该调度到最合适的节点上,这需要迁移能力的支持。当弹性伸缩触发缩容时,被缩掉的实例上的服务应该先迁移走再回收,这也需要迁移能力的支持。
我在实践中发现,把迁移能力和弹性伸缩策略结合起来,可以显著提升资源利用率和降低运维成本。比如在缩容时,不是直接销毁实例,而是先把服务迁移到其他节点,再销毁空闲实例。这样既完成了缩容,又保证了服务连续性。
5.3 迁移演练的重要性
迁移能力不是看文档看出来的,是练出来的。我强烈建议定期做迁移演练,哪怕没有真实的迁移需求。
演练可以从最简单的场景开始:找一个无状态的服务,做一次冷迁移,观察整个过程。然后逐步增加难度:有状态服务的温迁移、长连接服务的热迁移、跨可用区的迁移。
演练的目的是暴露问题。很多问题在真实迁移时才会出现,演练就是提前把这些坑踩一遍。演练时要把监控打开,把日志收集好,演练后认真复盘。
演练的频率建议至少每季度一次。如果团队人员有变动,新成员上岗前必须做一次演练。如果迁移方案有更新,更新后也要做一次演练验证。
5.4 迁移过程中的成本控制
迁移本身是有成本的。数据传输要消耗网络带宽,新实例创建要消耗计算资源,迁移期间可能需要同时运行新旧两套实例,资源成本翻倍。
控制迁移成本有几个思路。第一是选择合适的迁移时间窗口,尽量在业务低峰期迁移,减少对正常业务的影响,也减少迁移期间需要的额外资源。第二是优化迁移方式,能增量同步就不全量同步,能温迁移就不热迁移,减少迁移过程中的资源消耗。第三是及时回收旧实例,迁移完成后尽快释放旧实例占用的资源,避免资源空转。
还有一个容易被忽略的成本是人力成本。迁移操作需要运维人员投入时间精力,如果迁移频繁且手动操作,人力成本会很高。这也是为什么要推进迁移自动化的原因之一。
5.5 迁移能力成熟度模型
最后分享一下我总结的迁移能力成熟度模型,可以用来评估团队的迁移能力水平。
第一级是手动迁移。迁移完全靠人工操作,没有标准流程,每次迁移方式可能都不一样。这个阶段的迁移风险高、效率低。
第二级是脚本化迁移。迁移步骤固化成脚本,按脚本执行。比手动迁移规范一些,但异常处理还是靠人。
第三级是流程化迁移。迁移流程编排成工作流,有明确的异常处理和回滚机制。这个阶段迁移的可靠性明显提升。
第四级是自动化迁移。系统根据策略自动触发迁移,自动选择目标节点,自动执行迁移流程。人工只需要监控和兜底。
第五级是智能化迁移。系统根据历史数据和实时监控,预测迁移需求,提前规划迁移方案,实现预防性迁移。这个阶段迁移对业务几乎零影响。
大多数团队处于第一级到第二级之间。我的建议是先把第二级做扎实,再往第三级推进。不要跳级,基础不牢的话,高级能力也发挥不出来。
提示:评估自己的迁移能力时,不要只看技术层面,还要看流程层面和人员层面。技术再好,流程不规范、人员不熟练,迁移照样会出问题。
6. 一些踩坑之后的个人体会
迁移这件事,我最大的体会是:准备工作比迁移操作本身重要十倍。我经历过的最顺利的迁移,都是准备工作做得特别充分的。迁移前把所有可能的问题都想到了,把所有的回滚方案都准备好了,真正操作的时候反而很轻松。而那些出问题的迁移,往往都是准备工作偷了懒,觉得“应该没问题”,结果问题就来了。
另一个体会是:不要追求一次迁移就完美。迁移是一个迭代的过程,第一次迁移能把服务搬过去就算成功,第二次迁移可以优化迁移速度,第三次迁移可以优化迁移体验。每次进步一点,积累下来就是很大的提升。
还有一点:迁移能力的建设需要时间,不要指望一蹴而就。从手动迁移到自动化迁移,中间需要经历很多次实践和优化。但只要方向对了,每一步都算数。
最后分享一个小技巧:每次迁移前,我都会在纸上画一张迁移流程图,把每个步骤、每个检查点、每个回滚分支都画出来。画图的过程就是梳理思路的过程,很多潜在问题在画图时就能发现。这张图在迁移过程中也是很好的参考,遇到问题时看一眼图就知道下一步该做什么。这个习惯帮我避免了很多次“迁移到一半不知道下一步该干嘛”的尴尬。