一 与本地事务的区别
描述场景:支付订单的时候需要完成两步操作
-
修改订单表订单状态为已支付
-
修改库存表减去订单对应库存数量
本地事务:
只有唯一的数据库,订单表和库存表都位于同一个数据库,直接使用spring进行事务管理
分布式事务:跨库事务
随着系统用户量增长,业务量庞大,一个数据库无法支撑我们业务的访问压力,以及数据库表的容量无法满足我们的需求的时候。我们考虑将数据库按照业务进行拆分,将订单表单独放到订单库,将库存表单独放到库存库…
这样在一个支付方法中我们会操作两个数据库,这时候使用spring进行事务管理已经不会起作用了
跨库事务如果出现问题一般都是第一步成功了,第二步失败了(第一步如果就失败了,直接退出了):
即订单修改成功,库存数量没变(超卖),可能原因:库存不够减,库存库挂了等情况
二分布式事务基础理论
2.1 CAP理论
2.1.1 CAP
对照如下的商品服务调用主库写入数据,调用存库读取数据,主库需要向从库同步数据的场景解释下CAP
image
C:Consistency 一致性
一致性指的是写操作后的读操作可以读取到最新的数据状态,上图中,商品信息的写入和读取要满足一致性就是要实现:商品服务写入主库成功,在从库中也能查询到这条最新写入的数据
如何实现一致性:
-
写入主库后需要将写入的数据同步到从库
-
写入主库后,在向从库同步期间要将从库锁定,等到同步完成后再释放锁,防止数据写入后,没同步完成从而在从库查询到旧数据
分布式系统一致性的特点:
-
由于存在数据同步的延迟,因此写操作的响应会有一定的延迟,因为是同步的!!你写不只是写到主库成功还要加上从主库同步到从库的时间
2 . 为了保证数据一致性会对资源暂时锁定,等待数据同步完成释放锁定资源,因此允许出现返回错误或者响应超时
A:aVailability 可用性
可用性指的是任何事务操作都可以得到响应结果,且不会出现响应超时或者响应错误,上图中,商品信息读取满足可用性即需要实现:从库接收到数据查询的请求能够立即响应数据查询结果,且不会出现响应超时或者响应错误
如何实现可用性:
-
写入数据哭后要将写入的数据同步到从库
-
由于要保证从库的可用性,因此不可将从库的资源锁定
-
即使数据还没有同步过来,从库也要返回查询到的数据,哪怕是旧数据,但不能返回错误或响应超时
分布式系统可用性特点:
所有请求都有响应,不会出现响应超时或响应错误
P:partition tolerance 分区容错性
分区容错性是指分布式系统的各个节点可能部署在不同的子网(不同机房等),这就是网络分区,相互之前需要进行利用网络进行通信,不可避免的会出现网络问题导致的通信失败,这时候仍然可以对外提供服务,这就是分区容忍性
上图中,商品信息写入和读取满足分区容忍性就是要实现:
-
主库向从库同步数据失败不影响对从库的读和主库的写操作
-
其中一个节点挂了不影响另外一个节点对外提供服务
如何实现分区容忍性:
-
尽量使用异步而非同步操作,例如使用异步方式将数据从主库同步到从库
-
添加从库节点,防止一个从节点挂了其他从节点还可以提供服务
分布式系统分区容忍性特点:
分布式系统具备的基本能力
2.1.2 CAP组合方式
在所有分布式事务场景中不会同时具备CAP三个特性,因为在具备了P的前提下C和A是不能共存的
对于大多数互联网应用场景,节点众多,部署分散,集群规模庞大,因此节点故障,网络故障都是常态,而且要保证服务可用性达到N个9(99.999999%),并能达到良好的响应性能来提高用户体验,因此一般会做出如下选择:保证P和A,舍弃C强一致性,保证最终一致性
-
AP:
放弃一致性,追求分区容忍性和可用性,这是很多分布式系统设计时的选择。通常AP都会保证最终一致性,BASE理论基于AP,一些业务场景比如订单退款,今日显示退款成功,明日账户才能到账,只要用户可以接受在一段时间内到账即可
如上面的商品写入,查询,完全可以实现AP,只要用户能接受所查询到的数据在一定时间内不是最新数据即可 -
CP
放弃可用性,追求分区容错性和一致性,zookeeper即是CP,但是只是理想达到,但是zk实际上实现的还是最终一致性。CP要求一次转账请求必须要等待双方银行系统都完成整个事务才算完成 -
CA
放弃分区容忍性,mysql主从变成只有一个主mysql,不考虑由于网络不通或者节点挂掉的问题,则可以实现CA,同时这样的系统不再是一个标准的分布式系统,我们最常用的关系型数据库就满足了CA