随系统规模逐渐增长,总会遇到更换数据库问题。

  • 对MySQL分库分表后,需要从原来的单实例数据库迁移到新的数据库集群
  • 系统从传统部署方式向云上迁移的时候,也需要从自建的数据库迁移到云数据库
  • 一些在线分析类的系统,MySQL性能不够用的时候,就需要更换成一些专门的分析类数据库,比如说HBase

整个迁移过程,既不能长时间停服,也不能丢数据。如何不停机安全地迁移数据更换数据库。

1 不停机更换数据库

设计迁移方案的时候,要做到,每步都可逆。 要保证,每执行一个步骤后,一旦出现问题,能快速地回滚到上一个步骤 。以订单库为例子。

先把旧库数据复制到新库。因为旧库还在服务线上业务,所以不断会有订单数据写旧库,不仅要往新库复制数据,还要保证新旧两个库的数据是实时同步。要用一个同步程序,实现新旧两个数据库实时同步。

怎么实现两个异构数据库间的数据实时同步?Binlog实时同步数据。如果源库不是MySQL就麻烦,但也可以参考我们讲过的,复制状态机理论来实现。这一步不需回滚,只增加了一个新库和一个同步程序,对系统的旧库和程序都没有任何改变。即使新上线的同步程序影响到了旧库,只要停掉同步程序。

改造订单服务,业务逻辑部分不变,DAO层改造:

  • 支持双写新旧两库,并预留热切换开关,能通过开关控制三种写状态:只写旧库、只写新库和同步双写
  • 支持读新、旧两库,预留热切换开关,控制读旧库or新库

上线新版订单服务,订单服务仍只读写旧库,不读写新库。让这新版订单服务稳定运行至少1~2周,期间除验证新版订单服务稳定性,还要验证新、旧两个订单库中的数据是否一致。这个过程中,如果新版订单服务有问题,可以立即下线新版订单服务,回滚到旧版本的订单服务。

稳定段时间后,开启订单服务的双写开关,同时停掉同步程序。这个双写的业务逻辑,一定先写旧库,再写新库,并以写旧库的结果为准。

旧库写成功,新库写失败,返回写成功,但记录日志,后续用这日志验证新库是否还有问题。旧库写失败,直接返回失败,就不写新库。不能让新库影响现有业务可用性和数据准确性。上面这过程若出现问题,可关闭双写,回滚到只读写旧库状态。

切换到双写后,新、旧库数据可能存在不一致:

  • 停止同步程序和开启双写,这两个过程很难做无缝衔接
  • 双写策略也不保证新旧库强一致,这时候要上线一个对比和补偿程序,对比旧库最近数据变更,然后检查新库中的数据是否一致,若不一致,还要补偿

开启双写后,还要至少稳定运行几周,期间不断检查,确保不能有旧库写成功,新库写失败case。对比程序也没发现新旧两库数据有不一致,这时就可认为,新旧两库数据一直保持同步的。

接下来灰度发布把读请求切到新库。期间若初问题,可再切回旧库。全部读请求都切换到新库后,读写请求就已经都切换到新库,实际的切换已完成。

再稳定一段时间后,停掉对比程序,把订单服务写状态改为只写新库。旧库就可下线。整个迁移过程中,只有这步不可逆。但这步主要操作就是摘掉不再使用的旧库,对在用的新库并没有什么改变,实际出问题的可能性已非常小。

就完成在线更换数据库的全部流程。双写版本的订单服务也就完成了它的历史使命,可以在下一次升级订单服务版本的时候,下线双写功能。

2 实现对比和补偿程序

要对比的是两都在随时变换的数据库中的数据。没有类似复制状态机这样理论上严谨实际操作还很简单的方法。但还是可根据业务数据实际情况,针对实现对比和补偿,经过一段时间,把新旧两个数据库的差异,逐渐收敛一致。

订单这类时效性强数据,较好对比和补偿。因为订单一旦完成几乎不会再变,对比和补偿程序,就可依据订单完成时间,每次只对比这时间窗口内完成的订单。补偿逻辑简单:发现不一致,直接用旧库订单数据覆盖新库订单数据。

切换双写期间,少量不一致订单数据,等订单完成后,会被补偿程序修正。后续只要不是双写时,新库频繁写失败,就可保证两库数据完全一致。

麻烦的是更一般case

如商品信息随时可能变化。若数据上有更新时间,对比程序可利用这更新时间,每次在旧库取一个更新时间窗口内的数据,去新库找相同主键的数据对比,发现数据不一致,还要对比更新时间。若新库数据更新时间晚于旧库数据,可能对比期间数据发生变化,这种情况暂不补偿,放到下个时间窗口继续对比。时间窗口的结束时间,不要选取当前时间,而要比当前时间早点儿,如1min前,避免对比正写入的数据。

若数据连时间戳也没,只能去旧库读取Binlog,获取数据变化,去新库对比和补偿。

这些方法严格推敲都不是百分百严谨,都不能保证在任何情况下,经过对比和补偿后,新库数据和旧库完全一样。但大多数情况下,这些实践方法还是可以有效地收敛新旧两个库的数据差异,酌情采用。

设计在线切换数据库的技术方案,首先要保证安全性,确保每一个步骤一旦失败,都可以快速回滚。此外,还要确保迁移过程中不丢数据,这主要是依靠实时同步程序和对比补偿程序来实现。

切换过程按顺序:

  1. 上线同步程序,从旧库中复制数据到新库中,并实时保持同步;
  2. 上线双写订单服务,只读写旧库;
  3. 开启双写,同时停止同步程序;
  4. 开启对比和补偿程序,确保新旧数据库数据完全一样;
  5. 逐步切量读请求到新库上;
  6. 下线对比补偿程序,关闭双写,读写都切换到新库上;
  7. 下线旧库和订单服务的双写功能。
设计在线切换数据库的技术方案,首先要保证安全性,确保每一个步骤一旦失败,都可以快速回滚。此外,还要确保迁移过程中不丢数据,这主要是依靠实时同步程序和对比补偿程序来实现。上线同步程序,从旧库中复制数据到新库中,并实时保持同步;上线双写订单服务,只读写旧库;开启双写,同时停止同步程序;开启对比和补偿程序,确保新旧数据库数据完全一样;逐步切量读请求到新库上;下线对比补偿程序,关闭双写,读写都切换到新库上;下线旧库和订单服务的双写功能。
SQL Server 数据库 镜像是对于 数据库 可用性的软件 解决 方案 。镜像在每个 数据库 级别被部署,并只能在完整恢复模式下工作。由于磁盘空间的问题,需要移动镜像 数据库 到一个不同的位置。我们想不 停机 、不破坏镜像来完成这个任务。需要在不同的环境做测试。   对于启用了 数据库 镜像的 数据库 的文件移动,我们只有有限的选择。常规方法如下:   · 破坏 数据库 镜像会话,通过使用Alter database或Attach Detach移动在线 数据库 文件到一个新的位置。   · 备份 数据库 ,并在镜像服务器上恢复备份,然后重建镜像。   技术上来讲,这是可行的,但是它需要 停机 时间,并且尤其对于大 数据库 ,移动和恢复
系统随着业务的发展,系统技术选型和层级划分都会进行或大或小的调整,在系统调整过程中,沉淀下来的数据需要得到良好的梳理和传承,对于非流水的属性类数据,需要随着系统的重构重新迁移、组合,但是在线的系统不允许大规模的停服来配合迁移,这个时候需要一套热迁移或者准热迁移的 方案 ,下面我们来讨论下。 查了下类似的经验和 方案 ,主要分一下几类: 1、完全停服,全量部署至新服务、迁移至新数据源(单写) 推荐指...
对MySQL做了分库分表之后,需要从原来的单实例 数据库 迁移到新的 数据库 集群上 系统从传统部署方式向云上迁移的时候,也需要从自建的 数据库 迁移到云 数据库 上 一些在线分析类的系统,MySQL性能不够用的时候,需要 更换 成一些专门的分析类 数据库 ,比如HBase 更换 数据库 这个事儿,是一个非常大的技术挑战,因为我们需要保证整个迁移过程中,既不能长时间停服,也不能丢数据。 如何实现不 停机 更换 数据库 实际上,无论是新版本的程序,还是新的 数据库 ,即使我们做了
我已经进行了一段时间的连续交付讨论 ,在我的讨论中,我描述了一种如何在不 停机 的情况下安全地将一个 数据库 迁移到另一个 数据库 的模式。 由于许多人联系我并要求提供更多详细信息,因此,我将在此处按承诺提供更多详细信息。 您可以使用此模式在两个不同的 数据库 之间迁移,例如在MySql和MongoDB之间或同一 数据库 中的两个模式之间迁移。 此模式的想法是使用功能切换来进行懒惰的 数据库 迁移,以控制应...
mysql-在线迁移 以最少的 停机 时间将 数据库 表迁移到新服务器,并且不会丢失数据完整性。 在处理大型 数据库 系统时,有时需要将表从一台服务器移动到另一台服务器,并且中断最少。 此工具允许将大量数据作为 csv 文件导入,而无需锁定源表。 批量加载时对表的任何更改都使用触发器记录,然后可以针对新表重播。
数据迁移时, 为了保证数据的一致性, 往往伴随着停服, 此期间无法给用户提供服务或只能提供部分服务. 同时, 为了确保迁移后业务及数据的正确性, 迁移后测试工作也要占用不少时间. 如此造成的损失是比较大的。 接下来, 本文将就如何在不停服的情况下进行数据迁移进行探讨。 订单系统中存在这样一组订单表: 数据库 : MySQL 表名: order_{0~19}, 其中...