方案
- 每执行一个步骤后,一旦出现问题,能快速地回滚到上一个步骤。
- 异构数据库,Binlog 实时同步数据。
- 上线同步程序,从旧库中复制数据到新库中,并实时保持同步;
- 上线双写订单服务,只读写旧库;
- 开启双写,同时停止同步程序;
- 开启对比和补偿程序,确保新旧数据库数据完全一样;
- 逐步切量读请求到新库上;
- 下线对比补偿程序,关闭双写,读写都切换到新库上;
- 下线旧库和订单服务的双写功能。
Another:
- 我们对老库的更新操作(增删改),同时也要写入新库(双写)。如果操作的数据不存在于新库的话,需要插入到新库中。这样就能保证,咱们新库里的数据是最新的。
- 在迁移过程,双写只会让被更新操作过的老库中的数据同步到新库,我们还需要自己写脚本将老库中的数据和新库的数据做比对。如果新库中没有,那咱们就把数据插入到新库。如果新库有,旧库没有,就把新库对应的数据删除(冗余数据清理)。
- 重复上一步的操作,直到老库和新库的数据一致为止。
想要在项目中实施双写还是比较麻烦的,很容易会出现问题。我们可以借助上面提到的数据库同步工具 Canal 做增量数据迁移(还是依赖 binlog,开发和维护成本较低)。
评论的迁移方案
在 16 年去 o 时设计的一个方案和这个很相似。需要将 56 亿 oracle 的财务数据迁移到 mysql 中并保证一直提供稳定的线上服务。方案主要涉及以下几点:
-
设计同步 worker 以 6 亿/天的速度同步至 mysql,预先按照 1000 的间隔生成 560w 个任务,用于保证数据同步不丢失。
-
mysql 业务数据库库为了防止和 oracle 中 id 碰撞,设计 id 生成器其中,前三位为库编号;
-
因为高达 100w/分钟的事务量,设计了前置防重表+任务表(按照 uuid 分库),用于防重、规避热点和异步增加吞吐量;
-
业务数据库通过在前置库生成的 id 分库,同时会异步同步至 es;
-
原接口服务改造,写老库数据和发送 mq 在一个事务(mq 挂了会影响服务)。提供新接口服务写新库并发 mq;
-
接收端消费 mq 并根据标示同步至老库或新库;
-
提前定义好一个阈值单号,比如当前数据已经累积到 57 亿,那我们可以根据增速估算一个阈值 58 亿。在上线后只有 58 亿以后的数据会通过 mq 同步至老库的。以前的数据都由 worker 同步(在适当时候:如目前单号已超过 58 亿,生成另外 20w 个任务,并开始执行另外两亿数据的同步,期间新库会缺少这两亿数据);
-
在 mq 同步稳定一段时间后,用新接口灰度替代老接口,在整体稳定后全量切换至新接口,并用 mq 同步老库。