美文网首页
ZooKeeper(动物园管理员)

ZooKeeper(动物园管理员)

作者: 康俊1024 | 来源:发表于2019-02-15 15:26 被阅读0次

    一、概述

    ZooKeeper 是一个开源的分布式协调服务,由雅虎创建,是 Google Chubby 的开源实现。分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举分布式锁和分布式队列等功能。

    1. ZooKeeper角色

    在 ZooKeeper 中,有三种角色:Leader、Follower、Observer

    一个 ZooKeeper 集群同一时刻只会有一个 Leader,其他都是 Follower 或 Observer。当Leader奔溃后会从Follower重新选举一个出来,可以参考Zab协议

    Leader是zookeeper集群的核心

    ①事务请求的唯一调度者和处理者,保证集群事务请求的顺序性

    ②集群内部各个服务器的调度者

    Follower

    ①处理客户端非事务请求,以及转发事务请求给leader服务器

    ②参与事务请求提议的投票(客户端的一个事务请求,需要半数服务器投票通过后才能通知leader commit;要...)

    ③参与leader选举的投票

    Observer

    ①观察zookeeper集群中最新状态的变化将这些状态同步到observer服务器上

    ②增加observer不影响集群中事务处理能力,同时还能提升集群的非事务处理能力

    2.节点介绍

    ①PERSISTENT-持久化目录节点: 客户端与Zookeeper断开连接后,该节点依旧存在

    ②PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点: 客户端与Zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号

    ③EPHEMERAL-临时目录节点:客户端与Zookeeper断开连接后,该节点被删除

    ④EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点:客户端与Zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号

    二、ZooKeeper分布式锁的实现

    Zookeeper实现分布式锁是通过节点和临时顺序节点来实现的:

    ①在构造函数里面启动的时候建立一个节点,假如命名为:lock。节点类型为持久节点(PERSISTENT)【ZooKeeper里面的znode节点会自动同步的,而且是强一致性,创建一个节点后只有ZooKeeper集群同步完成后算成功】

    ②每当进程需要访问共享资源时,会在lock节点下面建立响应的顺序子节点,节点类型为临时顺序节点(EPHEMERAL_SEQUENTIAL)

    ③在建立子节点之后,判断刚刚建立的子节点顺序号是否为最小节点,如果是最小节点,则可以获得该锁对资源进行访问。(临时子节点建立会自动生成一个序号的)

    ④如果不是该节点,就获得该节点的上一顺序节点,并给该节点是否存在注册监听事件。同时在这里阻塞。等待监听事件的发生。获得控制权(实现watch接口,并且重写process方法,在process里面实现监听)

    ⑤当完成之后,关闭ZooKeeper连接,进而可以应发监听事件,释放该锁(客户端关闭ZooKeeper连接之后会删除当前的临时节点)

    知识点一:Zookeeper为了保证高吞吐和低延迟,在内存中维护了这个树状的目录结构,这种特性使得Zookeeper不能用于存放大量的数据,每个节点的存放数据上限为1M。

    知识点二:有序性是zookeeper中非常重要的一个特性,所有的更新都是全局有序的,每个更新都有一个唯一的时间戳,这个时间戳称为zxid(Zookeeper Transaction Id)。而读请求只会相对于更新有序,也就是读请求的返回结果中会带有这个zookeeper最新的zxid。

    知识点三:事件监听:在读取数据时,我们可以同时对节点设置事件监听,当节点数据或结构变化时,zookeeper会通知客户端。当前zookeeper有如下四种事件:1)节点创建;2)节点删除;3)节点数据修改;4)子节点变更。

    注意一:创建的临时节点能够保证在故障的情况下锁也能被释放,考虑这么个场景:假如客户端a当前创建的子节点为序号最小的节点,获得锁之后客户端所在机器宕机了,客户端没有主动删除子节点;如果创建的是永久的节点,那么这个锁永远不会释放,导致死锁;由于创建的是临时节点,客户端宕机后,过了一定时间zookeeper没有收到客户端的心跳包判断会话失效,将临时节点删除从而释放锁。

    注意二:获取子节点列表与设置监听这两步操作的原子性问题,考虑这么个场景:客户端a对应子节点为/lock/lock-0000000000,客户端b对应子节点为/lock/lock-0000000001,客户端b获取子节点列表时发现自己不是序号最小的,但是在设置监听器前客户端a完成业务流程删除了子节点/lock/lock-0000000000,客户端b设置的监听器岂不是丢失了这个事件从而导致永远等待了?这个问题不存在的。因为zookeeper提供的API中设置监听器的操作与读操作是原子执行的,也就是说在读子节点列表时同时设置监听器,保证不会丢失事件。

    注意三:这个算法有个极大的优化点:假如当前有1000个节点在等待锁,如果获得锁的客户端释放锁时,这1000个客户端都会被唤醒,这种情况称为“羊群效应”;在这种羊群效应中,zookeeper需要通知1000个客户端,这会阻塞其他的操作,最好的情况应该只唤醒新的最小节点对应的客户端。应该怎么做呢?在设置事件监听时,每个客户端应该对刚好在它之前的子节点设置事件监听,例如子节点列表为/lock/lock-0000000000、/lock/lock-0000000001、/lock/lock-0000000002,序号为1的客户端监听序号为0的子节点删除消息,序号为2的监听序号为1的子节点删除消息。

    三、master选举

    选主原理介绍:zookeeper的节点有两种类型,持久节点跟临时节点。临时节点有个特性,就是如果注册这个节点的机器失去连接(通常是宕机),那么这个节点会被zookeeper删除。选主过程就是利用这个特性,在服务器启动的时候,去zookeeper特定的一个目录下注册一个临时节点(这个节点作为master,谁注册了这个节点谁就是master),注册的时候,如果发现该节点已经存在,则说明已经有别的服务器注册了(也就是有别的服务器已经抢主成功),那么当前服务器只能放弃抢主,作为从机存在。同时,抢主失败的当前服务器需要订阅该临时节点的删除事件,以便该节点删除时(也就是注册该节点的服务器宕机了或者网络断了之类的)进行再次抢主操作。从机具体需要去哪里注册服务器列表的临时节点,节点保存什么信息,根据具体的业务不同自行约定。选主的过程,其实就是简单的争抢在zookeeper注册临时节点的操作,谁注册了约定的临时节点,谁就是master。

    四、zab协议原理:

    1.在zookeeper的主备模式下,通过zab协议来保证集群中各个副本数据的一致性。

    2.zookeeper使用单一的主进程来接收并处理所有的事务请求,并采用zab协议,把数据的状态变更以事务请求的形式广播到其他的节点。

    3.zab协议在主备模型架构中,保证了同一时刻只能有一个主进程来广播服务器的状态变更。

    4.所有的事务请求必须由全局唯一的服务器来协调处理。这个服务器叫leader,其他的叫follower。leader节点主要负责把客户端的事务请求转化成一个事务提议(proposal),并发给集群中的所有follower节点,再等待follower节点的反馈。一旦超过半数服务器进行了正确的反馈,那么leader就会commit这条消息。

    问题一:什么情况下zab协议会进入崩溃恢复模式

    a.当服务器启动时

    b.当leader服务器出现网络中断、崩溃或者重启的情况

    c.集群中已经不存在过半的服务器与该leader保持正常通信

    问题二:zab协议进入崩溃恢复模式会做什么

    a.当leader出现问题,zab协议进入崩溃恢复模式,并且选举新的leader。当新的leader选举出来以后,如果集群中已经有过半的机器完成了leader服务器的状态同步(数据同步),退出崩溃恢复,进入消息广播模式。

    b.当新机器加入到集群中的时候,如果已经存在leader服务器,那么新加入的服务器就会自觉的进入数据恢复模式,找到leader进行数据同步

    五、leader选举:默认FastLeaderElection

    重要参数:

    serverid:在配置server集群的时候,给定服务器的标识id(myid)

    zxid:服务器在运行时产生的数据ID,zxid越大,表示数据越新

    Epoch:选举的轮数

    server的状态:Looking Following Observering Leading

    第一次初始化启动的时候:Looking

    1.所有在集群中的server都会推荐自己为leader,然后把(myid,zxid,epoch)作为广播信息,广播给集群中的其他server,然后等待其他服务器响应。

    2.每个服务器都会接受来自集群中其他服务器的投票。集群中的每个服务器在接受到投票后,开始判断投票的有效性

        a.判断sid,如果sid大于当前的sid,说明自己保存的sid是过期的,更新sid,同时clear其他服务器发过来的选举数据。判断是否更新当前自己的数据

        b.如果sid小于目前的sid,说明对方的sid过期了,也就意味着对方服务器的选举轮数是过期的。这个时候,只需将自己的信息发送给对方

        c.等于时,根据规则来判断是否有资格获得leader接受到来自其他服务器的投票后,针对每一个投票,都需要将别人的投票和自己的投票进行     PK zkid,大的优先。

    3.统计投票

    相关文章

      网友评论

          本文标题:ZooKeeper(动物园管理员)

          本文链接:https://www.haomeiwen.com/subject/qbypeqtx.html