关于本片随笔
笔者在阅读知乎老刘的文章后有感而写,本文按照自己的观点论述了分布式事务
侵删
-------------------------------------------------------------------
本地事务
ACID特性
A |
Atomicity |
原子性 |
C |
Consistency |
一致性 |
I |
Isolation |
隔离性 |
D |
Durability |
持久性 |
一致性是最基本的特性,其他三个特性都是为了保持一致性存在的。
分布式事务
集群
核心:分担请求的压力
多台计算机进行相同的工作
在多个服务器上部署相同的应用,处理同一个问题
分布式
核心:去中心化
多台计算机进行不同的工作
把问题拆分,主要工作是分解任务,职能拆解
【将一套系统拆分成不同的子系统部署在不同服务器上,这叫分布式】
【然后部署多个相同的子系统在同一个服务器上,这叫集群】
【部署在不同服务器上的同一个子系统应进行负载均衡】
CAP理论
一个分布式系统不可能同时满足一致性、可用性和分区容错性。最多只能满足其中的两项。
而分区容错性是必须要保证的特性,所以就要在一致性和可用性之间进行取舍。
C |
Consistency |
一致性 |
A |
Availability |
可用性 |
P |
Partition tolerance |
分区容错性 |
分布式事务实战
银行转账案例
-----------------------------------------------------------------------------
最初的流程:
1、A银行对转出账户进行检查,扣除金额
2、A银行同步调用B银行的转账接口
3、B银行对转入账户进行检查,增加金额
4、B银行返回处理结果给A银行
处理流程图如下:
但是,这个流程并不能满足银行需求。
可能出现的问题:
1、同步调用远程接口,导致接口耗时太久,主线程阻塞时间长
2、难以控制流量,A银行流量高峰导致B银行系统崩溃
3、扣除金额后A银行宕机,A进行了扣款但B没增加,AB数据不一致。
4、B系统金额增加后宕机,A系统收不到响应后回滚,AB数据不一致。
问题1、2的解决方式:
引入中间件和消息队列
-----------------------------------------------------------------------------
一次修改后的流程:
1、A银行对转出账户进行检查,扣除金额
2、将对B银行的请求写入异步消息队列,主线程返回
3、启动后台程序从队列中获取待处理数据
4、后台程序对B进行远程调用
5、B银行对转入账户进行检查,增加金额
6、B银行返回处理结果给A银行
处理流程图如下:
通过增加消息队列的方式,解决了1、2问题,但是系统的复杂性提升,引入了新问题并且未解决一致性问题。
可能出现的问题:
1、扣款后A系统宕机,写入消息队列失败,AB数据不一致
2、增加余额时失败,向A反馈失败消息时宕机,A不回滚,AB数据不一致。
问题1、2的解决方式:
借助转账日志表
-----------------------------------------------------------------------------
二次修改后的部分流程:
1、A银行对转出账户进行检查,扣除金额。同时向日志表写入操作,状态为“待处理”(通过本地事务保证两个操作原子性)
2、将对B银行的请求写入异步消息队列,主线程返回
3、启动后台程序从队列中获取待处理数据
4、后台程序对B进行远程调用
……
出现问题后的处理:
第一步写入日志表后,操作已经持久化。若写入消息队列失败,只需加入后台线程补偿(周期性读取日志表,时间大于某个阈值且状态仍未“待处理”时, 重写消息队列)
处理流程图如下:
同样,对B银行也需要增加一个转账日志表,就可以保证分布式事务的一致性。
最终处理流程图如下:
解决分布式事务一致性的核心:
A银行通过本地事务保证日志记录 + 后台线程轮询保证消息不丢失
B银行通过本地事务保证日志记录,进而保证消息不重复
B银行回调A接口时,返回处理结果,若转账失败则回滚。
原文地址:https://www.cnblogs.com/cyx-qk/p/11082726.html