1、分布式事务
分布式系统经常出现的异常,如机器宕机、网络异常、消息丢失、数据错误、不可靠的TCP、存储数据丢失等等。分布式事务是指事务的参与者,支持事务的服务器,资源服务器分别位于分布式系统的不同节点之上,通常一个分布式事物中会涉及到对多个数据源或业务系统的操作。
典型的分布式事务场景:跨银行转操作就涉及调用两个异地银行服务
1.1、CAP定理
CAP理论:一个分布式系统不可能同时满足一致性,可用性和分区容错性这个三个基本需求,最多只能同时满足其中两项
- 一致性(Consistency):数据在多个副本之间是否能够保持一致的特性。
- 可用性(Avaliability):是指系统提供的服务必须一致处于可用状态,对于每一个用户的请求总是在有限的时间内返回结果,超过时间就认为系统是不可用的
- 分区容错性(Partition tolerance):分布式系统在遇到任何网络分区故障的时候,仍然需要能够保证对外提供满足一致性和可用性的服务,除非整个网络环境都发生故障。
一致性算法raft:通过选举和心跳日志复制来解决一致性问题
对于多数大型互联网应用的场景,主机众多,部署分散,而且现在集群的规模越来越大,所以,节点故障、网络故障是常态,而且要保证服务可用性达到 99.999999%(N个9),即保证P和A,舍弃C。一般都是AP
1.2、BASE理论
BASE是基本可用,软状态,最终一致性。是对CAP中一致性和可用性权限的结果,是基于CAP定理演化而来的,核心思想是即使无法做到强一致性,但每个应用都可以根据自身的业务特定,采用适当的方式来使系统达到最终一致性
强一致性、弱一致性、最终一致性:
- 对于关系型数据库,要求更新过的数据能被后续的访问都能看到,这就是强一致性。
- 如果能容忍后续的部分或者全部访问不到,则是弱一致性,
- 如果经过一段时间能访问到更新后的数据,则是最终一致性。
1.3、分布式事务的几种解决方案
刚性事务:遵循 ACID 原则,强一致性。
柔性事务:遵循 BASE 理论,最终一致性。1.3.1、刚性事务——2PC模式
1.3.2、刚性事务-3PC模式
- 三阶段提,也叫三阶段提交协议,是二阶段提交(2PC)的改进版本。
- 与两阶段提交不同的是,三阶段提交有两个改动点。引入超时机制。同时在协调者和参与者中都引入超时机制。在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。
三阶段提交就有CanCommit、PreCommit、DoCommit三个阶段。
1.3.3、柔性事务-TCC事务补偿型方案
Try操作是先把多个应用中的业务资源预留和锁定住,为后续的确认打下基础,类似的,DML操作要锁定数据库记录行,持有数据库资源。
- Confirm操作是在Try操作中涉及的所有应用均成功之后进行确认,使用预留的业务资源,和Commit类似。
- Cancel则是当Try操作中涉及的所有应用没有全部成功,需要将已成功的应用进行取消(即Rollback回滚)。其中Confirm和Cancel操作是一对反向业务操作。
1.3.4、柔性事务-最大努力通知型方案
高并发下使用较多1.3.5、柔性事务-可靠消息+最终一致性方案(异步确保型)高并发最多用
高并发下使用最多2、分布式下session共享问题
session机制在分布式和集群情况下带来的问题:
- 不同服务(不同域名)下,session不能共享
- 即使同一个服务,复制多份,session不同步问题
用的多
用的多
以上解决了分布式下的session的共享问题,但是没有解决子域session问题
最终解决办法:通过Spring Sessiona整合Redis进行统一存储session并解决子域session共享问题。具体见Spring Cloud篇Spring Session。
3、单点登录
单点登录全称Single Sign On(以下简称SSO),是指在多系统应用群中登录一个系统,便可在其他所有系统中得到授权而无需再次登录,包括单点登录与单点注销两部分
https://blog.csdn.net/a2522827931/article/details/107100760
https://www.cnblogs.com/ywlaker/p/6113927.html
4、分布式锁
单机情况下,直接在单服务中使用synchronize和lock加锁效果是可行的,但是在分布式情况下。单机锁只能锁住当前服务的代码,并不能锁住其他服务的代码。所以分布式锁就应运而生了。
分布式锁的解决方案就是在一个中间的地方加上一个数据或者一个记录。请求每次过来之后,先去中间商看看有没有这个数据或者说是记录,如果没有就给它加上这个数据。如果有,那就自旋等待锁释放,也就是数据删除。
一般的解决办法是Redis分布式锁,有一下几点需要特别注意一下。
- 加锁、必须设置过期时间防止死锁原子性,setnx
- 解锁必须原子性,lua脚本
- 过期时间的自动续期
- 解不是自己的锁
但是这样太麻烦了,最终我们采用Redisson来实现Redis版的分布式锁