分布式事务的问题:
电商系统,下单扣减商品库存测试的时候,出现过一个问题,就是:商品服务没有正确的连接到Redis,从而导致商品服务出现异常,虽然商品服务出现了异常,库存没有扣减成功。但是订单已经添加到了数据库中。这个不是我们期望的效果,因为下单扣减商品库存的功能,虽然操作的是不同的服务,但是他是一个整体功能,要么都成功,要么都失败,当商品库存扣减失败的时候,订单不应该添加到数据库中。这个效果的出现是因为我们需要使用分布式事务来进行功能控制。
刚才我们讲的扣减库存与保存订单是在两个服务中存在的,如果扣减库存后订单保存失败了是不会回滚的,这样就会造成数据不一致的情况,这其实就是我们所说的分布式事务的问题,接下来我们来学习分布式事务的解决方案。
讲解分布式事务之前我们要回顾下事务的相关知识
一、 本地事务与分布式事务
1.1 事务
数据库事务(简称:事务,Transaction)是指数据库执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
1 、事务拥有以下四个特性
事务拥有以下四个特性,习惯上被称为ACID特性:
原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
事务是不可分割的单位,要么都成功,要么都失败,这是事务的原子性。
一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态是指数据库中的数据应满足完整性约束。除此之外,一致性还有另外一层语义,就是事务的中间状态不能被观察到(这层语义也有说应该属于原子性)。
就是事务在执行前与执行后,他需要保证数据库中的数据,能够从一个一致性状态转换到另外一个一致性状态上。这就是事务的一致性。
隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行,如同只有这一个操作在被数据库所执行一样。
隔离性就是当有多个事务在并发执行的时候,他们相互之间是不会产生影响的,互相都是被隔离开的。这就是事务的隔离性。
持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中。在事务结束时,此操作将不可逆转。
持久性就是一个事务他对数据库的修改,会永久保存到数据库中,不会因为系统的瘫痪,而导致数据的丢失。这就是事务的持久性。
2、 本地事务
起初,事务仅限于对单一数据库资源的访问控制,架构服务化以后,事务的概念延伸到了服务中。倘若将一个单一的服务操作作为一个事务,那么整个服务操作只能涉及一个单一的数据库资源,这类基于单个服务单一数据库资源访问的事务,被称为本地事务(Local Transaction)。
添加事务操作,找到业务层实现类OrderServiceImpl, 添@Transactional注解进行事务控制。只会对本系统生效,只会在订单服务中生效。
3 、分布式事务
分布式事务指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上,且属于不同的应用,分布式事务需要保证这些操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。
最早的分布式事务应用架构很简单,不涉及服务间的访问调用,仅仅是服务内操作涉及到对多个数据库资源的访问。
当一个服务操作访问不同的数据库资源,又希望对它们的访问具有事务特性时,就需要采用分布式事务来协调所有的事务参与者。
服务内操作多个数据库资源图:
对于上面介绍的分布式事务应用架构,尽管一个服务操作会访问多个数据库资源,但是毕竟整个事务还是控制在单一服务的内部。如果一个服务操作需要调用另外一个服务,这时的事务就需要跨越多个服务了。在这种情况下,起始于某个服务的事务在调用另外一个服务的时候,需要以某种机制流转到另外一个服务,从而使被调用的服务访问的资源也自动加入到该事务当中来。下图反映了这样一个跨越多个服务的分布式事务:
包含多个服务的分布式事务图:
如果将上面这两种场景(一个服务可以调用多个数据库资源,也可以调用其他服务)结合在一起,对此进行延伸,整个分布式事务的参与者将会组成如下图所示的树形拓扑结构。在一个跨服务的分布式事务中,事务的发起者和提交均系同一个,它可以是整个调用的客户端,也可以是客户端最先调用的那个服务。
分布式事务的参与者将会组成如下的树形拓扑结构图:
较之基于单一数据库资源访问的本地事务,分布式事务的应用架构更为复杂。在不同的分布式应用架构下,实现一个分布式事务要考虑的问题并不完全一样,比如对多资源的协调、事务的跨服务传播等,实现机制也是复杂多变。
二、 分布式事务相关理论
1 CAP定理
CAP定理是在 1998年加州大学的计算机科学家 Eric Brewer (埃里克.布鲁尔)提出,分布式系统有三个指标
-Consistency 一致性
-Availability 可用性
-Partition tolerance 分区容错性
它们的第一个字母分别是 C、A、P。Eric Brewer 说,这三个指标不可能同时做到。这个结论就叫做 CAP 定理。
分区容错 Partition tolerance
对于分布式系统来说,内部一定会存在若干个子服务,会将每一个子服务进行单独部署,从而构成若干个子网络,每个子网络叫做一个区(partition)。分区容错的意思是,区间通信可能失败。比如,一台服务器放在中国,另一台服务器放在美国,这就是两个区,它们之间可能无法通信。
服务与服务之间都会涉及到相互调用,如下图有1号(G1)和2号(G2)两个服务,假设1号(G1)服务部署在中国,2号(G2)服务部署在美国。当他们之间产生通信调用的时候。就很有可能因为一些意外情况,如天气,导致他们无法通信。因此对于分布式系统设计的时候,我们会认为分区容错这个问题是一定会出现的。因此对于分区容错性(Partition tolerance)在CAP定理中,它是一只成立的,这就是分区容错性。
CAP三个指标中最多只能保证其中两点,P是一直成立的,因此在分布式系统的设计下,C(一致性 Consistency)和A(可用性 Availability),它们两者无法同时成立。
图中,G1 和 G2 是两台跨区的服务器。G1 向 G2 发送一条消息,G2 可能无法收到。系统设计的时候,必须考虑到这种情况。
一般来说,分区容错无法避免,因此可以认为 CAP 的 P 总是成立。CAP 定理告诉我们,剩下的 C 和 A 无法同时做到。
Group(服务器/服务),client(用户),Version(信息记录0-1)
可用性 Availability
Availability 中文叫做"可用性",意思是只要收到用户的请求,服务器就必须给出回应。在分布式系统下,保证服务的高可用。如何保证高可用,可以搭建主备服务器来保证服务的高可用。
用户可以选择向 G1 或 G2 发起读操作。不管是哪台服务器,只要收到请求,就必须告诉用户,到底是 v0 还是 v1,否则就不满足可用性。
一致性 Consistency
Consistency 中文叫做"一致性"。意思是,写操作之后的读操作,必须返回该值。
在分布式系统下,要保证服务内部中相关服务器,数据读写的一致性。
举例来说,订单服务有一主(G1)一备(G2)两台服务器,如果要进行数据传递的时候,某条记录是 v0,用户向 G1 发起一个写操作,将其改为 v1。
问题是,用户有可能向 G2 发起读操作,由于 G2 的值没有发生变化,因此返回的是 v0。G1 和 G2 读操作的结果不一致,这就不满足一致性了。
为了让 G2 也能变为 v1,就要在 G1 写操作的时候,让 G1 向 G2 发送一条消息,要求 G2 也改成 v1。
一致性和可用性的矛盾
一致性和可用性,为什么不可能同时成立?答案很简单,因为可能通信失败(即出现分区容错)。
如果保证 G2(服务器) 的一致性,那么 G1(服务器) 必须在写操作时,锁定 G2 的读操作和写操作。只有数据同步后,才能重新开放读写。锁定期间,G2 不能读写,没有可用性。
如果保证 G2 的可用性,那么势必不能锁定 G2,所以一致性不成立。
综上所述,G2 (服务器)无法同时做到一致性和可用性。系统设计时只能选择一个目标。如果追求一致性,那么无法保证所有节点的可用性;如果追求所有节点的可用性,那就没法做到一致性。
对于分布式系统设计来说,会考虑CP(一致性 Consistency)的组合或者AP(可用性 Availability和)的组合,在大多数情况下都考虑AP组合,更重视可用性,但是在一些特殊场景,比方说:进行银行转账,需要保证转账数据的强一致同步,转账发起方和转账收到方要保证实时同步,此时需要考虑CP的组合,更注重一致性。
在分布式系统设计中,这对于CAP定理,只能保证2点,即保证可用性或者一致性。大多数情况下优先考虑可用性。
2 BASE理论
BASE理论: 由ebay 的架构师提出。全称:Basically Available(基本可用),Soft state(软状态),和 Eventually consistent(最终一致性)三个短语的缩写。BASE 理论是对 CAP 中一致性和可用性权衡的结果,其来源于对大型互联网分布式实践的总结,是基于 CAP 定理逐步演化而来的。其核心思想是:
在大多数分布式架构系统中,更倾向于使用AP,保证可用性,无法保证数据实时同步,也就是强一致性的话,我们就退而求其次,要去保证当前数据的最终一致性。
既是无法做到强一致性(Strong consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。
Basically Available(基本可用)
什么是基本可用呢?假设系统,出现了不可预知的异常,但还要保证他还是可以进行使用的,相比较正常的系统而言,一般会在响应时间和功能上做一定的降级处理:
1.响应时间上的损失:正常情况下的搜索引擎 0.5 秒即返回给用户结果,出现异常后,不能说用户得不到结果,可以做一些降级处理,最终结果需要响应给用户。而基本可用的搜索引擎可以在 1 秒作用返回结果。
2.功能上的损失:在一个电商网站上,正常情况下,用户可以顺利完成每一笔订单,但是到了大促期间,为了保护购物系统的稳定性,部分消费者可能会被引导到一个降级页面。
Basically Available(基本可用)的解释:就算当前系统出现了不可预知的异常,当前系统还是可以正常的使用的这就是Basically Available(基本可用)。
Soft state(软状态)
什么是软状态呢?相对于原子性而言,要求多个节点的数据副本都是一致的,这是一种 “硬状态”,强一致性。
软状态指的是:允许系统中多个服务节点的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个不同服务节点的数据副本存在数据延时。
Eventually consistent(最终一致性)
系统能够保证在没有其他新的更新操作的情况下,数据最终一定能够达到一致的状态,因此所有客户端对系统的数据访问最终都能够获取到最新的值。
最终结果一定是正确的,一定是符合我们期望的。功能执行完成后,最终的结果一定是正确的结果,一定是符合我们期望的结果。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库