目录:
1、什么是分布式事务
2、分布式事务解决方案
3、集成seata
4、seata原理
什么是分布式事务
在服务拆分之后,完成某一个功能可能需要横跨多个服务,操作多个数据库。
之前操作单一的数据库,只需要保证在这个数据库中执行的操作要么一起成功,要么一起失败。这种事务叫做本地事务。
而操作多个数据库,要保证多个数据库里的操作一起成功或失败的事务就是分布式事务。
上图中有库存服务和订单服务,库存服务和订单服务都有自己单独的数据库。
在一个下单操作中,需要先调用库存服务减去相应的库存,然后再调用订单服务添加一笔订单。
在正常情况下库存正常扣减了,订单也正常插入了,这时两个库的数据是一致的。
但是在非正常情况下,有可能库存扣减了,但在订单服务进行订单插入的时候,因为数据库宕机或者订单服务宕机等其它因素,导致订单插入失败了。这个时候两个库的数据就 不一致了。明明库存减少了,但是却没有对应的订单信息。
分布式事务就是用来保证多个数据源直接数据的一致性。
分布式事务解决方案
1 两阶段提交(2PC)
在两阶段提交中,存在两个角色,事务协调者和事务参与者。
第一阶段:
在这一阶段中,事务协调者先发送Prepare消息给各个事务参与者,事务参与者先在自己本地执行相关的数据库操作,但是不进行提交。
执行成功了就给事务协调者返回yes,执行失败者返回no。
第二阶段:
第二阶段事务协调者会根据第一个阶段,各个事务参与者返回的信息来决定发送commit还是abort。
要是第一个阶段所有的事务参与者都是返回的yes,那么这时事务协调者就会发送commit的消息给事务参与者,告诉他们可以进行提交操作了。
事务参与者提交完成后就返回ack,告诉事务协调者已经提交完成。整个分布式事务玩成。
要是第一阶段有任何一个事务参与者返回的是no,那么这时事务协调者就会发送abort的消息给所有事务参与者,告诉他们本次执行不成功,需要进行回滚。
各个事务参与者就对第一阶段执行的操作进行回滚,然后返回ack消息。
存在的问题
1、性能问题:在事务协调者发送Prepare消息后,事务参与者会执行相关的数据库操作,但是不提交。这个时候对应的数据就被锁定了,其它的请求是无法操作这个数据,只有等事务协调者发送commit或者abort消息后,事务参与者提交或者回滚事务才能释放这个锁。
2、单点问题:要是在事务协调者发送Prepare后,事务协调者就宕机了。参与者一直无法接收到commit或者abort消息,事务就一直无法提交,导致资源一直被锁定。
3、数据不一致问题:事务协调者发送的commit消息,由于网络等一些原因,导致部分参与者收到了commit消息提交了事务,而另一部分没有收到没有进行事务提交,导致数据不一致。
2 补偿事务(TCC)
TCC事务是Try、Commit、Cancel三种指令的缩写,其逻辑模式类似于2PC两阶段提交,但是实现方式是在代码层面人为实现的。
第一阶段
在try这个阶段中,主要用于系统做检测和锁定资源。主业务逻辑会先去调用库存服务和订单服务的try接口,这个接口需要库存服务和订单服务提供。
比如说正常的逻辑是库存服务商品数量减1,订单服务插入一条订单。
而现在try接口里面的逻辑不是直接把商品数量减1,而是添加一个字段叫做锁定商品数量。把需要减去的商品数量存储在这个字段。
订单服务也不是直接插入一条订单数据,而是插入一条状态为未支付的数据。
第二阶段
在commit这个阶段,就是真正执行业务操作。commit接口的逻辑就是把之前库存服务锁定数量字段修改为原来的0,订单服务将订单状态修改为已支付状态。这样就完成了一个下单的操作。
第三阶段
在cancel阶段中主要是对之前的操作进行还原,比如说在commit这个阶段中,订单服务commit失败了。那么这个时候数据就 不一致了。这时就需要对数据进行还原。需要对库存服务的锁定数量字段的数据还原回商