分库分表后我们需要将原有的数据迁移到新的数据和表中 一般会有停机迁移和不停机迁移两种方案,下面给大家讲解一下, 这两种方案分别怎么做,和需要关注的点
停机迁移
优点:
简单 停机迁移因为系统停机 所以数据不会新增只需要将存量数据迁移到新的库表中即可
缺点:
需要停机 数据多的话可能停机时间较长 而且如果迁移失败可能需要再次迁移
不停机迁移
优点:
系统不需要停机 可以无感迁移
缺点:
方案较复杂需要关注
- 增量数据迁移
- 存量 数据迁移
- 数据迁移过程中的数据校验
- 老库 新库切换方案
- 灰度方案
不停机迁移方案
核心流程
双读双写
双读双写流程:写旧读旧 -> 双写读旧 -> 双写双读(核对) -> 双写读新 -> 写新读新
(1)代码梳理: 对需要迁移的读写接口进行整理 并改造编写对应的代理类;
(3)双写:控制往老库写数据,还是往新库写数据。在灰度期间,既要写老库又要写新库,新库写失败,不能影响老库数据的写入,不能影响服务。双写不一致数据需要有补偿兜底,如增量迁移兜底还有双读校验等。
(4)双读:双读的目的是在实时数据核对不一致时,控制返回老库的结果,还是返回新库的结果。在代理层对所有的读操作进行灰度控制(如果没有灰度字段,需要改造代码)开关控制是否需要读新库、老库数据做对比,如果对比校验两边数据一致,则返回新库数据,否则返回老库数据,同时打印不一致的内容,补偿数据,排查不一致的原因。
数据迁移
(1)存量数据迁移:将老库中已经存在的数据批量迁移到新库,在进行存量数据迁移前。需要注意一下数据迁移完成的时间,适当使用多线程同步,注意控制qps,也可以加上开关保证有问题时迁移任务能够立即停止(停止时打印当前迁移的位置,下次可以从暂停位置继续迁移),以免对线上服务造成影响。
(2)开启双写:存量数据迁移完成之后,开启双写,同时写老库与新库。存量数据迁移过程中,数据可能会更新,因此还需要进行增量迁移。
(3)增量数据迁移:将老库更新时间大于存量数据迁移开始时间的数据,再迁移到新库一遍
可能出现的问题
- 老库执行insert操作后
新库执行insert操作,操作一定能成功,因为新库的数据是老库的子集,老库既然可以插入成功,那么新库也可以插入成功,此时老库新库都插入了数据;
- 老库执行delete操作后
根据删除的数据所处的区间,分为两种情况:
(1):假设delete的数据属于[start, current]范围,即已经写入了新库,则老库新库都删除了该条数据,数 据一致性没有被破坏;
(2):假设delete的数据属于[current, latest]范围,即还未写入新库,则老库中删除操作的affect rows(影响的行数)为1,新库中删除操作的affect rows为0。但是数据迁移任务在后续数据迁移中,因为这条"未来的"数据已经从旧库删除,因此并不会将这条旧库中被删除的数据迁移到新库中,所以数据一致性仍没有被破坏;
- 老库执行update操作后
根据更新的数据所处的区间,分为两种情况:
(1):假设update的数据属于[start, current]范围,即已经写入了新库,则老库新库都更新了该条数据,数据一致性没有被破坏;
(2):假设update的数据属于[current, latest]范围,即还未写入新库,数据迁移任务在后续迁移中,这条数据也会被正确迁移。
特殊情况
数据迁移时刚好从老库将数据取出,准备迁移插入到新库;同时旧库发生了update或delete操作;新库的数据和旧库的数据就存在了差异。
数据校验与订正
存量、增量数据迁移完成后,由于删除、并发更新冲突等特殊情况,以及迁移的代码可能存在问题。因此数据校验与订正是必要的,校验老库和新库的所有字段数据是否一致。校验方式可以通过:
(1)实时内存双读校验
(2)接口抽样/全量数据校验
(3)离线同步数据,通过脚本校验
校验后,可能会发现各种数据不一致的问题,需要修正迁移逻辑,将不一致的老库和新库进行数据订正,保证一致性。
切流
(1)当数据校验完成后,可以进行灰度切流;
(2)需要制定好一个切流计划,在什么时间段,放出多少的流量,并且切流的时候要选择流量比较少的时候进行切流,每一次切流都需要对日志做详细的观察,出现问题尽早修复。流量的放出过程是一个由慢到快的过程,比如最开始是以1%的量去不断叠加的,到后面的时候以10%,20%的量去快速放量。因为如果出现问题的话往往在小流量的时候就会发现,如果小流量没有问题那么后续就可以快速放量
完成迁移
切流和后处理完成,然后观察各个业务后续工单反馈情况和各个系统预警与日志;双写关闭,只写新库,观察新库性能,确保新库的稳定性。