项目背景
数据迁移指的是数据需要从A迁移到B,之所以需要进行数据迁移,一般是出于2个原因:
- 业务整合,比如两条独立的业务线业务重合度高,为了降本增效,需要将AB业务线数据进行融合。
- 架构升级:业务发展迅猛导致数据增长量快速,原有架构可能在可预期的不久就无法支撑业务发展,一般应对策略是分库分表,而这就涉及需要将老集群(或老库)数据迁移到新集群(或新库)上。
有些项目可能是出于以上两点原因其中一个,有些可能是2个原因都有,本文就是出于以上2个原因。文章将尝试一步步探讨电商订单迁移方案和关键设计,至于分库分表方案不在本次讨论范围(会单独出一篇技术博文)。
注:在后文的讨论中我们假设数据库使用的是Mysql。
迁移方案
迁移思路
在上一篇《数据迁移方案和关键设计》中,我们探讨了在对象存储领域进行数据迁移的一般解决方案,有它的相同点,有些解决思路我们可以尝试应用到订单迁移项目中。
当开始迁移时,按照对象数据迁移方案,当开始迁移时,我们应该避免老集群产生新订单或有新的数据变更,所有请求都转发到新集群,新集群再决定是否需要从老集群拉取数据,是否需要从老集群获取数据判断依据是请求数据是否在新集群已有。
这种思路完全可以应用于订单迁移项目中,但咱们还得思考一下方案是不是最佳的(或者说这种方案是否存在问题)。
对象迁移方案是先适配如果数据不存在再从老集群读过来,然后在流量低峰进行数据迁移,也就是说还未进行数据迁移前可能会出现大量的同步双读情况,性能double了,我们能否利用缓存的思想,预先准备好数据,尽可能避免双读,这样性能不是就更好了?答案是肯定的,我们完全在开始迁移前将老库订单数据同步到新库(即全量同步),然后利用binlog复制日志进行数据异步增量同步。回过头思考为什么对象迁移方案不这么做?这是因为对象存储系统不像mysql这种关系型数据库系统,没有这种复制日志,对象拷贝到新集群过程中,如果老集群相关对象数据发生变更,新集群无法感知这种变化。【数据预热】
迁移粒度
迁移粒度上,对象存储我们最后的方案是按桶和租户进行数据分区迁移,在订单项目中,可以按用户pin迁移,为了确保安全迁移,可以采用试探策略,提前做好用户pin和对应订单数统计,迁移时先针对订单较少的用户迁移,这样做只因为即使迁移失败(设计方案缺陷or系统bug),影响面也能控制在小范围。【数据迁移分区粒度】
如何避免迁移遗漏,迁移数据不正确?
对象迁移给的方案是迁移进度表,同样,订单迁移也需要一张迁移进度表。当迁移开关打开时,老库不再产生新订单,新订单从新库中插入,这样做可以保证老库用户pin维度订单只是存量订单(total是不变的),不会新增,这就给迁移带来了方便,只需要记录:用户pin、total、position、isFinish等字段就能跟踪迁移进度。这块思路和对象迁移是一致的。
如何保证迁移数据正确?在对象迁移中可以通过校验md5、length判断是否正确;由于本次需求涉及多条业务线订单融合,数据正确性保证应该是在设计阶段确定的。最好的保证方式还是需要程序员在编码阶段和代码review阶段保证字段映射正确。
另外,数据迁移过程中,需要避免数据不一致,双写是禁忌。对象迁移是通过禁止老集群有写流量来保证。其实还有一个思路是主从思路。保证写入的数据只有一个主,从通过异步复制方式来达到和主一致。这样也能避免数据不一致。那为什么对象迁移不用主从方式?这和对象存储业务有关,当对象被覆盖时,从重新和主一致成本太高;二来没有这种异步复制机制,而mysql上述两种情况都不是问题。
接口分析
订单操作可分为读写操作:
- 写操作:下单、确定订单、取消订单、其他订单状态变更。
- 读操作:单个读、批量读。在写操作中伴随着订单读接口调用。
读写操作都需要做适配。
迁移流程
通过上节分析,整体过程如下:
- 【数据预热】按用户pin打开迁移开关,迁移job(迁移job在同步器模块中)开始迁移,以此同时,同步器开始接收接收并解析binlog日志,异步同步老库订单状态。
- 经过全量迁移后保证总数总数和已迁移订单大概在99%时,说明订单数据已经基本同步。这时打开灰度开关、双读开关和状态开关,此时下单流量到新系统,新订单在新系统生成。
- 在路由开关打开后,用户pin下的订单可能来自两部分:新系统 or 老系统,为了保证订单查询接口的正确性,存在一个短暂的双读过程。由于路由开关打开后老库订单是一定的,经过几轮全量同步和增量同步,数据可以达到新老系统一直。当两边一致时(订单数一致、订单状态99%几乎完全一致),此时将双读开关设置为完成。(双读过程很短暂)所有读请求走新系统。
- 对老库订单的确认、取消或其他写操作根据订单状态开关判断,当订单状态开关开启时,老库订单状态的变更还是走老库,同步器读取binlog,当发现有老库订单已确认、已取消或已完成时,说明这个订单声明周期已经结束,此时将订单状态开关设置为完成。所有写操作走新系统。
- 订单同步任务发现双读开关已完成 且 用户pin下所有订单状态开关已完成,此时更新灰度开关完成,所有读写请求通通走新系统。
- 下线老系统、下线新系统适配代码、回收资源。
关键设计
迁移组件
参考对象迁移,如下图所示
![d7b35266c8bddbdcc1b4b6ebb0b5a0d8.png](https://i-blog.csdnimg.cn/blog_migrate/b4c2111401dba14234dcc7b32522bd42.png)
- 配置中心:存储迁移开关、灰度路由开关、双读开关和状态开关,并提供读写服务。
- 控制中心:共开发和运维人员使用,可人工控制迁移状态(比如迁移暂停等等)、查看当前迁移进度(提供工具或页面进行查询)。
- 适配代码:从上面的分析老新集群都要做代码适配。
- 同步器:完成订单数据同步,新老订单系统字段映射、数据同步
开关设计
![8fc9d8692cd619d46bc516a72757de85.png](https://i-blog.csdnimg.cn/blog_migrate/7f12117a52a3a6c0c89cb3523c8dfc71.jpeg)
The end.
转载请注明来源,否则严禁转载。