如何保证业务变更的可回滚性

背景

采用快速迭代的开发方式的互联网公司常常一天之内要对线上业务做多次变更,如果在变更业务后出现了伤害用户体验或影响收入的意外情况,最简单快速的解决方法就是将线上业务回滚到变更前的状态。保证业务变更的可回滚性,对于控制风险和保障开发人员的安全感,都有重要的意义。本文介绍了几种保证业务变更可回滚的方法。

将代码和配置整体打包

如果将代码和配置分开部署,在回滚的时候就会遇到"应该是先回滚代码还是回滚配置"的难题,所以,要想轻松回滚,在部署的时候,一定要将代码和配置整体打包。在具体的实践方式上,我强烈建议采用容器化部署,在CI系统中将变更后的代码和配置build为一个docker image, 并给不同版本的容器打上不同的tag, 通过切换tag便能实现整体服务的快速回滚。

引入中间版本

对于单体应用,采用容器化的手段将代码和配置整体打包部署就能很好的保证可回滚性,但是,这仅是一个过度简化的模型,实际的线上系统则要复杂许多,一般都是由有依赖关系的多个子服务构成。例如,前端web系统会访问后端数据服务,后端数据服务会访问数据库,或者给批量作业系统下发任务。对于这种有依赖关系的变更,怎样开发和部署才能如何保证可回滚性?

首先,系统设计要保证调用的单向性,即如果服务A调用了服务B,那么服务B一定不会调用服务A。在满足单向调用的前提下,可以使用下列方法来保证可回滚性。

例如,有两个子服务A和B,服务A会调用服务B,业务需求需要同时将A变更为A'和将B变更为B'才能实现。

初始状态: A -> B

最终状态: A' -> B'

但是,由于A'和B以及A和B'的实现不兼容,所以不能出现A -> B'或A' -> B的中间状态。

解决办法:

  1. 将B变更为B'',B''可以同时兼容A和A',即A -> B''与A' -> B''均成立, 此时系统状态变为A -> B'',如果发现问题,可回滚成状态A -> B
  2. 将A变更为A', 此时系统状态变为A' -> B'',如果发现问题,可回滚成状态A -> B''
  3. 将B''变更为B', 此时系统状态变为A' -> B', 顺利抵达最终状态,并且切换过程平滑, 如果发现问题,可回滚成状态A' -> B''

综上可见,通过引入中间版本B'',就能保证对存在依赖关系的两个子服务的变更的可回滚性。

举个具体的例子,当前的用户登录系统只要求输入用户名和密码,由前端系统将用户名和密码发送给后端系统进行验证,现在,需要在用户登录时输入验证码。显然,这一改进需要前后端系统一起配合才能实现:

  • 前端系统的界面要加入验证码的图片显示和输入框,并且调用验证接口时需加入验证码参数
  • 后端系统的验证接口需提供对验证码参数的支持

应用前面的解决办法可以得出下面的开发和部署步骤:

  1. 修改后端系统的验证接口,加入对验证码参数的支持,但为了兼容不带验证码的前端系统(版本A),验证码参数是 可选
  2. 上线修改后的后端系统(版本B''),观察是否与A兼容,如果有问题,回滚到版本B
  3. 修改前端系统,显示验证码图片和表单字段,在调用验证接口时传入验证码参数
  4. 上线修改后的前端系统(版本A'),观察该版本是否工作正常,如果有问题,回滚到版本A
  5. 在前端A'和后端B''工作正常后,再修改后端系统的验证接口,将验证码参数由可选改为 必需
  6. 上线修改后的后端系统(版本B'),如果工作正常,业务变更完成;如果有问题,回滚到版本B''

数据迁移的处理

在业务变更涉及数据迁移时,应对数据表的字段采取"只增不删"的原则。原因很简单,当某个字段被当前代码引用的字段被删除后,线上业务是会出问题的,但新增一个没有被当前代码引用到的字段,则不会有问题。

等到确认新版代码工作完全正常,不会再回滚到旧版本时,才将旧字段删除。一旦旧字段被删除,引用到旧字段的旧版本代码就无法工作,也就无法回滚到旧版本了。

总结

  • 使用容器化部署,代码和配置可以整体回滚
  • 通过引入中间版本,让有依赖关系的系统可以分开独立回滚
  • 数据迁移时,不能删除字段,要等到确认新版代码工作正常,无需回滚到旧版时才能删除
时间: 2024-10-29 00:46:55

如何保证业务变更的可回滚性的相关文章

大数据开发套件中数据同步-日志报错回滚信息的一些问题总结

在使用大数据开发套件时最常用的就是数据同步模块,工单里最常见的问题就是其中数据同步的问题,这里总结一些常见一些从MaxCompute(原名ODPS)到其他数据源的同步任务报错案例,主要是日志中出现数据回滚写入的问题. 那首先看下日志中数据回滚的原因,当数据写入rds或者hybridDB等一些支持事务的数据库中,数据批量写入,一旦由于各种原因没有写入成功,这个批次的数据会回滚重新写入,如果再次写入失败,就会报脏数据的错误导致任务失败.数据写入失败可能是以下原因导致回滚.1,脏数据(数据值超过数据类

mysql 回滚-spring3+mybatis+myql事务不生效

问题描述 spring3+mybatis+myql事务不生效 代码格式为 @Transactional(rollbackFor=java.lang.Exception.class, propagation=Propagation.REQUIRED, readOnly=false) public void excuDevOrAppPagRel(DevPackageRln devPackageRln) throws Exception{ //具体操作,无try-catch操作 } mysql所有表的

spring 事务管理 手动回滚策略

问题描述 如果我不用spring的事务代理机制,直接在service代码中进行事务的提交或者回滚处理,那么一般是这样的处理逻辑-->主要有2点:即1:事务流程中,某一节点的数据(正常返回)遇到某值时,进行回滚,执行结果中说明情况.2:事务流程中,try catch 所有的代码-->保证遇到运行时异常,或者error的时候,进行回滚现在要用spring的事务管理了,导致在处理提到的第一个情况的时候有个问题,不知道如何解决就是spring所管理到的业务代码方法,必须要抛出指定异常,才可以回滚那么,

PostgreSQL 10.0 preview 功能增强 - 回滚范围可精细控制(事务、语句级)

标签 PostgreSQL , 10.0 , 事务回滚 , 语句回滚 , 服务端特性 背景 数据库的原子操作单位是事务,那么在一个事务中的SQL,正常情况下,应该是这样的:要么全部提交,要么全部回滚. 为了保证持久性,数据库还有一个概念,事务日志,每当事务提交时,都需要确保REDO持久化(REDO的写IO会比较多,IO延迟直接关系到tps吞吐量,特别是小事务). 因此,有些业务,为了提高整体的吞吐(比如数据插入的吞吐),通常会使用分批提交的方式,比如一个事务中封装1000条INSERT语句. 但

java-银行交易如何实现类似事务回滚

问题描述 银行交易如何实现类似事务回滚 在做的项目中,有一个基金产品的购买交易,里面的大致逻辑是 先判断用户是否基金开户,未开户发交易开基金账户>是否签约***(具体什么省略) 未签约发交易签约>最后一步发交易购买该款基金产品. 但现在的问题是购买失败则一个java类里的前两个交易都给做了现在,想不出什么类似操作数据库的事务回滚机制才控制这段交易,该交易在一个页面完成.望经验丰富的朋友给个思路,谢谢! 解决方案 你可以使用应用层的事务框架,或者自己实现一个简单的:先将操作放入临时的表中,然后一

ORACLE回滚段的概念,用法和规划及问题的解决

oracle|概念|规划|解决|问题      回滚段管理一直是ORACLE数据库管理的一个难题,本文通过实例介绍ORACLE回滚段的概念,用法和规划及问题的解决. 回滚段概述 回滚段用于存放数据修改之前的值(包括数据修改之前的位置和值).回滚段的头部包含正在使用的该回滚段事务的信息.一个事务只能使用一个回滚段来存放它的回滚信息,而一个回滚段可以存放多个事务的回滚信息. 回滚段的作用 事务回滚:当事务修改表中数据的时候,该数据修改前的值(即前影像)会存放在回滚段中,当用户回滚事务(ROLLBAC

ORACLE回滚段管理

oracle 回滚段管理一直是ORACLE数据库管理的一个难题,本文通过实例介绍ORACLE回滚段的概念,用法和规划及问题的解决. 回滚段概述 回滚段用于存放数据修改之前的值(包括数据修改之前的位置和值).回滚段的头部包含正在使用的该回滚段事务的信息.一个事务只能使用一个回滚段来存放它的回滚信息,而一个回滚段可以存放多个事务的回滚信息. 回滚段的作用 事务回滚:当事务修改表中数据的时候,该数据修改前的值(即前影像)会存放在回滚段中,当用户回滚事务(ROLLBACK)时,ORACLE将会利用回滚段

ORACLE回滚段管理(上)

oracle 回滚段管理一直是ORACLE数据库管理的一个难题,本文通过实例介绍ORACLE回滚段的概念, 用法和规划及问题的解决. 回滚段概述 回滚段用于存放数据修改之前的值(包括数据修改之前的位置和值).回滚段的头部包含正 在使用的该回滚段事务的信息.一个事务只能使用一个回滚段来存放它的回滚信息,而一个回滚 段可以存放多个事务的回滚信息. 回滚段的作用 事务回滚:当事务修改表中数据的时候,该数据修改前的值(即前影像)会存放在回滚段中,当用 户回滚事务(ROLLBACK)时,ORACLE将会利

ORACLE 回滚段表空间数据文件丢失或损坏处理方法(2)

oracle|数据 续上文:http://www.csdn.net/Develop/read_article.asp?id=20220 II. 数据库是启动着的 如果你检测到丢失或损坏了回滚段表空间的数据文件,并且数据库是运行着的,不要把它down掉.在很多情况下,数据库是启着的比关闭着解决问题更容易些. 这种情况的两种可能的解决方法: A)使丢失的那个数据文件offline,并从备份中恢复它,这种情况适用于数据库是处于归档方式的. B)另一个方法是offline掉所有的那个文件所属表空间的回滚