左耳听风_047_46_弹力设计篇之补偿事务
你好,我是陈浩网名做耳朵house.那之前呢我们说过,分布式系统呢有一个比较明显的问题,就是一个业务流程需要组合一组服务。
那这样的事情啊在微服务下就更为明显了。
因为这个需要业务上一致性的保证。
也就是说呢如果一个步骤失败了,那么要么回滚到以前的服务调用,要么呢不断重试,保证所有的步骤都成功。
那这里呢如果需要强一致性,那在业务层上就需要使用两阶段提交这样的方式。
但是呢好在我们很多情况下并不需要这么强的一致性,而且强一致性的最佳保证基本上都是在底层完成的。
或者呢像之前说的stateful sticking session那样,在一台机器上完成。
在我们接触到的大多数业务中呢啊其实只需要最终一致性就够了。
那谈到这里呢,有必要先说一下ACID和BASE的差别。
那传统关系性数据库系统的事物呢都有SID属性,也就是原子性atomaity、一致性、coninstency、隔离性isolation,还有持久性neurability.那接着呢我逐一做一下解释。
那所谓原子性能,就是整个事物中的所有操作,要么全部完成,要么全部失败,不能停滞。
在中间某个环节,事物在执行过程中发生错误会被回滚到啊,也就是roll back到事物开始前的状态,就像这个事物从来没有被执行过一样。
那一致性呢就是事物在开始之前和事物结束之后,数据库的完整性约束没有被破坏。
而隔离性呢指的是两个事物的执行,是互不干扰的。
一个事物不可能看到其他事物运行时中间某一时刻的数据。
那两个事物呢不会发生交互。
最后呢持久性就是说事物在完成之后,这个事物对数据库所做的更改就会持久的保存在数据库之中,并不会被回滚。
那事物的ACID属性保证了数据库的一致性。
比如说在银行系统中转账呢,就是一个事物,从原账户扣除金额和向目标账户添加金额。
那这两个数据库操作的总和构成一个完整的逻辑过程啊,是不可拆分的原子操作,从而保证了整个系统中的总金额没有变化。
但是呢这对于我们的分布式系统来说啊,尤其微微服务来说,那样的方式呢是很难满足高性能要求的。
我们呢都很熟悉CAP理论,就是在分布式的服务架构中啊一致性。
可可性性还分区容忍性在现实中啊不能都满足,那最多呢只能满足其中两个。
所以呢为了提高性能,就出现了ACID的一个变种BASE.那其中的BA呢指的是basic availability,意思是基本可用。
那这个呢就意味着系统可以出现暂时不可用的状态,而后面呢会快速恢复。
而s指的是soft state,意思是软状态。
它是我们前面有状态和无状态的服务的一种中间状态。
也就是说呢为了提高性能,我们可以让服务暂时保存一些状态或者数据。
那这些状态和数据啊不是强一致性的那第三点呢是evantual, coninstancy意思是最终一致性系统在一个短暂的时间段之内呢是不一致的。
但是最终整个系统看到的数据呢是一致的那可以看到BASE系统是允许或者容忍系统出现暂时性问题了。
那这样一来呢,我们的系统就能更有弹力。
因为我们知道在分布式系统的世界里,故障呢是不可避免的。
我们能做的呢就是把故障处理当做成功,能够写入代码中。
那这个呢就是design for failure.那BASE的系统倾向于设计出更加有弹力的系统。
那这种系统的设计特点呢在于要保证在短时间内,就算是有数据不同步的风险啊,我们也应该允许新的交易可以发生。
而后面呢我们在业务上把可能出现问题的事物啊给处理掉,来保证最终的一致性。
那这里呢我举一个网上卖书这个场景的例子。
那ACID的玩法呢,就是大家在买同一本书的过程中呢,每个用户的购买请求都需要把库存锁住,等解完库存之后呢,把锁释放出来。
那后续的人呢才能进行购买。
我们在ACID的玩儿法之下,我们在同一时间啊就不可能有多个用户下单。
我们的订单流程呢需要有排队的情况。
那这样一来呢,我们就不可能做出性能比较高的系统来。
而BASE的玩法呢就是大家可以同时下单。
那这个时候呢不需要去真正的分配库存,然后系统异步的处理订单,而且啊是批量的处理。
因为下单的时候啊,没有去真正的扣减库存,所以呢就有可能出现超卖的情况。
而后台的系统啊异步处理订单的时候,发现库存没有了,于是呢才会告诉用户啊,你没有购买成功。
那BASE的这种玩儿法其实就是亚马逊的玩法。
因为要根据用户的地址去不同的仓库查看库存。
那这个操作非常耗时,所以呢不想做成异步的都不行。
在亚马逊上买东西的时候呢,你会先收到一封邮件啊,说系统收到你的订单了。
然后过一会儿呢你会收到你的订单被确认的邮件。
那这个时候呢才是真正的分配了库存。
所以有些时候呢,你可能会先收到下单的邮件,那过一会儿呢又收到了没有库存的致歉的邮件。
那有趣的是ACID啊,也就是acid,它的意思是酸,而BASE base啊却是碱的意思。
所以呢这是一个对立的东西。
那其实啊从本质上来讲,虽然强调的是一致性,也就是CAP中的c而减呢强调的是可用性,是CAP中的a那接着呢我们来谈一谈业务补偿,有了对acid和base的分析。
我们知道在很多情况下,我们是无法做到强一制性的acid.那特别是我们需要跨多个系统的时候,而且啊这一系统还不是由一个公司所提供的。
比如在我们的日常生活中呢,我们会经常遇到这样的情况,就要找很多方案,协调很多事儿,而且还要保证我们每一件事儿都成功,否则呢整件事儿就做不到。
比如呢我要出门旅游,我们呢就需要干这么几件事儿。
那第一呢向公司请假拿到相应的假期。
那第二呢,订飞机票或者火车票,第三订酒店,第四是租车。
而这四件事中呢,前三件必须完全成功,我们才能出行。
而第四件事呢是一个锦锦添添花事儿。
但是第四件事儿一旦确定,那么也会成为整个事物中的一部分。
那这些事啊都是要向不同的组织或者系统去请求,我们可以并行的做这件事儿。
但是呢如果某个事儿有变化,那其他的事儿都会跟着出现一些变化。
我们设想以下的几种情况,那第一种情况我没有订到返程机票,那么呢我就去不了了。
我需要把订到的去程机票,还有酒店,还有租到的车都给取消了,而且呢还要把请的假也取消了。
那第二种情况呢,是如果我假也请好了,机票和酒店也订好了啊,只是车没有租到,那么并不影响我出行这个事儿。
整个这个事儿还是可以继续的那第三种情况呢,是我的飞机,因为天气原因取消或者晚点了。
那么我呢就要被迫去调整和修改我的酒店预定和租车的预定。
从人类的实际生活当中呢,我们可以看出上面的这些情况都是天天在发生的事情。
所以呢我们的分布式系统啊也是一样的,也是需要处理这样的事情啊。
就是当条件不满足或者有变化的时候,需要从业务上做相应的整体事物的补偿。
那一般来说呢,业务的事务补偿都是需要有一个工作流引擎的。
亚马逊呢是一个超级喜欢工作流引擎的公司。
那这个工作流引擎啊把各式各样的服务给串联在一起,并在工作流上做相应的业务补偿。
那整个过程呢设计成了最终一致性的那对于业务补偿来说呢,首先需要将服务做成密等性的那如果一个事物失败了或者超时了,我们需要不断的重试啊,努力的达到我们最终想要的状态。
然后呢,如果我们不能达到这个我们想要的状态,我们需要把整个状态恢复到之前的状态。
那另外呢,如果有变化的请求,我们需要重新启动整个事物的业务更新机制。
所以呢一个好的业务补偿机制啊需要做到这些点。
首先呢要能清楚的描述出要达到什么样的状态。
那还有呢如果其中的条件不满足,那么我们要回滚到哪一个状态,那这个呢就是所谓的整个业务的起始状态定义。
那其次呢当整条业务跑起来的时候,我们可以串行或者并行的做这些事儿。
那对于旅游机票呢是可以并行的,但是对于网购流程呢是不能并行的。
所以呢我们的系统需要努力的通过一系列的操作达到一个我们想要的状态。
那如果达不到呢,就需要通过补偿机制回滚到之前的状态,那这个呢就是所谓的状态拟合。
另外呢对于一个已经完成的事物进行整体修改,可以考虑成一个修改拟合。
那其实呢在纯技术的世界里啊,也有这样的事儿。
比如线上运维系统啊需要发布一个新的服务,或者呢对一个已有的服务进行水平扩展。
我们呢就需要先找到相应的机器啊,然后初始化环境再部署上应用,在做相应的健康检查。
啊,最后呢接入流量,那这一系列的动作都要完全成功。
所以我们的部署系统啊就需要管理好整个过程和相关的运行状态。
那以上呢,我们简单介绍的业务补偿。
那什么是业务补偿的设计重点呢?业务补偿呢主要做了两件事儿,一是努力的把一个业务流程执行完成。
那二呢,是如果执行不下去啊,需要启动补偿机制,回滚业务流程。
所以呢业务补偿的重点有这么几个。
那第一呢,因为要把一个业务流程执行完成,需要这个流程中所设计的服务方支持密等性,并且要在上游啊有重试计时。
那第二呢,我们需要小心的维护和监控整个过程的状态。
所以呢千万不要把这些状态放在不同的组件中。
那最好啊是一个业务流程的控制方来做这个事儿啊,也就是一个工作流引擎。
所以这个工作流引擎呢是需要高可用和稳定的这就好像旅行代理机构一样,我们把需求告诉他他会帮我们搞定所有的事儿。
那如果有问题呢,也会帮我们回滚和补偿的那第三呢,补偿的业务逻辑和流程不一定非得是严格的反向操作,有时候呢可以并行,有时候可以串行,可能会更简单。
总之呢设计业务正向流程的时候啊,也需要设计业务的反向补偿流程。
第四呢,我们需要清楚的知道业务补偿的业务逻辑啊是强业务相关的,很难做成通用的。
最后呢业务补偿的第五个重点下层的业务方最好提供短期的资源预留机制。
那就像是在电商中啊,把货品的库存预先占住,等待用户在十五分钟内支付。
那如果没有收到用户的支付呢,就释放库存,然后回滚到之前的下单操作,等待用户啊重新下单。
好了,我们来总结一下今天分享的主要内容。
那首先呢我介绍了ACID和BASE两种不同级别的一致性,在分布式系统中呢ACID有更强的一致性。
但是可伸缩性呢非常差啊,仅在必要的时候才使用,而BASE的一致性呢比较弱。
但是呢有很好的可伸缩性,还可以异步的批量处理。
那大多数分布式事物啊适合BASE,那要实现BASE事物呢需要实现补偿逻辑,因为事物可能会失败。
那这个时候呢就需要协调各方进行撤销补偿的各个步骤呢,可以根据具体的业务来确定是串行还是并行。
由于补偿事务是和业务强相关的,所以必须实现。
在业务逻辑里,在下一节课呢,我们会讲述重式设计。
那希望能对你有帮助,也欢迎你分享一下你的分布式服务用到了怎样的一致性能。
你是怎么实现补偿事务的呢?文末呢我给出了分布式系统设计模式系列文章的目录,希望你能在这个列表里啊找到自己感兴趣的内容。