团队文化:进取,分享,快乐,责任!
团队愿景:做最好的产品,打造有影响力的团队!
随着业务的发展,用户信息的数据目前达到一定的量,并且用户数据在持续增长,原先定义的单库单表的数据库对于目前大量数据进行处理时性能变得比较低,数据查询响应的耗时也比较大,我们决定开始对数据库进行优化,进行分库分表,并将用户数据平滑迁移至新库中,进而保证在用户无感知的情况下提高响应速度,并且保证数据的完整性,避免用户数据丢失。
常见数据迁移的方案
方案一:暂停服务,进行历史数据的迁移。
停服迁移数据的方案相对简单,并且能够保证数据迁移的一致性,但是用户将会有一段时
间无法使用服务,对用户很不友好。
方案二:以某一时间节点进行数据迁移,该时间节点之后的数据在插入数据库的同时使用消息表进行记录,当该时间节点之前的数据迁移完成之后,再将消息表中记录的数据变化情况同步到新库的数据中。
这种方案可以保证服务的正常运行,同时进行数据的迁移。当已迁移的数据再次发生变化
时,需要将数据的变化情况加入消息表中,最后在逐步的将消息表中的数据变化情况同步
到新库中。但是在同步消息表中的数据的变化时,依然会有新的数据变化产生,这样就需
要逐步的去追平数据的变化,因此在同步消息表中数据的变化时,如果数据量比较大,就
需要相对较长的时间才能完全将数据持平。
方案三:在迁移静态数据的同时,将旧库中变化的数据同时在新库中同步。
该方案在迁移数据的同时同步数据的变化,可以做到动态数据迁移。但是一旦数据迁移过
程中发生失败,无法感知,在后续进行动态数据的一致性校验时比较困难。
在了解了上述几种迁移方案后,我们是否可以直接选择其中一种进行使用呢?答案是不行的!
首先,我们此次进行的是用户基础数据的迁移,不允许进行停服迁移数据,否则没有用户基础数据,所有使用的业务都将无法进行。
其次,我们的用户数据量比较大,否则也不需要进行数据库的优化。
再次,我们的用户数据都是动态数据,即每条用户数据时时都会发生改变,而非是一些不再发生变化的历史数据迁移,并且每天用户的新增条数和数据变化量都很大,如果单纯使用消息表记录数据,那么后期将会陷入一个长期的数据追平过程中。
另外,尽管数据已经追平使其保持一致,在切换数据库的过程中依然会发生数据变化,如何保证数据的完全一致,当数据库切换过程中出现问题又如何进行回滚仍然需要进一步的考虑。
最后,我们希望在数据迁移过程中对数据有一定的掌控,能够清楚的了解哪些数据已经迁移,哪些数据在迁移过程中又发生了变化,这些变化哪些进行了顺利的改变,哪些又产生了异常需要重试……从而真正的保证数据迁移的一致性、完整性。
我们的方案
结合方案二的数据记录以及方案三数据库双写的思想进行方案改造:对旧库的表进行binlog日志监听,当用户信息表发生变化时发送mq,将mq信息进行存储,同时将动态数据同步到新库中,保证数据的最终一致性。
具体步骤如下
步骤一:对旧库用户信息数据的变化进行binlog监听,主要监听旧库中insert、update、delete的操作。
步骤二:开发数据迁移工具:
消息监听器,将消息存入消息表中,并将最新的用户信息同步到新库中。
数据迁移工具,将旧库中的数据迁移到新库中。
开发工具,处理消息表中同步新库时失败的数据。
步骤三:数据一致性对比,保证数据量完全同步,并且数据都是用户编辑后的最新数据。
步骤四:新库向旧库动态数据反向同步。
正常来说,数据完全一致后就可以切换数据源到新库,但是为了避免数据库切换后,发生未能预料的异常,便于回滚到旧库,在上线后仍然需要对新旧库同时写入数据。如同上述步骤一、二,需要对新库binlog监听,进行用户数据的变化监听,在新库插入数据的同时同步数据到旧库。
此处需要注意的是,由于上线是新、旧服务的切换过程,因此有新库、旧库短暂同时并存的情况,即在新旧数据库中都会产生数据变化,因此就会同时对新、旧库的监听日志产生。如下图:
此时需要避免因此产生的数据重复双写入问题。以数据插入新库中为例。数据插入新库后,由于数据的变化,产生binlog消息,向旧库中插入数据,由于新、旧库都有对数据变化的监听,因此旧库也会产生binlog消息,此时则需要对数据进行处理。
针对单一新增操作。我们只需要查库判断新库中是否存在数据即可。
针对单一修改操作。由于我们在存储数据时,会记录每条数据的数据修改时间,只需判断时间是否为最新时间点即可。
针对单一删除操作。我们只需要查库判断新库中是否存在数据即可。
针对用户先新增后删除且速度很快的操作。比如用户向新库新增一条数据,由于binlog消息的发送延迟、消费延迟以及网络抖动等因素,我们可能还未及时处理由旧库向新库同步的binlog消息,用户就已经删除了新库中的数据,而这时,我们收到旧库向新库同步的新增binlog消息,我们该如何处理呢?如果我们还是按照之前2.1的操作继续进行,则会陷入新旧库相互间处理数据的死循环中,因此我们对binlog消息进行打标,标记为非用户操作,使之与用户的操作进行区别。如果发现是binlog消息则不再继续处理。
步骤五:流量切到新库,去除对旧库的日志监听,对新库试运行一段时间。如果新库试运行期间,确认无任何问题后,即可去除对旧库的数据同步。
数据迁移过程中的注意点
由于同步的数据量比较大,需要时刻关注数据库的cpu使用率,避免数据库cpu过高影响线上服务的正常使用。
关注消息表中数据量的增长,防止数据量过大后产生慢sql,拖垮数据库的使用。
添加消息表,弥补数据写入过程中发生失败造成的数据丢失。
上线过程中出现新旧库同时监听数据而产生的双写入问题。
上线后如果出现问题需要切回旧数据源,需保证数据没有丢失。
领取专属 10元无门槛券
私享最新 技术干货