分布式相关
一、什么是分布式
一个大型应用被拆分为很多小的应用分布部署在各个机器上。
二、CAP理论
任何分布式系统都无法同时满足一致性(consistency),可用性(availibity),**分区容错性(partition tolerance)**这三项,最多只可同时满足其中的两项.
①一致性: 对于客户端的每次读操作,要么读到的是最新的数据,要么读取失败。换句话说,一致性是站在分布式系统的角度,对访问本系统的客户端的一种承诺:要么我给您返回一个错误,要么我给你返回绝对一致的最新数据,不难看出,其强调的是数据正确。
②可用性: 任何客户端的请求都能得到响应数据,不会出现响应错误。换句话说,可用性是站在分布式系统的角度,对访问本系统的客户的另一种承诺:我一定会给您返回数据,不会给你返回错误,但不保证数据最新,强调的是不出错。
③分区容忍性: 由于分布式系统通过网络进行通信,网络是不可靠的。当任意数量的消息丢失或延迟到达时,系统仍会继续提供服务,不会挂掉。换句话说,分区容忍性是站在分布式系统的角度,对访问本系统的客户端的再一种承诺:我会一直运行,不管我的内部出现何种数据同步问题,强调的是不挂掉。
三、base理论
BASE理论是由eBa工程师提出,是对可用性和一致性的权衡。BASE是由 Basically Available(基本可用),Soft state(软状态),和 Eventually consistent(最终一致性) 三个短语的缩写。base理论是对cap理论的一种拓展。
1、基本可用
在互联网上,用户量等有时候难以预见,就造成了用户超出系统设计的标准,想一直保持完全可用就很难,所以折中下,我们可以通过延迟响应,流量削峰等手段来保障系统的核心功能的正常,从而实现基本可用。
保障基本可用的方法:削峰填谷、延迟响应(请求慢慢处理)、服务降级(牺牲系统非必要的功能,保证核心正常运行)、过载保护(防止服务雪崩,抛弃请求返回错误)
2、软状态
允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个不同节点的数据副本存在数据延时。软状态可以理解为可以变动的状态,强调的是数据状态处于一种临界状态。
3、最终一致性
我们不能随时都保障数据的一致,所以我们有了数据的中间状态,即软状态,经过一定时间后,数据最终回归于最终一致,这些短暂的数据不一致性,对用户的影响很小。
最终一致性的系统不承诺写入数据成功后,立刻就从系统中读出最新的数据,也不承诺具体多久之后可以读到最新的数据,而是尽可能保障特定时间级别之后的数据可用。
方式:写实修复(多副本写时如果一个失败了就缓存起来自动重试来进行修复)、读时修复(读数据时从多个节点读,根据一定的规则来返回值,并按照正确的值进行修复)、异步修复(定时不同节点比对,如果需要修复则进行同步,性能较差)
四、分布式锁
1、什么是分布式锁
随着技术快速发展,数据规模增大,分布式系统越来越普及,一个应用往往会部署在多台机器上(多节点)在多机部署环境中,不同机器不同进程,就需要在多进程下保证线程的安全性了。
2、分布式锁的特性
- 互斥:不同线程之间互斥,只有一个线程能持有锁。
- 超时机制:代码耗时过长,网络原因等,导致锁一直被占用,造成死锁,所以引入超时机制,超过指定时间自动释放锁。
- 完备的锁接口:阻塞的和非阻塞的接口都要有,lock 和 tryLock。
- 可重入性:当前请求的节点 + 线程唯一标识,可以再次获取同一把锁
- 公平性:锁唤醒时候,按照顺序唤醒,不公平的话,有可能出现饥饿现象。
3、实现方式
(1)基于数据库mysql,使用较少
创建一个名为lock的表,表中包含方法名等字段,并在方法名字段上创建唯一索引,想要执行某个方法,就使用这个方法名向表中插入数据,成功插入则获取锁,执行完成后删除对应的行数据释放锁。
存在的问题:受数据库的影响,不具备可重入性(可以修改表结构来实现),锁失效时间(也可以加一列)
(2)redis
redis性能很好,redis命令支持较好
1、setNx:当且仅当key不存在时,set一个key为val的字符串,返回1;若key存在,则什么都不做,返回0。
expire:为key设置过期时间,超过时间则自动释放
实现思路:(1)获取锁的时候,使用setnx加锁,并使用expire命令为锁添加一个超时时间,超过该时间则自动释放锁,锁的value值为一个随机生成的UUID,通过此在释放锁的时候进行判断。(2)获取锁的时候还设置一个获取的超时时间,若超过这个时间则放弃获取锁。(3)释放锁的时候,通过UUID判断是不是该锁,若是该锁,则执行delete进行锁释放。
存在问题:如果是在 Redis 集群环境下,由于 Redis 集群同步是异步的。如果在 Master 节点上设置锁,Slave 节点可能没有同步到最新的数据。此时 Master 节点崩溃了但是理论上锁不应当被释放,但由于 Master 的宕机导致了锁物理上被释放,所以其他客户端可能会加新的锁来对共享资源进行修改,这样就出现了问题。
解决问题的方法就是relock算法redission
2、redisson
RedLock 算法的主要目的是为了解决 Master 节点宕机导致锁的释放问题。RedLock 算法的基本思路是,在多个 Redis 节点上同时加锁,只要大多数 Redis 节点都加锁成功,那么加锁成功;如果加锁失败,则释放所有锁并重试。
RedLock 算法的流程如下:
- 客户端获取当前时间戳。
- 客户端在每个 Redis 节点上尝试用相同的锁名和 UUID 获取锁,并设置一个较短的过期时间。获取成功则记录加锁节点,否则记录失败节点。并记录加锁的总用时。
- 如果成功加锁的节点大于等于 N/2+1(N 为 Redis 节点数),并且获取锁的总时间小于锁的过期时间,则认为加锁成功并执行业务逻辑;否则认为获取锁失败,释放所有锁
Redisson 的看门狗机制目的是检查锁的状态,自动管理分布式锁过期时间。其实现主要通过一个后台线程(俗称看门狗),每隔锁的 1/3 时间检查锁的状态,只要持有锁的线程仍在执行且没有主动释放锁,看门狗就会持续进行续期操作。如果没有线程持有锁,看门狗就会自动释放锁。
(3)zookeeper实现
ZooKeeper是一个为分布式应用提供一致性服务的开源组件,它内部是一个分层的文件系统目录树结构,规定同一个目录下只能有一个唯一文件名。基于ZooKeeper实现分布式锁的步骤如下:
(1)创建一个目录mylock;
(2)线程A想获取锁就在mylock目录下创建临时顺序节点;
(3)获取mylock目录下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说明当前线程顺序号最小,获得锁;
(4)线程B获取所有节点,判断自己不是最小节点,设置监听比自己次小的节点;
(5)线程A处理完,删除自己的节点,线程B监听到变更事件,判断自己是不是最小的节点,如果是则获得锁。
优点:具备高可用、可重入、阻塞锁特性,可解决失效死锁问题。
缺点:因为需要频繁的创建和删除节点,性能上不如Redis方式。
五、分布式事务
1、什么是分布式事务
举一个典型的例子,阿里的淘宝网站随着访问量越来越大,只能按照商品、订单、用户、店铺等业务为单位进行数据库拆分,以及按照业务为单位提供服务接口。这个时候 为了完成一个简单的业务功能,比如:购买商品后扣款,有可能需要横跨多个服务,涉及用户订单、商品库存、支付等多个数据库,而这些操作又需要在同一个事务中完,这就涉及到到了分布式事务。
分布式事务是指会涉及到操作多个数据库的事务。目的是为了保证分布式系统中的数据一致性。
2、解决方案
(1)2pc(两阶段提交)
第一阶段
协调者向参与者发送预备信号,参与者进行事务操作,但不提交;然后,所有参与者都将本事务能否成功的信息反馈发给协调者。
第二阶段
执行阶段,协调者根据所有参与者的反馈,通知所有参与者,步调一致地在所有分支上提交或者回滚。(如果都可以则进行提交否则都回滚)
优缺点:
尽量保证了数据的强一致,实现成本较低,在各大主流数据库都有自己实现,存在单点故障问题、性能问题、跨数据库问题。(如果一个节点出现问题就会造成其他节点的浪费)
(2)3pc(三阶段提交)
在2pc的基础上加了一个询问阶段,问各个参与者是否存在。后面两步同2pc。
解决了一个节点故障问题,但还有问题一个事务执行时会进行全局阻塞。
(3)TCC(Try Confirm Cancel)
类似2pc,阻塞的粒度更小,偏向于用代码逻辑进行实现。
try:协调者向参与者问‘你先试试行,的话再说’,排除一切会造成问题的可能性 完成准备工作。
confirm:如果准备好了,直接提交数据库
cancel:如果没准备好,则取消。
(4)长事务:Saga
直接让参与者进行开启事务并提交。如果都成功ok,如果出错反向回滚。不会隔离
(5)消息最终一致性
通过消息队列
参考文章:
深入理解分布式锁的原理和使用场景_牛客网
什么是分布式锁?实现分布式锁的三种方式 - 刘清政 - 博客园
理解分布式锁的原理和使用场景_牛客网
什么是分布式锁?实现分布式锁的三种方式 - 刘清政 - 博客园
Redis分布式锁-这一篇全了解(Redisson实现分布式锁完美方案)_redisson分布式锁实现-CSDN博客