logo头像
Snippet 博客主题

如何平滑数据迁移不影响服务的可用性

本文于 875 天之前发表,文中内容可能已经过时。

今天去壹钱包面试,问了一些解决方案,被有道题目难住了。

业务场景

有个用户基础信息表,注册的时候,用户的手机号当前是明文保存在db,用户信息泄露的问题影响是不能容忍的,安全部要求把这个明文手机号改成密文,但是我们号称是24*7小时全天服务的公司,为保证系统可用性,请出个方案,平滑的将明文数据改成密文数据。

初看这道题,觉得很简单。这里涉及到新老数据共存的问题。
我当时提出的方案是这样的:

老用户数据加个是否加密的标示。新用户直接执行加密,存db。老用户查询的时候用明文,查询完,将明文转成秘文,更新到db并且标志位更新成秘文。
再加个补偿任务,降漏掉的明文改成秘文。

无疑,太粗暴了。当系统发布的过程中,原逻辑代码的实例与加密的新实例,如果收到并发的2个同样手机的请求来,会导致重复手机号注册的问题。当时没有思绪,面试官让我回家想。。。

后来回到家,经过跟瑞强讨论,拿到了如下的解决方案。

时间换空间

分四步
1:加另一张表,跟原来表结构一样,用于存密文。
2:然后代码增加一个同步数据的功能,将明文转成密文同步到新表去。
然后新代码发布的过程中,老代码的服务可能存在的情况就是没有把数据同步到新表去,
新代码的数据 老表跟新表都有。
3:然后等待系统发布稳定后,再写个脚本将旧表数据 加密同步到新表去。
4:切换业务代码到新表,删除旧表

我回复了面试的答案,面试官说,也是一种思路。他用一句话总结:“两个表双写是一个思路,本质上就是新老不能混在一起,为达到这个目的手段可以有多个”


2019/4/28

这二天,看了下架构方便的博客,看到了58沈剑的文章有提到这块关于“100亿数据平滑数据迁移,不影响服务”的介绍,才明白,上面提到的解决方案,名叫“双写法”,这个方案是不完善的,体现在:
数据迁移后,先写个校对数据校验工具保证新旧表的数据一致性,再切新表。

在一个极端的情况下,在数据迁移过程中,当提取旧表的某一条记录A,准备迁移到新表,这时候旧表进行了delete A的操作,这时候双写的时候,新表还没有A的记录,这就导致了新表多了一条数据,所以数据校对一致性工具还是必要的。

另外学到了另外一套新的迁移方法,个人觉得比较麻烦。追日志法,可以看下这篇文章的介绍。