分布式事务
背景
在微服务环境下,因为会根据不同的业务会拆分成不同的服务,比如会员服务、订单服务、商品服务等,让专业的人做专业的事情,每个服务都有自己独立的数据库,并且是独立运行,互不影响。但是每个服务中都有自己独立的数据源,即自己独立的本地事务。两个服务相互通讯的时候,两个本地事务互不影响,从而出现分布式事务产生的原因。
案例说明: 下单和扣库存如何保持一致问题
描述: 数据库都是独立的,每个独立的数据源中都有自己独立的事务,该事务成为本地事务。本地事务有效范围在同一个jdbc里面(同一个事务管理器 )
代码展示:
问题: 下单失败了,但是库存成功了,如何去回滚? 注意: 下单成功,库存失败,不属于分布式事务问题。
总结: 本地数据源有效范围是 同一个jdbc连接或者同一个事务管理器。
分布式事务解决方案
刚性事务 -- 关系型数据库的ACID
关系型数据库天生就是解决具有复杂事务场景的问题,关系型数据库完全满足ACID的特性。满足ACID特性
ACID对应的含义:事务管理(ACID)
谈到事务一般都是以下四点:
原子性(Atomicity):原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
一致性(Consistency):事务前后数据的完整性必须保持一致。
隔离性(Isolation):事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
持久性(Durability):持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响
柔性事务 -- 遵循Base和CPA理论
CPA理论
-
C:Consistency, 一致性。在分布式系统中的所有数据 备份,在同一时刻具有同样的值,所有节点在同一时刻读取的数据都是最新的数据副本。双方进行通讯的时候,或者服务器集群的时候,一定要保证数据一致性问题,不能发生脏读等问题。其实一般情况下可以做个取舍,可以暂时不遵循一致性,但是达到最终一致性,只要核心遵循下面的可用性和分区容忍性就可以。
-
A:Availability,可用性,好的响应性能。完全的可用性指的是在任何故障模型下,服务都会在有限的时间内处理完成并进行响应。比如服务器宕机情况下 还有备机
-
P: Partition tolerance,分区容错性。尽管网络上有部分消息丢失,但系统仍然可继续工作。
总结:
- CAP原理指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。
- 对于分布式数据系统,分区容忍性是基本要求,容错是肯定的,否则就失去了价值,在一致性和可用性之间取一个平衡
- 对于大多数web应用,其实并不需要强一致性,因此牺牲一致性而换取高可用性,是目前多数分布式数据库产品的方向。
- 通过软状态,可以暂时不一致,但是最终实现一致。通过补偿、重试等。
- 牺牲一致性,只是不再要求关系型数据库中的强一致性,而是只要系统能达到最终一致性即可
- 由于关系型数据库是单节点无复制的,因此不具有分区容忍性,但是具有一致性和可用性,而分布式的服务化系统都需要满足分区容忍性,那么我们必须在一致性和可用性之间进行权衡
注意实际开发中只遵循了P和A
Base 理论
- BA:(Basically Available),基本可用。指分布式系统在出现故障的时候,保证核心可用。比如:网页访问过大时,部分用户提供降级服务。
- S:(Soft State),软状态,状态可以在一段时间内不同步。
- E:(Eventually Consistent),最终一致,在一定的时间内,最终数据达成一致即可。
总结: BASE 思想与 ACID 原理截然不同,它满足CAP原理,通过牺牲强一致性获得可用性, 一般应用于服务化系统的应用层或者大数据处理系统中,通过达到最终一致性来尽量满足业务的绝大多数需求。
支付案例
流程如下:
- toov5 调用支付宝时候 会传递两个参数 同步回调地址 和 异步回调地址
- 同步回调地址:支付完成后,支付宝采用浏览器方式重定向回调方
- 异步回调地址:支付完成后,采用后台也就是HttpClient进行调用toov5接口通知支付接口
- 当通知接口出现延迟或者异常情况下,支付宝会发生自动重试。短暂的不一致情况
柔性事务分为:
- 两阶段型
- 补偿型
- 异步确保型
- 最大努力通知型
关于两阶段、三阶段
1. 两阶段: 交易中间件与数据库通过 XA 接口规范,使用两阶段提交来完成一个全局事务, XA规范的基础是两阶段提交协议。
- 准备阶段:协调者向参与者发起指令,参与者评估自己的状态,如果参与者评估指令可以完成,则会写redo或者undo日志(提交日志和回滚日志),然后锁定资源,执行操作,但并不提交。
- 提交阶段:协调者会向参与者发送一个指令,如果参与者收到指令后,会把该业务逻辑是否执行成功结果返回给协调者。如果参与者都返回执行成功,协调者在第二阶段发送提交事务通知,如果有一方执行失败,就会终止提交。
缺点:
- 如果协调者发生宕机,整个就没法指挥协调了。库存服务和订单服务会一直等待。
- 两阶段提交方案锁定资源时间长,对性能影响很大,基本不适合解决微服务事务问题。
技术落地:
- Jta+Atomikos 属于两阶段提交协议。底层是基于XA协议,主流数据库MySQL等都支持XA协议。这个协议规范就是协调者把指令发送给参与者的过程。MySQL是参与者,Atomikos:Atomikos TransactionsEssentials是一个为Java平台提供增值服务的并且开源类事务管理器,底层就是遵循了XA协议的规范。
Jta+Atomikos 代码案例
1. 三阶段提交协议 --- 两阶段准备阶段再加了一个询问阶段
- 询问阶段: 协调者询问参与者是否可以完成指令,协调者只需要回答是还是不是,而不需要做真正的操作,这个阶段超时导致中止。协调者和参与者执行的任务中都增加了超时,一旦超时,协调者和参与者都继续提交事务,默认为成功,这也是根据概率统计上超时后默认成功的正确性最大。
优点: 至少不会阻塞和永远锁定资源。
结合非关系型数据库
- 但当数据库要开始满足横向扩展、高可用、模式*等需求时,需要对ACID理论进行取舍,不能严格遵循ACID。以CAP理论和BASE理论为基础的NoSQL数据库开始出现。
- 由于NoSQL的基本需求就是支持分布式存储,严格一致性与可用性需要互相取舍,由此延伸出了CAP理论来定义分布式存储遇到的问题。