zoukankan      html  css  js  c++  java
  • 个人学习分布式专题(二)分布式服务治理之分布式协调技术Zookeeper

    分布式协调技术Zookeeper

     2.1 zookeeper集群安装部署(略)

      2.2 zookeeper的基本原理,数据模型

      2.3 zookeeper Java api的使用

      2.4 zookeeper实际应用场景分析及实战

      2.5 zookeeper+dubbo的实战练习(略)


    zookeeper的基本原理,数据模型:

    dubbo的服务注册中心就是基于zookeeper。zookeeper是一种分布式协调服务(可以在分布式系统中共享配置,协调锁资源,提供命名服务)。

    zookeeper的目标:封装好复杂易出错的关键职务,将简单易用的接口和性能高效、功能稳定的系统提供给用户;

    zookeeper的特点:

    • 最终一致性:为客户端展示同一视图,这是Zookeeper最重要的性能;
    • 可靠性:如果消息被一台服务器接受,那么它将被所有的服务器接受;
    • 原子性:更新只能成功或失败,没有中间状态;

    zookeeper的数据结构:zookeeper的数据存储是基于节点,叫Znode;它的引用方式是路径引用,类似于文件路径;Znode包含数据,子节点引用,访问权限等;

    data:

    Znode存储的数据信息。

    ACL:

    记录Znode的访问权限,即哪些人或哪些IP可以访问本节点。

    stat:

    包含Znode的各种元数据,比如事务ID、版本号、时间戳、大小等等。

    child:

    当前节点的子节点引用,类似于二叉树的左孩子右孩子。

      需注意:zookeeper是为读多写少的场景所设计的,Znode并不是用来存储大规模业务数据的,而是用于存储少量的状态和配置信息的,每个节点的数据最大不能超过1MB;

     Znode分为四种类型:

      1.持久节点:默认的节点类型,创建节点的客户端和zookeeper断开连接后,该节点一直存在

      2.持久节点顺序节点:创建节点时,zookeeper根据创建的时间顺序给该节点名称进行编号

      3.临时节点:当创建节点的客户端和zookeeper断开连接后,临时节点就会被删除

      4.临时顺序节点:根据创建时间排序的临时节点

    如何实现分布式一致性为防止单机挂掉的情况,Zookeeper维护了一个集群,如图所示:

    zookeeper的集群是一主多从的结构,在更新数据时,首先更新到主节点(主节点:服务器,不是Znode),再同步到从节点;在读取数据时,直接读取任意从节点

    为了保证主从节点的数据一致性,zookeeper采用了ZAB协议,这种协议非常类似于一致性算法Paxos和Raft

      ZAB(Zookeeper Atomic Broadcast):有效解决Zookeeper集群崩溃恢复,以及主从同步数据的问题; 

    ZAB协议是单调一致性,依靠事物ID和版本号,保证了数据的更新和读取是有序的;

    ZAB协议所定义的三种节点状态:looking(选举状态),following(follower节点所处的状态),leading(leader节点所处的状态)

      ZXID:节点本地的最新事物编号,包含epoch和计数两部分;epoch是纪元的意思,相当于Raft算法选主时的term  

      ------假如zookeeper当前的主节点挂掉了,集群会进行崩溃恢复:

      阶段一:

          leader election:选举阶段,此时集群中的节点处于looking状态,它们会各自向其他节点发起投票,投票当中包含自己的服务器ID和最新事物ID(zxid)节点自身会与从其他节点接收到的zxid做对比,对方大则对方数据更新,则重新发起投票,投票给目前已知最大的zxid所属节点每次投票后,服务器都会统计投票数,判断是否有某个节点得到半数以上的投票,如果存在,该节点变为leader,状态变为leading,其他则为following

      阶段二:

          Discovery:发现阶段,用于从节点中发现最新的zxid和事物日志,为防止某些意外情况产生多个leader。如果出现两个准leader,都会发出new epoch消息给各个Follower,必然有一个Leader的 epoch并不是最新的。Follower发现接收的epoch没有自身保存的epoch新,就会重新变为Looking状态,重新寻找真正的Leader。所以这一阶段,leader接收所有来自follower发来的各自最新的epoch值,leader从中选出最大的epoch,基于此值加1,生成新的epoch分发给各个follower,各个follower接收到全新的epoch后,返回ACK给leader,带上各自最大的zxid和历史事物日志。leader选出最大的zxid,并更新自身历史日志

      阶段三:

          Synchronization:同步阶段,把leader刚收集到的最新历史事物日志,同步给集群中所有的follower,只有半数follower同步成功,这个准leader才能称为正式leader自此,故障恢复正式完成。

      ------ZAB实现写入数据,涉及ZAB协议的Broadcast阶段:Zookeeper常规情况下更新数据的时候,由leader广播到所有follower

      •  客户端发出写入数据请求给任意follower
      •  follower把写入数据请求转法给leader
      •  leader采用二阶段提交方式,先发送propose广播给follower
      •  follower接到propose消息,写入日志成功后,返回ACK消息给leader
      •  leader接到半数以上ACK消息,返回成功给客户端,并且广播commit请求给follower

    都有哪些应用场景:

      •  分布式锁
      •  服务注册和发现:利用Znode和Watcher,可以实现分布式服务的注册和发现,如dubbo
      •  共享配置和状态信息:redis的分布式解决方案codis,利用了zookeeper来存放数据路由表和codis-proxy节点的元信息。同时codis-config发起的命令都会通过zookeeper同步到各个存活的codis-proxy

       此外kafka,hbase,hadoop,也都依靠zookeeper同步节点信息,实现高可用

    zookeeper Java api的使用

    create:创建节点 ;

    delete:删除节点;

    exists:判断节点是否存在;

    getData:获得一个节点的数据;

    setData:设置一个节点的数据;

    getChildren:获取节点下的所有子节点

    这其中,exists,getData,getChildren属于读操作。Zookeeper客户端在请求读操作的时候,可以选择是否设置Watch。

    Watch是什么意思呢?

    我们可以理解成是注册在特定Znode上的触发器。当这个Znode发生改变,也就是调用了create,delete,setData方法的时候,将会触发Znode上注册的对应事件,请求Watch的客户端会接收到异步通知

    具体交互过程如下:

    1.客户端调用getData方法,watch参数是true。服务端接到请求,返回节点数据,并且在对应的哈希表里插入被Watch的Znode路径,以及Watcher列表。

    2.当被Watch的Znode已删除,服务端会查找哈希表,找到该Znode对应的所有Watcher,异步通知客户端,并且删除哈希表中对应的Key-Value。

    zookeeper实现分布式锁:    (转自:https://mp.weixin.qq.com/s/u8QDlrDj3Rl1YjY4TyKMCA)

    zookeeper分布式锁应用了临时顺序节点,支持可重入

    获取锁首先在zookeeper中创建一个持久节点的ParentLock,当第一个客户端想要获得锁时,需要在ParentLock这个节点下创建一个临时顺序节点Lock1

    之后,Client1查找ParentLock下面所有的临时顺序节点并排序,判断自己所创建的节点Lock1是不是顺序最靠前的一个。如果是第一个节点,则成功获得锁。

    这时候,如果再有一个客户端 Client2 前来获取锁,则在ParentLock下载再创建一个临时顺序节点Lock2。

    Client2查找ParentLock下面所有的临时顺序节点并排序,判断自己所创建的节点Lock2是不是顺序最靠前的一个,结果发现节点Lock2并不是最小的。

    于是,Client2向排序仅比它靠前的节点Lock1注册Watcher,用于监听Lock1节点是否存在。这意味着Client2抢锁失败,进入了等待状态。

    这时候,如果又有一个客户端Client3前来获取锁,则在ParentLock下载再创建一个临时顺序节点Lock3。

    Client3查找ParentLock下面所有的临时顺序节点并排序,判断自己所创建的节点Lock3是不是顺序最靠前的一个,结果同样发现节点Lock3并不是最小的。

    于是,Client3向排序仅比它靠前的节点Lock2注册Watcher,用于监听Lock2节点是否存在。这意味着Client3同样抢锁失败,进入了等待状态。

    这样一来,Client1得到了锁,Client2监听了Lock1,Client3监听了Lock2。这恰恰形成了一个等待队列,很像是Java当中ReentrantLock所依赖的AQS(AbstractQueuedSynchronizer)。

    释放锁:

    1.任务完成,客户端显示释放:当任务完成时,Client1会显示调用删除节点Lock1的指令。

    2.任务执行过程中,客户端崩溃:获得锁的Client1在任务执行过程中,如果Duang的一声崩溃,则会断开与Zookeeper服务端的链接。根据临时节点的特性,相关联的节点Lock1会随之自动删除。由于Client2一直监听着Lock1的存在状态,当Lock1节点被删除,Client2会立刻收到通知。这时候Client2会再次查询ParentLock下面的所有节点,确认自己创建的节点Lock2是不是目前最小的节点。如果是最小,则Client2顺理成章获得了锁。

  • 相关阅读:
    微信二维码 场景二维码 用于推送事件,关注等 注册用户 ,经过测试
    简单的 Helper 封装 -- CookieHelper
    简单的 Helper 封装 -- SecurityHelper 安全助手:封装加密算法(MD5、SHA、HMAC、DES、RSA)
    Java反射机制
    Windows Azure Web Site (13) Azure Web Site备份
    Windows Azure Virtual Machine (1) IaaS用户手册
    Windows Azure Web Site (1) 用户手册
    Windows Azure Web Site (12) Azure Web Site配置文件
    Windows Azure Web Site (11) 使用源代码管理器管理Azure Web Site
    Windows Azure Web Site (10) Web Site测试环境
  • 原文地址:https://www.cnblogs.com/hangzhi/p/9101272.html
Copyright © 2011-2022 走看看