chubby分布式锁服务概述

分布式锁与chubby

分布式锁,是控制分布式系统之间同步访问共享资源的一种方式。Chubby是一种面向松耦合的分布式系统的锁服务,通常用于为一个由适度规模的大量小型计算机构成的的松耦合的分布式系统提供高可用的分布式锁服务。锁服务的目的是允许它的客户端进程同步彼此的操作,并对当前所处环境的基本状态信息达成一致。因此,Chubby的主要设计目标是为一个由适度大规模的客户端进程组成的分布式场景提供高可用的锁服务,以及易于理解的API接口定义。而值得一提的是,在Chubby的设计过程中,系统的吞吐量和存储容量并不是首要考虑的因素。Chubby的客户端接口设计非常类似于文件系统结构,不仅能够对Chubby上的整个文件进行读写操作,还能够添加对文件节点的锁控制,并且能够订阅Chubby服务端发出的一系列文件变动的事件通知。

chubby概述

chubby在实现分布式锁的时候,主要考虑的是通过小文件读写服务的方式来进行Master选举结果的发布与订阅,Chubby客户端需要实时的感知到Master的变化情况,Chubby需要有能力将服务端的数据变化情况以时间通知的形式通知到所有订阅的客户端,利用租约机制来加入缓存机制从而达到数据一致性与较高的响应性能,通过访问控制来保住服务端数据的安全性。

Chubby设计为只提供面向粗粒度锁机制的锁服务,而放弃对细粒度锁控制的支持。即可降低对服务器端的压力,也可让用户自行实现一定的业务逻辑。其基本的结构如下;

在这里插入图片描述

chubby的架构设计如上所示。

chubby架构

推荐的部署模式是五台部署,因为数据一致性需要通过一致性的算法来进行确定,采用的Quorum机制(即需要获得绝大多数的从节点同意才算数据提交成功),所以奇数台机器可以快速的有效的进行判读数据是否提交成功。

在运行过程中,只有master节点才能够进行数据的修改创建操作,操作完成的数据通过一致性算法同步到follower节点。客户端在连接到服务端的过程中,如果连接的是master服务器则接着进行数据交互,如果连接的是从节点,则从节点会返回master服务器的信息,客户端直连master节点,从而为后面提交修改数据,并且可以获取订阅服务的修改与变更。如果在运行过程中,master节点崩溃,从节点会在租期到期之后进行重新选举,重新选择出主节点,从而客户端会重新连接到新的master节点继续运行。

启动过程的流程

此时,启动的过程中会启动选举,此时就统计哪个节点获取最多的票数,从而完成对master的选举,根据zookeeper的实现可知,在选举过程中,会生成一个id从而检查获取的选票是哪个周期的选举。在该流程中,ServerA发起了选举投票,并且ServerB稍后也发起了选举投票,此时就看哪个节点先接受到了超过半数的选票,在ServerB发起的选举投票中,此时ServerA已经获取了大部分的选票,并通知各个节点,主节点的信息。从而完成选举。

在运行过程中,如果master节点突然崩溃,在超过一个租约的过程中(此时也可以根据心跳)来判断是否master节点还存活,如果在一个租约中,没有得到反馈则会发起选举过程,从而重新选择master。

数据与权限

在chubby中,数据的展示形式类似与常用的文件系统形式,例如;

/ls/foo/wombat/pouch

其中“ls”是所有Chubby节点所共有的前缀,代表着锁服务(lock service)。第二个部分(foo)是Chubby集群的名字,并可以由一个服务器集群来组成该服务。名字的剩余部分(/wombat/pouch),则是一个真正包含业务含义的节点名字,由Chubby服务器内部解析并定位到数据节点。同样跟UNIX系统一样,每个目录都可以包含一系列的子文件和子目录列表,而每个文件中则会包含文件内容。在chubby中节点分为临时节点和持久节点,临时节点就是与会话保持一致的节点,当会话消失时该节点就会删除,持久节点就会被一致保持在服务端,并会被集群所保存。在节点上面包含一些元数据和控制信息,通过控制权限可限制客户端访问数据的权限,在实现锁的过程中,chubby通过请求一个序号器,来访问服务端,服务器接收到这样的请求后,会首先检测该序号器是否有效,以及检查客户端是否处于恰当的锁模式;如果没有检查通过,那么服务端就会拒绝该客户端请求。在客户端已经持有锁的过程中,如果出现网络突然断线也会造成锁的突然失效,故会添加一个锁延时,如果在延时时间内该客户端重新连接上,则该锁可以继续被该客户端持有并使用,如果锁延时到期之后该客户端还未能重新连接,则会让接下来的其他客户端来持有该锁。

缓存与故障恢复

为了减少客户端和服务端之间读请求的数据传输量,Chubby客户端会将数据及节点信息缓存在内存,从而达到较高的访问效率,master上维护着每个客户端的数据缓存情况,并通过向客户端发送过期信息来维护客户端数据的一致性。当文件或节点的元数据信息被修改时,Chubby首先会阻塞该修改操作,然后由master向所有可能缓存了该数据的客户端发送缓存过期信号,等到Master在接收到所有相关的客户端针对该过期信号的应答后(应答包括两类,一种是客户端明确要求更新缓存,另一类则是客户端允许缓存租期过期),在继续之前的修改操作。从而完成数据一致性的操作,该操作就是在租约的基础上,在修改数据的情况下,主动通知可能缓存过期数据的客户端,然后通过客户端缓存数据失效,再收到客户端的确认删除过期数据之后再继续数据的更新修改操作,从而保证了数据的强一致性。

在故障的回复过程中,当在正常运行的时候,客户端通过访问master获取租约并操作数据,此时客户端会缓存租约,并保持会话,假如master节点突然崩溃,此时客户端还会持有租约,但是在续约的过程中master不能响应客户端的请求,故客户端会清空本地的数据,然后再尝试连接服务端,当服务端重新选举完成之后,此时客户端就会被告知master节点的位置,在连接到新的master节点之后,此时服务端检查的租约信息与当前租约的周期不同,则重新向客户端颁发一个新的租约周期,并将数据返回给客户端缓存,在此过程中,新选举出来的master需要进来一下步骤才能继续提供服务;

  1. 新的master节点会重新生成一个周期id,以区分不同周期过程中的周期,用来标识是否处于同一个周期;
  2. master会处理数据请求但不会处理会话处理;
  3. master会根据保存的数据重新构建服务端数据的内存状态,从而重新完成数据的加载;
  4. 此时处理客户端的会话信息,并给每个会话发送一个故障恢复的信息,让客户端重新清空本地的缓存;
  5. 在客户端响应故障恢复的信息的过程中,会一直等待所有客户端完成,待完成之后再进行新的会话的处理;

大致的处理过程如上,在故障的处理过程中,数据的恢复主要就是通过数据的备份机制来进行新的master的信息的重建,该数据备份同步的过程也可以通过Quorum机制,只要大部分节点同意了该数据的更新,则将该数据提交到本地的备份数据中去,从而完成信息的一致性。

chubby与zookeeper

chubby当前还没有开源的代码,zookeeper主要就是根据该模式的开源实现,大家如有兴趣可以去查看zookeeper的源码,在zookeeper的实现过程中,并没有采用paxos算法来保证数据的一致性,而是通过Quorum机制来保证修改数据的一致性,在其他的论文中也讨论论文chubby通过paxos机制来实现数据备份的一致性大家有星球可自行查看。

总结

本文只是简单的阅读了一下chubby的论文内容,其基本的实现过程与zookeeper的实现思路高度相似,大家可通过查阅zookeeper的实现来更深刻的理解论文的基本思想,分布式锁与分布式数据一致性一直都是比较复杂、需要根据场景进行取舍的内容,场景的侧重点更偏向于解决一类问题,本文的内容比较浅并没有深入的去探讨与学习,例如在选举的过程中,也会出现多种异常情况,例如选举过程中突然出现网络分区,并且如果出现了分区之后多个主之后的数据如果保持一致也需要额外的去保证与讨论。由于本人才疏学浅,如有错误请批评指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章