刚才我们编写的扣减库存与保存订单是在两个服务中存在的,如果扣减库存后订单保存失败了是不会回滚的,这样就会造成数据不一致的情况,这其实就是我们所说的分布式事务的问题,接下来我们来学习分布式事务的解决方案。:
就是上一篇博客的保存订单代码中调了另一个服务的,容易造成分布式事务问题
一、本地事务与分布式事务
1.1 事务
狂神的:
1.2本地事务
起初,事务仅限于对单一数据库资源的访问控制,架构服务化以后,事务的概念延伸到了 服务中。倘若将一个单一的服务操作作为一个事务,那么整个服务操作只能涉及一个单 一的数据库资源,这类基于单个服务单一数据库资源访问的事务,被称为本地事务(Local Transaction)。
1.3 分布式事务
较之基于单一数据库资源访问的本地事务,分布式事务的应用架构更为复杂。在不 同的分布式应用架构下,实现一个分布式事务要考虑的问题并不完全一样,比如对多资 源的协调、事务的跨服务传播等,实现机制也是复杂多变。
二、分布式事务相关理论
2.1 CAP定理
CAP定理是在 1998年加州大学的计算机科学家 Eric Brewer (埃里克.布鲁尔)提出,分 布式系统有三个指标:
- Consistency 一致性
- Availability 可用性
- Partition tolerance 分区容错
它们的第一个字母分别是 C、A、P。Eric Brewer 说,这三个指标不可能同时做到。这个 结论就叫做 CAP 定理。
(2.1.1)分区容错 Partition tolerance(一定得满足,因为都会出错)
大多数分布式系统都分布在多个子网络。每个子网络就叫做一个区(partition)。分区 容错的意思是,区间通信可能失败。比如,一台服务器放在中国,另一台服务器放在美 国,这就是两个区,它们之间可能无法通信:
上图中,G1 和 G2 是两台跨区的服务器。G1 向 G2 发送一条消息,G2 可能无法收到。 系统设计的时候,必须考虑到这种情况。
一般来说,分区容错无法避免,因此可以认为 CAP 的 P 总是成立。CAP 定理告诉我们, 剩下的 C 和 A 无法同时做到。
(2.1.2)可用性 Availability
Availability 中文叫做"可用性",意思是只要收到用户的请求,服务器就必须给出回应。
用户可以选择向 G1 或 G2 发起读操作。不管是哪台服务器,只要收到请求,就必须告诉 用户,到底是 v0 还是 v1,否则就不满足可用性。:
(2.1.3)一致性 Consistency
Consistency 中文叫做"一致性"。意思是,写操作之后的读操作,必须返回该值。 举例来说,某条记录是 v0,用户向 G1 发起一个写操作,将其改为 v1:
问题是,用户有可能向 G2 发起读操作(在G1还没改完的情况下),由于 G2 的值没有发生变化,因此返回的是 v0。G1 和 G2 读操作的结果不一致,这就不满足一致性了:
为了让 G2 也能变为 v1,就要在 G1 写操作的时候,让 G1 向 G2 发送一条消息,要求 G2 也改成 v1,这才能满足一致性。
(2.1.4) 一致性和可用性的矛盾
一致性和可用性,为什么不可能同时成立?答案很简单,因为可能通信失败(即出现分 区容错)(因为P一定要的)。
如果保证 G2 的一致性,那么 G1 必须在写操作时,锁定 G2 的读操作和写操作。只有数 据同步后,才能重新开放读写。锁定期间,G2 不能读写,没有可用性。
如果保证 G2 的可用性,那么势必不能锁定 G2,所以一致性不成立。
综上所述,G2 无法同时做到一致性和可用性。系统设计时只能选择一个目标。如果追求 一致性,那么无法保证所有节点的可用性;如果追求所有节点的可用性,那就没法做到 一致性。
2.2 BASE理论
(2.2.1) Basically Available(基本可用)
(2.2.2) Soft state(软状态)
(2.2.3)Eventually consistent(最终一致性)
三、 分布式事务解决方案
3.1 基于XA协议的两阶段提交
首先我们来简要看下分布式事务处理的XA规范 :
3.2 TCC补偿机制(3个阶段的)
3.3 消息最终一致性(推荐)
四、库存扣减分布式事务的实现
基于上述消息最终一致性
如果订单在创建时发生了异常,此时库存已经扣减了,这样库存就比实际中的数量要 少,造成数据不一致,为了避免这种情况,我们需要采用消息最终一致性的分布式事务 解决方案。(就是本文开头的情况,就是上一篇博客保存订单出现错误,解决另一个工程的服务回滚不了的问题)
(7)qingcheng_service_goods添加配置文件applicationContext-rabbitmq- consumer.xml
在保存订单try最后价格 int i/0就可以看到回滚了。
完成我们分布式事务的问题