数据迁移在服务端是很常见的,包括cache迁移、db迁移等。迁移的动机包括业务重构、业务隔离、机器迁移、扩容等很多种情况。下面笔者就工作中遇到的比较简单的迁移案例浅谈下,读者工作中遇到同类问题可以互相探讨下。
1.cache迁移
mc或者redis节点经常是一致性哈希方式在集群中存放数据的,所以迁移或者扩容并不是简单的加节点。比如我们业务通过twemproxy配置了5个redis节点。现在需要把所有的redis数据迁到新的集群。通常最简单的做法是,在业务低峰期进行全量的redis数据同步,twemproxy进行一刀切。现在谈另外一种做法,更具有普适性,包括可以针对扩容。也即twemproxy逐个加新的cache节点,如:5+1->5+2->...->5+5,然后逐个减少老的cache节点,如:5+5->4+5->3+5->...->0+5。当然整个过程是很谨慎的,要有数据支撑。
- 要评估的数据是,增加或减少cache节点带来的miss的量,以及db是否能够承受。因为增加或减少一个节点,必然导致部分key在cache节点中产生偏移,从而回源到db。所以cache节点尽量多,迁移也尽量在低峰期。实际miss的量和哈希算法以及节点个数相关。
- 要观察的数据是,一方面是每次更改节点后,cache的命中率的变化。要等cache命中率稳定提升到最高,理论上是最适合迁移的时候。另一方面就是db的负载。这两方面共同决定了要不要继续下一次更改节点。
当然,如果有公司自研的cache代理,本身就可以支持扩容。比如可以通过支持流量copy的方式,逐步加热新的cache集群,直至流量全部迁移完毕。
无论什么场景,采用什么方式,cache的迁移或扩容都要特别谨慎!业务请求的tps的时间分布,高峰期的量,cache命中率的预期变化,每个操作步骤的预期时间,回源量变化对后端的影响,网络、存储、带宽,迁移是否会导致业务上的逻辑漏洞等等方方面面都要有尽量明确的评估,还有非常重要的一点:迁移失败的回滚方案。
2.db数据迁移
我们业务中是纯粹进行数据库的迁移,而且要求业务不能停服。具体场景是,千万级以上的数据,数据拷贝至少需要1个小时,另外表的主键id没有被其他表或者cache引用。所以我们的做法是:
- 老库数据全量导入到新库,并记录全部max id
- 程序更改配置和上线,读写都走新库
- 再导出老库的max id,对比上次记录的max id,做增量插入。注意插入时候需要忽略id,否则会有id冲突。
这样基本就完成了表的迁移。这里有个细节,如果新表的自增id我们允许不连续,那么可以设置个比较大的数,在增量插入的时候就可以全部字段复制插入了。而且好处是新老表可以认为是完全一样的,而前一种方式id会变,如果有cache引用那也是有问题的。所以迁移要考虑是否有id作为其他表的外键、是否有cache或者其他地方引用主键id等等。如果漏考虑很可能就造成脏数据甚至影响业务了。