您的位置:首页 > 其它

分布式锁和分布式事务协议学习笔记

2019-07-08 11:18 239 查看

分布式锁和分布式事务协议学习笔记

  • 1.2.2 基于缓存实现分布式锁
  • 1.2.3 基于Zookeeper实现分布式锁
  • 1.3 比较
  • 2. 分布式事务协议
  • 2.2.2 应用
  • 1. 分布式锁

    1.1 概念与要求

    操作不同数据库数据时,无法依赖于单个数据库锁的模式,需要有一个分布式锁来保证事务一致性。
    要求:
    1) 这把锁要是一把可重入锁(避免死锁)
    2) 这把锁最好是一把阻塞锁(根据业务需求考虑要不要这条)
    3) 有高可用的获取锁和释放锁功能
    4) 获取锁和释放锁的性能要好

    1.2 方法

    1.2.1 基于数据库实现分布式锁

    1.2.1.1 基于表记录实现

    在公用的数据库中建立一张锁表,将锁的属性设置为唯一性,比如某个方法需要做分布式锁,表中method_name列就是唯一性。

    当要获取某个方法的锁时,可以往表中插入数据。如果插入成功就获取锁,失败则无法获取。释放锁时,直接删除记录即可。
    此实现有几个问题:
    1) 单一数据库,不符合高可用(可采用主备模式解决)
    2) 锁没有失效时间,当解锁失败,锁一直存在(用定时任务清理过时锁)
    3) 锁是非阻塞的,一旦插入失败,没有排队机制(while循环获取)
    4) 锁是非重入(增加主机、线程等信息在获取之前查询一下本线程是否已经获取)

    1.2.1.2 基于数据库排它锁


    类似mysql中InnoDB引擎,利用for update机制,可以获取到锁。
    再利用comit来解锁。

    此实现存在问题:
    1) 单一数据库,不符合高可用
    2) 锁是阻塞锁,当for update不成功,将一直卡住。
    3) 锁是不是重入锁。

    1.2.2 基于缓存实现分布式锁

    目前市面有很多成熟的缓存架构,比如Redis,memcached以及Tair。基于redis实现的分布式锁。利用setNX和watch来实现分布式锁。使用缓存解决以下问题:
    1) 单一数据库,不符合高可用(可使用集群)
    2) 锁没有失效时间,当解锁失败,锁一直存在(有过期机制)
    3) 锁是非阻塞的,一旦插入失败,没有排队机制(while循环获取)
    4) 锁是非重入(将锁的信息包括主机、线程等信息放入数据中,在获取之前查询一下本线程是否已经获取)

    1.2.3 基于Zookeeper实现分布式锁

    1.2.3.1 概念

    基于zookeeper临时有序节点可以实现的分布式锁。
    大致思想即为:每个客户端对某个方法加锁时,在zookeeper上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点。 判断是否获取锁的方式很简单,只需要判断有序节点中序号最小的一个。 当释放锁的时候,只需将这个瞬时节点删除即可。同时,其可以避免服务宕机导致的锁无法释放,而产生的死锁问题。

    1.2.3.2 解决问题

    使用Zookeeper解决以下的问题。
    1) 锁无法释放?使用Zookeeper可以有效的解决锁无法释放的问题,因为在创建锁的时候,客户端会在ZK中创建一个临时节点,一旦客户端获取到锁之后突然挂掉(Session连接断开),那么这个临时节点就会自动删除掉。其他客户端就可以再次获得锁。
    2) 非阻塞锁?使用Zookeeper可以实现阻塞的锁,客户端可以通过在ZK中创建顺序节点,并且在节点上绑定监听器,一旦节点有变化,Zookeeper会通知客户端,客户端可以检查自己创建的节点是不是当前所有节点中序号最小的,如果是,那么自己就获取到锁,便可以执行业务逻辑了。
    3) 不可重入?使用Zookeeper也可以有效的解决不可重入的问题,客户端在创建节点的时候,把当前客户端的主机信息和线程信息直接写入到节点中,下次想要获取锁的时候和当前最小的节点中的数据比对一下就可以了。如果和自己的信息一样,那么自己直接获取到锁,如果不一样就再创建一个临时的顺序节点,参与排队。
    4) 单点问题?使用Zookeeper可以有效的解决单点问题,ZK是集群部署的,只要集群中有半数以上的机器存活,就可以对外提供服务。

    1.2.3.3 缺点

    1) Zookeeper实现的分布式锁其实存在一个缺点,那就是性能上可能并没有缓存服务那么高。
    2) 使用Zookeeper也有可能带来并发问题,由于网络抖动,客户端可ZK集群的session连接断了,那么zk以为客户端挂了,就会删除临时节点,这时候其他客户端就可以获取到分布式锁了。

    1.3 比较

    从理解的难易程度角度(从低到高)
    数据库 > 缓存 > Zookeeper

    从实现的复杂性角度(从低到高)
    Zookeeper >= 缓存 > 数据库

    从性能角度(从高到低)
    缓存 > Zookeeper >= 数据库

    从可靠性角度(从高到低)
    Zookeeper > 缓存 > 数据库

    2. 分布式事务协议

    2.1 两阶段提交协议

    分布式事务通常采用2PC协议,全称Two Phase Commitment Protocol。该协议主要为了解决在分布式数据库场景下,所有节点间数据一致性的问题。分布式事务通过2PC协议将提交分成两个阶段:
    prepare;
    commit/rollback
    阶段一为准备(prepare)阶段。即所有的参与者准备执行事务并锁住需要的资源。参与者ready时,向transaction manager报告已准备就绪。
    阶段二为提交阶段(commit)。当transaction manager确认所有参与者都ready后,向所有参与者发送commit命令。

    2.2 Paxos协议

    2.2.1 概念和算法

    Paxos是用于解决分布式系统中一致性问题的共识算法(Consensus Algorithm),其最基本的功能是为了在多个进程之间对某个值达成一致。通过这个最基本功能,就可以在多个进程之间进行数据库、状态机、账本(区块链)等对象的同步。

    基本概念

    ID:相互不冲突的提案编号,用于区分不同轮次的提案。
    Value:提案的值,即最后试图达成共识的候选结果。
    Propos 3ff7 er:提案发起者,用于提出议案,提案的内容为:令 x=value,对同一轮提案,最多提议一个value 。Proposer角度看,提案分为两个阶段:Prepare阶段、Propose阶段。一轮提案的value不一定非要是Proposer自己提议的value。
    Acceptor:提案投票者,有 N 个。Proposer 提出的 x=value 提案必须获得超过半数(N/2+1)的 Acceptor接受后才能被chosen。Acceptor 之间完全对等,在独立的时间轴执行提案投票。从Acceptor角度看,投票分两阶段进行:Promise阶段、Accept阶段。
    Learner:提案学习者。一个提案超过半数accpetor通过即可被chosen,其他未确定的Acceptor可以通过learner来同步结果。

    协议流程

    以下流程针对每个进程(多个Proposer、多个Acceptor)都是独立执行的,进程之间的处理逻辑可能是顺序执行的,也可能是交错的,这就带来了整体的不确定性。Paxos就是通过增加各种约束处理条件,降低不确定性,使得多进程之间通过多轮投票,最终能够达成一致。
    Prepare阶段
    A:Proposer选择一个提案编号n,向所有的Acceptor广播Prepare(n)请求。
    B:Acceptor收到Prepare(n)请求,若提案编号n比之前接收的Prepare请求都要大,则承诺(Promise,将n记录下来)将不会接收提案编号比n小的提议,并且带上之前Accept的提议中编号小于n的最大的提案value。如果n比之前接受的提案编号小,则不予理会。
    Propose阶段
    A:Proposer收到Acceptor的Promise如果未超过半数的accpetor回复承诺(Promise),本次提案失败;如果超过半数的Acceptor回复承诺,又分为不同情况:如果(回复承诺的)所有Acceptor都未接收过value(都为null),那么向所有的Acceptor发起(Propose)自己的value和提案编号n。如果有部分Acceptor接收过value,那么从接受过的value中选择提案编号最大的value作为本次提案的value,提议编号仍然为n(即:此时Proposer不能提议自己的value,只能信任Acceptor通过的value,以达成收敛的效果。)
    B:Acceptor接收到提议后,如果该提案编号不等于自身当前承诺的编号(第一阶段记录的),不接受该请求,相等则将提案的value写入本地。

    2.2.2 应用

    paxos算法允许存在多个leader,可能导致性能不高,而在此基础上,很多系统做了优化:
    1.redis使用raft算法,其实是一种简单化的paxos算法。其中利用一个term时间间隔(每台follower的时间间隔不一样)来定时发送选举请求,而且只有一个leader,只有leader挂掉后,才发起选举。
    2.zookeeper使用ZAB,其实也是一种简单化的paxos算法。ZAB同样用于主备模式,所以也是简化成一个leader模式。

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: