一. 解决缓存不命中(高并发操作击穿打挂DB的风险)
二. 如何使用Binlog实时更新Redis缓存(当没部署Mq时)
三. Canal详解与实战
四. 基于Binlog实现跨系统实时数据同步
五. 如何实现不停机更换数据库
六. 如何更安全地实现数据备份和恢复
binlog是mysql提供的数据同步机制,很好的解决了主从分离、读写库分离等业务。而我们可以构建一个中间件系统,“伪造”成master的一个slave。当读取了binlog中的数据变化后,根据相应的业务场景做各种业务处理。而目前我接触到的最常见的就是第一个场景——数据异构(数据一致),可以异构到其他表中,也可以异构到其他数据引擎中,比如Elastic Search/redis。
来自网络
binlog可能中使用Canal需要对DB的binLog特别了解,所以使用MQ来同步更为容易,可读性更高
这个方案就比较简单了,也是最常使用的。但是引入中间件增加了系统数据的链路和系统的复杂度。
所以我们在设计迁移方案的时候,一定要保证每一步都是可逆的。也就是必须保证,每执行完一个步骤,一旦出现任何问题,都能快速回滚到上一个步骤。这是设计这种升级类技术方案的时候比较容易忽略的问题。
3)然后上线新版的订单服务,这个时候订单服务仍然是只读写旧库,不读写新库。让这个新版的订单服务稳定运行至少一到两周的时间,其间我们不仅要验证新版订单服务的稳定性,还要验证新旧两个订单库中的数据是否保持一致。这个过程中,如果新版订单服务出现任何问题,都要立即下线新版订单服务,回滚到旧版本的订单服务。
3、稳定一段时间之后,就可以开启订单服务的双写开关了。开启双写开关的同时,需要停掉同步程序。这里有一个需要特别注意的问题是,这里双写的业务逻辑,一定是先写旧库,再写新库,并且以旧库的结果为准。
如果旧库写成功,新库写失败,则返回成功,但这个时候要记录日志,后续我们会根据这个日志来验证新库是否还有问题。如果旧库写失败,则直接返回失败,同时也不再写新库了。这么做的原因是不能让新库影响到现有业务的可用性和数据准确性。上面这个过程如果出现任何问题都要关闭双写,回滚到只读写旧库的状态。
切换到双写之后,新库与旧库的数据可能会出现不一致的问题。原因有两点:
一是停止同步程序和开启双写,这两个过程很难做到无缝衔接;
二是双写的第略也不能保证新旧库的强一致性。对于这个问题,我们需要上线一个比对和补偿的程序,用于比对旧库最近的数据变更,然后检查新库中的数据是否一致,如果不一致,则需要进行补偿。
开启双写之后,还需要稳定运行至少几周的时间,并且在这期间我们需要不断地检查,以确保不能有旧库写成功、新库写失败的问题。如果在几周之后比对程序发现新旧两个库的数据没有不一致的情况,那就可以认为新旧两个库的数据一直都是保持同步的。
4、接下来就可以用类似灰度发布的方式把读请求逐步切换到新库上。同样,运行期间如果出现任何问题,都要再切回到旧库。
5、将全部读请求都切换到新库上之后,其实读写请求已经全部切换到新库上了,虽然实际的切换已经完成,但后续还有需要收尾的步骤。再稳定一段时间之后,就可以停掉比对程序,把订单服务的写状态改为只写新库。至此,旧库就可以下线了。注意,在整个迁移过程中,只有这个步骤是不可逆的。由于这一步的主要操作就是摘掉已经不再使用的旧库,因此对于正在使用的新库并不会有什么影响,实际出问题的可能性已经非常小了。