Zookeeper

  1. 概述

    Zookeeper 是一个分布式的,开放源码的分布式应用程序协调服务。

    提供的服务:统一命名服务、统一配置管理、统一集群管理、服务器节点动态上下线、软负载均衡

  2. 特点

    Zookeeper:一个领导者(Leader),多个跟随者(Follwer)组成的集群。

    集群中只要有半数以上节点存活,zookeeper集群就能正常服务。所以zookeeper适合安装奇数台服务器

    全局数据一致:每个Server保存一份相同的数据副本,Client无论连接哪个Server,数据都是一致的

    更新请求顺序执行,来自同一个Client的更新请求按其发送顺序依次执行。

    数据更新原子性,一次数据更新要么成功,要么失败。

    实时性,在一定时间范围内,Client能读到最新数据。

  3. 数据结构

    与Unix文件系统类似,整体上是一棵树,每个节点称为ZNode,每个ZNode默认能存储1MB的数据,每个ZNode可以通过其路径唯一标识。

  4. 应用场景

    统一命名服务:分布式环境下,经常需要对应用/服务进行统一命名,便于识别。 IP不容易记住,域名容易记住。

    统一配置管理:所有节点的配置信息是一致的。配置文件修改能够快速同步到各个节点上,

    统一集群管理:实时掌握每个节点的状态,根据节点实时状态做出一些调整。

    服务器节点动态上下线:客户端实时洞察服务器上下线变化。

    软负载均衡:记录每台服务器的访问数,让访问数最少的服务器去处理最新的客户端请求。

  5. 配置参数解读

    tickTime = 2000:通信心跳时间,zookeeper服务器与客户端心跳时间,单位毫秒

    initLimit = 10 :LF初始通信时限,Leader和Follower初始连接时能容忍的最多心跳数(tickTime的数量)

    syncLimit = 5 :LF同步通信时限,Leader和Follower之间通信时间如果超过syncLimit * tickTime,默认Follower 死掉,并进行删除。

    dataDir:保存zookeeper中的数据,默认的tmp目录,会被Linux系统定期删除。

    clientPort = 2181:客户端连接端口(通信端口)。

  6. 选举机制

    客户端每次写操作都有事务id(zxid)

    SID:服务器ID。用来唯一标识一台zookeeper集群中的机器,每台服务器不能重复,和myid一致。

    ZXID:事务ID。ZXID用来标识一次服务器状态的变更。

    Epoch:每个Lader任期的代号。没有Lader时同一轮投票过程中的逻辑时钟值是相同的。每投完一次票这个数据就会增加。

    1. 第一次启动

      ① 服务器1启动,发起一次选举。服务器1投自己一票。此时服务器1票,不够半数以上,选举无法完成,服务器1状态为LOOKING;

      ②服务器2启动,再次发起选举,服务器1和2分别投自己一票并交换选票信息:此时服务器1发现服务器2的myid比自己目前投票选举的大,更改为推举服务器二。此时服务器1为0票,服务器2为2票,没有半数,无法完成选举,服务器1、2状态为LOOKING;

      ③服务器3启动,再次发起选举。服务器1、2都会更改选票为服务器3,因为自身的myid比服务器3的小。此时服务器3的票数已经超过半数,服务器3当选Leader,服务器1、2状态更改为FOLLOWING,变成Follower,服务器3更改状态为LEADING;

      ④服务器4启动,再次发起选举,但Loader已经选出,所以不会更改选票信息,此时少数服从多数,更改自身的状态为FOLLOWING,成为Follower。

      ⑤服务器5启动,和④一样的流程。

    2. 非第一次启动

      ①当zookeeper集群中的一台服务器出现以下两种情况之一时,就会开始进入Loader选举:

      1. 服务器初始化启动

      2. 服务器运行期间无法和Leader保持连接

      ②当一台服务器进入Leader选举流程,当前集群也会处于以下两种状态:

      1. 集群中本来就已经存在一个Leader,其他的机器试图进行选举,会被告知当前服务器Leader信息,并且和Leader建立连接,进行状态同步。

      2. 集群中确实不存在Leader

        选举Leader规则:①EPOCH大的直接胜出 ②EPOCH相同,事务id大的胜出 ③事务id相同,服务器id大的胜出

  7. 客户端命令行操作

    命令行语法

    命令基本语法功能描述
    help 显示所有操作命令
    Is path 使用 Is 命令来查看当前znode的子节点[可监听] -w 监听子节点变化 -s 附加次级信息
    create 普通创建 -s 含有序列 -e 临时(重启或者超时消失)
    get path 获得节点的值[可监听] -w 监听节点内容变化 -s 附加次级信息
    set 设置节点的具体值
    stat 查看节点状态
    delete 删除节点
    deleteall 递归删除节点

    czxid:创建节点的事务zxid

    每次修改zookeeper状态都会产生一个zookeeper事务ID。事务ID是zookeeper中所有修改总的次序,每次修改都有唯一的zxid。

    ctime:znode被创建的毫秒数(从1970年开始)

    mzxid:znode最后更新的事务zxid

    mtime:znode最后修改的毫秒数(从1970年开始)

    pZxid:znode最后更新的子节点zxid

    cversion:znode子节点变化号,znode子节点修改次数

    dataversion:znode数据变化号

    aclVersion:znode访问控制列表的变化号

    ephemeralOwner:如果是临时节点,这个是znode拥有者的session id。如果不是临时节点则是0。

    dataLength:znode的数据长度

    numChildren:znode子节点数量

  8. 节点类型(持久/短暂/有序号/无序号)

    创建Znode时设置顺序标识,Znode名称后附加一个值,顺序号是一个单调递增的计数器,由父节点维护。顺序号可以被用于为所有的事件进行全局排序,客户端可以通过顺序号推断事件的顺序。

    持久(Persistent):客户端和服务器端断开连接后,创建的节点不删除

    短暂(Ephemeral):客户端和服务器端断开连接后,创建的节点自己删除

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

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

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

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

  9. 监听器

    1) 首先要有一个main()线程

    2) 在main线程中创建zookeeper客户端,这是就会创建两个线程,一个负责网络连接通信(connet),一个负责监听(listener)

    3) 通过connect线程将注册的监听事件添加到列表中

    4) 在zookeeper的注册监听器列表中将注册的监听事件添加到列表中

    5) zookeeper监听到有数据或路径变化,就会将这个消息发送给listener线程

    6) listener线程内部调用了process()方法

    常见的监听

    1) 监听节点数据的变化 get path [watch]

    2) 监听子节点增减的变化 Is path [watch]

  10. zookeeper分布式锁案例

    create -e -s /locks/seq- 创建临时顺序节点

    1) 接收到请求后,在/locks节点下创建一个临时顺序带序号的节点 -- 获取到锁处理业务

    2) 判断自己是不是当前节点下最小的节点:是,获取到锁;不是,对前一个节点进行监听

    3) 获取到锁,处理完业务后,delete节点释放锁,然后下面的节点将收到通知,重复第二步判断

  11. Curator 框架

    1)原生的Java API 开发存在问题:

    (1)会话连接是异步的,需要自己去处理。比如使用CountDownLatch

    (2)Watch需要重复注册,不然就不能生效

    (3)开发的复杂性还是比较高

    (4)不支持多节点删除和创建。需要自己去递归

    2)Curator是一个专门解决分布式锁的框架,解决原生Java API分布式的问题。

     

  12.  

posted on 2021-10-25 16:18  白糖℃  阅读(48)  评论(0编辑  收藏  举报