干货!如何平稳用户无感知的完成系统重构升级

前言

咱们在实际开发系统的过程中,颇有可能会遇到须要进行系统重构升级的状况,须要重构的缘由多是以前的设计不合理,致使如今维护起来很是的困难,也有多是如今的业务发展很是迅速,须要进行分库分表了又或者以前用的是单机的本地的文件存储,如今须要用到统一的网络存储。总而言之,就是当初的系统设计已经不符合如今发展须要了,须要进行重构和升级。php

而这其中会可能会涉及到代码逻辑的变动,数据存储的变动(如DB或者文件存储等)或者第三方接口的变动。在这样一个新旧的切换过程中,怎么样才能让用户无感知,平稳地进行过渡?segmentfault

有人说可能说能够停服,而后迁数据,迁完后切新逻辑,然而先不说会有一段不可接受的不可用时间,就说在迁移过程当中,咱们如何保证能一次迁移成功呢?再退一步,就算数据迁移成功了,可是若是代码逻辑有漏洞,咱们又该如何快速回退到旧版本呢?这可不仅仅是切回旧代码就行了,要知道这段时间可能产生了新版本的数据,这些新数据可也要迁回旧版本。网络

重构升级系统的过程可能会遇到这么多问题,那咱们有什么办法能够平稳且用户无感知地完成系统升级吗?今天就给你们提供一个通用的系统重构升级的框架。里面不少具体的逻辑得按不一样系统的实际状况来,可是总体思路倒是通用且可靠的。框架

场景模拟

咱们先来模拟一个简单的场景,并看看实际状况中应该如何操做。测试

假设咱们一开始有个users表存储学生数据,表结构以及一些数据以下:设计

id name age
1 张三 18
2 李四 19
3 王五 17

后面随着业务发展,咱们须要记录学生的语文成绩,而后咱们在users表加了score字段,以下code

id name age score
1 张三 18 98
2 李四 19 76
3 王五 17 80

过一段时间咱们发现又须要记录数学分数了,后面还可能须要记录英语分数等等。这时候不可能一次次加字段,现有的表设计又极不知足咱们的需求,因此只好对如今的系统进行重构升级了。咱们想用两个表来存数据:接口

students开发

id name age

mark表get

id type user_id score

这时候咱们会面临几个问题:

  • 代码逻辑的切换:包括增删改查
  • 表结构的变动
  • 数据的迁移
  • 迁移过程当中用户无感知

如何来升级呢?

步骤

  1. 在旧代码的增删改查的地方写好新逻辑和建好新的表,可是一开始线上并不调用新逻辑和写入新表,仅仅在测试环境调用和写入,线上仍调用旧逻辑。如:

    if($is_dev){
      //新逻辑:如增删改查students表和mark表
    }else{
      //旧逻辑:如增删改查users表
    }
  2. 测试新逻辑没问题了,线上同时双写新旧表(包括增删改),如:

    //新写入逻辑:如增删改students表和mark表
    //旧写入逻辑:如增删改users表
    
    
    if($is_dev){
      //新读取逻辑:如查students表和mark表
    }else{
      //旧读取逻辑:如查users表
    }
  3. 进行数据迁移,把原来users表的数据迁到students表和mark
  4. 而后让系统运行一段时间,而后再对users表和students表、mark表的数据进行对帐,若是有数据不一致的状况,说明咱们以前双写的时候有遗漏的地方,须要补全,若是没有不一致,说明咱们写入的地方都已经对齐了,如今新旧数据是已经能一直保持一致了,那下面就是切读的地方了。
  5. 把读的地方改为只读新的,以下

    //新写入逻辑:如增删改students表和mark表
    //旧写入逻辑:如增删改users表
    
    //新读取逻辑:如查students表和mark表
  6. 系统运行一段时间,没发现问题以后把写的改为只写新的,以下

    //新写入逻辑:如增删改students表和mark表
    
    //新读取逻辑:如查students表和mark表

完成以后咱们的系统就平稳的完成迁移了。

分析

整个过程可能看起来很繁琐,不要紧,咱们一步一步来分析其必要性。

  • 第一步是先写好新逻辑,并进行充分的测试,这固然是必要的啦,算是升级前的准备
  • 第二步是咱们升级的起始步骤了,咱们须要双写数据。在代码发布过程当中,即便有的访问到了新代码双写了,有的仍是访问旧代码单写也不要紧,由于会有第三步数据迁移的过程。这一步和第三步是为了保证数据无感知迁移(不用停服迁移数据),保证迁移后数据的一致性。
  • 第四步是对帐过程,是为了找出咱们写入遗漏的地方,这是由于咱们不能保证对于一个庞大的系统,你一次改造就能改到了全部的地方,因此留一段时间对写入进行对帐是很是有必要的,有则改之。
  • 上面的第四步保证了咱们新旧的数据已是一致的了,这时候第五步咱们就能够很放心的把咱们读从旧的地方改到读新的地方了。
  • 第六步也是很重要的,咱们要先让系统平稳运行一段时间再切成单读新表,由于这个过程当中,若是咱们发现系统新逻辑有问题,咱们能够不少地切回读旧逻辑,由于咱们写入仍是双写的,旧数据仍是有写入,直接切回去是没有问题的。这就避免了没法回滚,或者回滚后数据丢失的问题。
  • 注意第五步和第六步最好分开进行,也就是说不要一次就改单读和单写,否则在发布代码的过程当中,某些机器仍是旧代码,这是用户访问系统的时候可能先访问到新机器写入了数据,而后又访问到旧机器读的是旧表,这时候就会读不到刚写入的数据。这种临界状况虽然极端,可是在大访问量的基数仍是可能出现的

总结

能够看到,上面的系统升级重构的思路是比较细致的,可是确实是很是平稳,且不须要停服就能完成升级,即便系统很是的复杂,升级重构的逻辑和存储结构大变样也能适用。固然在实际过程当中你们也能够根据实际状况(小系统小改动)进行一些步骤的合并或者缩短期。

版权声明

转载请注明做者和文章出处
做者: X先生
http://www.javashuo.com/article/p-hufrzoqx-nk.html

以为不错的话请帮忙收藏点赞~

相关文章
相关标签/搜索