外贸流程询盘发盘,网站常用的优化方法,本地wordpress 上传,建设属于哪里今天啊#xff0c;本片博客我们一起来学习一下微服务中的一个重点和难点知识#xff1a;分布式事务。
我们会基于Seata 这个框架来学习。
1、分布式事务问题
事务#xff0c;我们应该比较了解#xff0c;我们知道所有的事务#xff0c;都必须要满足ACID的原则。也就是 …今天啊本片博客我们一起来学习一下微服务中的一个重点和难点知识分布式事务。
我们会基于Seata 这个框架来学习。
1、分布式事务问题
事务我们应该比较了解我们知道所有的事务都必须要满足ACID的原则。也就是 在我们以前所学习的单体架构当中的这个服务直接访问一个数据库业务比较简单。基于数据库本身的特性就已经能够实现ACID了。
但是我们现在要研究的是微服务。微服务的业务往往比较复杂可能一个业务啊就会跨越多个服务而每个服务又会有自己的数据库。
这个时候你再靠数据库本身的特性还能保证整个业务的ACID吗这可就不一定了。
我们来看一个例子啊。 比方说我这里有一个微服务它里边啊包含三个服务啊有订单有账户和库存。
现在我们有一个用户下单的业务用户下单时我希望订单服务去创建订单并且写入数据库。
然后他再去调用账户服务和库存服务账户服务呢去扣减用户的余额而库存服务呢则去扣减商品库存。
那你可以看到这个业务里边就包含了三个不同的微服务的调用而每个微服务都有自己独立的数据库也就是独立的事务。
那我们最终希望的肯定是我这个下单业务一旦执行每一个是不是都要成功当然如果你失败是不是大家都失败
1.1 演示分布式事务问题
结果是这样一个的结果但是能不能达到这样一个效果我们来验证一下。
微服务结构如下 其中
seata-demo父工程负责管理项目依赖
account-service账户服务负责管理用户的资金账户。提供扣减余额的接口storage-service库存服务负责管理商品库存。提供扣减库存的接口order-service订单服务负责管理订单。创建订单时需要调用account-service和storage-service
我们先来看一下这个order订单服务。看下它里边的业务逻辑啊在controller里边啊我们可以看到一个创建订单的接口。 在controller当中呢它就调了service所以我们进去入service方法。 在这个service方法当中 我们可以看到它先去创建订单把这个订单数据直接写到数据库当中。
那创建完订单了就去调用accountClient 扣用户余额和storageClient扣库存完成扣余额和扣库存。
accountClient 和 storageClient 是通过 Feign调用的。 这是这三张表的数据。
业务逻辑就是这样的了我们接下来使用Postman去做一下测试。 我们发送请求。 返回了500我们看一下数据库。 发现用户余额少了200。 订单并没有创建 库存也没有减少。
这个时候事务的状态是一致的吗不是吧
那为什么会这样子呢
那在刚才的业务当中我们的订单服务去创建了订单。
然后去调用账务服务和库存服务完成余额扣减和库存扣减。
其中订单和账务服务啊都执行成功了。 而库存服务在执行的时候却因为库存不足而报错了。 那按照理论上讲这里一报错前边是不是都应该跟着回滚啊但是我们所看到的结果是库存服务失败了账户的余额该扣还是扣了为什么呢
第一我们的每一个服务都是独立的。
那现在库存服务你抛了异常。
账户服务它知不知道它是不知道的呀
那我都不知道你抛异常了我去回滚什么呢
第二每一个服务是独立的所以他们的事务呢也是独立的。
那现在我订单服务和账务服务我执行完业务以后我事务结束了我是不是直接就提交了呀
现在你让我回滚我怎么回滚我事都办完了提交了就撤销不了了。
所以最终就没有达成事务状态的一致那么这个时候啊就出现了分布式事务的问题了
1.2 什么是分布式事务 那我们总结一下什么是分布式事务。 在分布式系统下一个业务它跨越了多个服务和数据源。每一个服务都可以认为是一个分支事务而我们要保证的是所有分支事务最终状态一致。
要么大家都成功要么大家都失败。那么这样的一种事务就是分布式事务了。 那为什么分布式事务出现了问题 就是因为各个服务之间或者说各个分支事务之间互相是感知不到的大家各提交各的那将来呀就无法去回滚就导致状态无法一致。
2、理论基础
接下来我们就进入分布式事务理论基础的学习。
解决分布式事务问题需要一些分布式系统的基础知识作为理论指导。
2.1 CAP定理
CAP定理是1998年啊加州大学的计算机科学家Eric Brewer 提出的那它说分布式系统里边往往有三个指标。
分别是 Consistency一致性Availability可用性Partition tolerance 分区容错性 那艾瑞克说呢这三个指标啊分布式系统它不可能同时满足。
你像这三个圆不就是分别三个特性吗 但是你看这三个圆不会出现三个同时重叠啊最多就是两两重叠。
那么这个结论就叫CAP定理了。那为什么会出现这样一个情况呢
我们必须得先弄清楚啊一致性可用性和分区容错性代表的含义才能理解这个其中含义。
2.1.1.一致性 那我们先来看一下其中的第一个一致性。 一致性是说用户在访问分布式系统中的任意节点时得到的数据必须是一致的。比方说我现在有两个结点。 那第一个结点上面有一个数据叫data值是v0第二个结点上也是如此。那它们其实就形成了一个什么呢主从。
现在用户去访问这两个节点啊不管访问的是谁拿到结果是不是都一样的 但是呢现在如果我对node 1节点的数据发生了修改。 这个时候两个节点数据是不是就不一样了
那为了满足一致性你要做什么
你是不是一定要把node 01的数据同步给node 02啊 一旦两者的数据同步完成数据是不是再次一致了所以呢作为一个分布式系统。
在做数据备份的时候你一定要及时的去完成数据同步这样才能满足一致性。
2.1.2.可用性 第二个概念可用性。 它说用户在访问集群中的任意健康节点的时候啊必须得到响应而不是超时或者拒绝。
比方说我现在这个集群里就有三个节点啊。 正常情况下用户访问任何一个是不是都没问题。 现在啊这三个节点没有出现宕机的情况。但是不知道什么原因啊比如说这个node3它的请求就会被阻塞或者拒绝了。 那所有请求进来根本就无法访问了。这个时候node3不就不可用了。所以可用性是指这个节点能不能被正常的访问。
2.1.3 分区容错 第三个概念 分区容错。 分区是指因为网络的故障或者其他原因导致分布式系统中的部分节点与其他节点失去了连接形成独立分区。
比方说还是这三个节点啊node 123。 然后用户呢可以访问其中任意一个。
但是因为网络出现了故障机器没有挂然后node 3与node 1和node 2之间断开了连接。 node 1node 2正常访问啊它们之间是能够感知到对方的但node 3感知不到了。所以呢此时整个集群就会被划分成两个区了。
那node1和node2它们俩是一个区node3自己是一个分区。
这个时候如果有用户向node 02写入了一个新的数据。 那node 02是可以把数据同步给node 01的。 但是那么node 3上面有没有同步
显然没有因为他们感知不到了怎么去做同步
那这两个分区数据就不一致了。
那分区容错是什么意思呢
容错就是不管集群有没有出现分区啊整个系统也要持续对外提供服务。
2.1.4.矛盾
那也就是说尽管你这儿分区了那用户该访问是不是还要访问呢
但是如果我现在去访问node1我拿到的结果和访问node3拿到结果一样吗不一样。
所以出现了数据不一致的情况没有满足一致性。那如果我一定要满足一致性。
我应该怎么办那我是不是可以这么做
我让node 3它等待node 2这个网络的恢复和数据的同步。
在恢复之前。所有来访问我的请求我都阻塞在这里说你们等等我这数据还没好。
可不可以
那如果这么做我是不是就能够满足数据的一致性了但是你的node3明明是一个健康的节点结果进来的请求你都卡在这里不让人家访问了。
那node3不就变成不可用了吗所以它就不满足可用性了。
所以你现在就会发现当网络出现分区时可用性和一致性是不是没有办法同时满足但是呢这个分区它又是不可避免的。
为什么这么说呢
只要你是一个分布式系统你的节点之间是不是一定是通过网络连接的而你只要是通过网络连接的你有没有办法保证网络100%永远是健康的
这不可能吧
所以我们可以认为凡是分布式系统分区一定会出现既然分区一定会出现。
而你整个集群又必须要对外提供服务那也就认为. Partition tolerance 分区容错性一 定要实现那么这个时候Consistency一致性和 Availability可用性之间你是不是要做出抉择了你要么Consistency要么Availability。没有办法同时满足啊 这也就是CAP 定理的一个原因了。
2.2 BASE理论
我们已经学习了CAP 的定理我们知道在分布式系统下因为分区不可避免所以你不得不在一致性和可用性之间做出一个选择但是这两个特性啊其实都非常的重要我一个都不想放弃那我该怎么办呢
好那么 BASE 理论正好可以解决这个问题.
BASE 理论它是对CAP 的一种解决的思路。其实呢主要包含了三个思想:
Basically Available 基本可用分布式系统在出现故障时允许损失部分可用性即保证核心可用。**Soft State软状态**在一定时间内允许出现中间状态比如临时的不一致状态。Eventually Consistent最终一致性虽然无法保证强一致性但是在软状态结束后最终达到数据一致。
其实BASE理论正是对CAP里边这种Consistency一致性和 Availability可用性的矛盾去做一种调和和选择。
那在CAP里边你要达到了一致性你就要牺牲可用性但是在BASE 里我们如果达到了强的一致性你是要牺牲可用性但不是不可用而是部分可用性的一个牺牲或者临时的不可用。
2.3.解决分布式事务的思路
说了这么多的思想它能不能去解决我们分布式事务的问题呢
其实是可以的。那我们分布式事务里边出现了什么问题呢 分布式事务当中往往包含n个子事务每个事务各自执行和提交。结果呢有些成功有些失败了这个时候大家的状态不一致。 而我们希望的就是这个分布式事务里边的每个子事务大家最终状态一定要一致要么都成功要么都失败。
那我们基于base理论怎么样去解决这分布式事务呢
第一种解决方案其实就是基于AP的模式。 AP模式各子事务分别执行和提交允许出现结果不一致然后采用弥补措施恢复数据即可实现最终一致。 也就是满足可用性牺牲一定的一致性。比如说我们各个子事务将来我们执行的时候分别去执行和提交那有些成功有些失败了那这叫什么
这叫状态不一致。
也就是说你处于一个什么
软状态了。
临时的不一致状态没关系为什么呢执行完了以后我们各个子事务可以通个气。
互相看一看哎你成功了吗哦我成功了呃你成功了吗哎这么一对比发现有人失败了怎么办
这个时候别着急啊我们采取一个弥补的措施去恢复数据啊那有的说已经提交了没法恢复了呀那我们可以做反向的操作呀比如说你之前新增了一个对不对
那我接下来我把它删了不就完了吗
这样不就把数据又恢复到原来的状态了那这样不就实现了最终一致了吗
所以这种模式啊其实就是一种AP的一种思想了
那反过来呢我可不可以达成强一致呢哎也是可以的。 CP模式各个子事务执行后互相等待同时提交同时回滚达成强一致。但事务等待过程中处于弱可用状态。 之前是各个子事务啊是分别执行和提交你一上来全部执行完了那么没法回滚对不对
但现在呢我各个子事务执行完别提交互相等待大家彼此看一看啊诶我这执行完了你执行完了没有这样直到什么我们全部都执行完都没问题。
那我们同时提交或者中间有人失败了那我们同时回滚那么这样是不是就能达成强一致了没有中间状态对不对
只不过在这个过程中啊你的各个子事务是不是要互相等待啊等待彼此的执行嘛所以在这个过程当中你的服务其实是处于一个弱可用状态。
因为你会锁定资源啊导致无法访问嘛。
你看我们是不是就基于base的这种理论来实现了分布式事务的一种解决的一个思想了
后面我们解决分布式事务都会基于这样一个思想去做但是无论你是CP还是AP这里边有一个共同点那就是各个子事务将来要做一个互相的通信去辨别对方的执行状态。
那么各个子事务之间怎么去通信呢
所以呢它就需要有一个协调者来帮助分布式事务中的各个子事务进行一个通信啊感知。对方的或者彼此的状态那我们就举个例子啊就以我们之前的那个下单为例。 用户下单调用订单服务然后去调用账务服务和库存服务。那这个地方呢我们就需要有一个事务的协调者了然后每一个微服务都跟事务的协调者啊保持一个联系。 业务来了以后啊大家各自执行。如果你现在要做强一致那好第三服务执行的时候不要提交啊。执行下单扣款服务执行扣款库存服务执行库存。
但是执行完了以后结果发现库存失败了。 怎么知道的他们要把自己的执行结果是不是告知这个协调者然后这协调者一看有人失败了再通知他们将来去做这个回滚。
那这样大家是不是就能保持一致了所以呢这个事务的协调者啊就起到了一个非常关键的作用了那么在整个过程当中啊我们参与分布式事务当中的每一个子系统的事务我们称之为叫分支事务。
而整个分支事务称之为叫全局事务所以事务协调者其实就是来去协调各个分支事务的状态的让他们达成一致。