Zookeeper入门(1)——zookeeper的基本概念

【项目地址】 从零开始学习springmvc
如果觉得有用可以关注一下公众号:码字不易,求赞求关注
程序猿不加班

一、Zookeeper

1、Zookeeper是什么?

ZooKeeper是为分布式应用提供高性能协调服务的Apache项目。

2、Zookeeper的作用

  • 分布式配置信息维护
  • 分布式同步(分布式锁)
  • 统一命名服务
  • 集群管理
  • 队列管理

3、Zookeeper的特性

  • 原子性

    一次数据更新要么成功(半数以上),要么失败,不存在中间状态

  • 一致性

    每个server保存一份数据副本,client从每个server获取的数据都是一致的

  • 可靠性

    如果消息被一个server接收,则所有的server都接收

  • 顺序性

    包括全局有序和偏序两种:全局有序是指如果在一台服务器上消息 a 在消息 b 前发布,则在所有 Server 上消息 a 都将在消息 b 前被发布;偏序是指如果一个消息 b 在消息 a 后被同一个发送者发布,a 必将排在 b 前面。

  • 实时性

    Zookeeper 保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。但由于网络延时等原因,Zookeeper 不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用 sync() 接口

4、Zookeeper的架构

  • Leader(领导者)

    在ZooKeeper集群中只有一个节点作为集群的领导者,由各Follower通过ZooKeeper Atomic Broadcast(ZAB)协议选举产生,主要负责接收和协调所有写请求,并把写入的信息同步到Follower和Observer。

  • Learner(学习者)

    Leaner又分为Follower和Observer两种角色,二者区别是Observer不参与选举和写请求的投票,用于分摊Follower的系统负担。

    • Follower(跟随者)

      当leader发生故障时,进行投票选举leader;处理读请求,并配合Leader一起进行写请求处理。

    • Observer(观察者)

      Observer不参与选举和写请求的投票,只负责处理读请求、并向Leader转发写请求,避免系统处理能力浪费。

  • Client(客户端)

    读写请求发起方。

5、 数据模型和分层命名空间

5.1 命名空间

Zookeeper的命名空间类似unix标准文件系统,名称是由斜杠 (/) 分隔的一系列路径元素。 ZooKeeper 命名空间中的每个节点都由路径标识。

5.2 节点类型(Znode)

与标准的文件系统不同,Zookeeper的命名空间中的每个节点都可以拥有与其关联的数据以及子节点。这就像一个即是文件也是目录的文件系统。ZooKeeper 被设计用来存储一致性数据:如状态信息、配置、位置信息等,所以每个节点存储的数据通常很小,在字节到千字节的范围内。节点被称为Znode。

Znode 维护一个数据结构,其中包括数据更新的版本号、ACL (Access Control List)更新和时间戳,可以实现缓存验证和一致性更新。 每次 znode 的数据更改时,版本号都会增加。 例如,每当客户端检索数据时,它也会收到数据的版本号。存储在命名空间中每个 znode 的数据是原子性读取和写入的。read会获取与 znode 关联的所有数据字节,write会替换所有数据。 每个节点都有一个访问控制列表 (ACL),它限制谁可以做什么。

3.6.2以上版本的节点类型有七种

  • PERSISTENT 持久化节点:

    所谓持久节点,是指在节点创建后,就一直存在,直到有删除操作来主动清除这个节点。否则不会因为创建该节点的客户端会话失效而消失。

  • PERSISTENT_SEQUENTIAL 持久顺序节点

    这类节点的基本特性和上面的节点类 型是一致的。额外的特性是,在 ZK 中,每个父节点会为他的第一级子节点维护一份时序, 会记录每个子节点创建的先后顺序。基于这个特性,在创建子节点的时候,可以设置这个属 性,那么在创建节点过程中,ZK 会自动为给定节点名加上一个数字后缀,作为新的节点名。 这个数字后缀的范围是整型的最大值。 在创建节点的时候只需要传入节点 /test_,这样之后,zookeeper 自动会给test_后面补充数字。

  • EPHEMERAL 临时节点

    和持久节点不同的是,临时节点的生命周期和客户端会话绑定。也就是说,如果客户端会话失效,那么这个节点就会自动被清除掉。注意,这里提 到的是会话失效,而非连接断开。另外,在临时节点下面不能创建子节点。 这里还要注意一件事,就是当你客户端会话失效后,所产生的节点也不是一下子就消失 了,也要过一段时间,大概是 10 秒以内,可以试一下,本机操作生成节点,在服务器端用 命令来查看当前的节点数目,你会发现客户端已经 stop,但是产生的节点还在。

  • EPHEMERAL_SEQUENTIAL 临时自动编号节点

    此节点是属于临时节点,不过带 有顺序,客户端会话结束节点就消失。

  • CONTAINER

    容器节点,一旦子节点被删除完就会被服务端删除。

  • PERSISTENT_WITH_TTL

    带过期时间的持久节点,带有超时时间的节点,如果超时时间内没有子节点被创建,就会被删除。

  • PERSISTENT_SEQUENTIAL_WITH_TTL

    带过期时间的持久顺序节点,基本同上,多了一个数字后缀。

注意事项

  • ZK不支持递归创建,即无法在父节点不存在的情况下创建子节点。
  • ZK节点数据类型只支持字节数组类型(byte[]),也就是ZK不负责为节点内容进行序列化和反序列化。

5.3 事件机制(监听通知机制,Watcher)

Watcher 监听机制是 Zookeeper 中非常重要的特性,我们基于 zookeeper 上创建的节点,可以对这些节点绑定监听事件,比如可以监听节点数据变更、节点删除、子节点状态变更等事件,通过这个事件机制,可以基于 zookeeper实现分布式锁、集群管理等功能

5.3.1 Watcher特性

watcher 特性:当数据发生变化的时候, zookeeper 会产生一个 watcher 事件,并且会发送到客户端。但是客户端只会收到一次通知。如果后续这个节点再次发生变化,那么之前设置 watcher 的客户端不会再次收到消息。(watcher 是一次性的操作)。 可以通过循环监听去达到永久监听效果。

5.3.2 Watcher流程处理

ZooKeeper 的 Watcher 机制,总的来说可以分为三个过程:客户端注册 Watcher、服务器处理 Watcher 和客户端回调 Watcher客户端。注册 watcher 有 3 种方式,getData、exists、getChildren;凡是事务类型的操作,都会触发监听事件,如create /delete /setData。

6、Zookeeper的实现机制

6.1 Paxos算法

请参考【Paxos、Raft分布式一致性最佳实践

6.2 ZAB协议

ZAB协议全称为ZooKeeper Atomic Broadcast , ZooKeeper 原子消息广播协议。ZAB协议的实现主要是依赖事务编号(Transaction id)Zxid实现。

6.2.1 事务编号 Zxid(事务请求计数器+ epoch)

​ Zxid(Transaction id) 类似于 RDBMS 中的事务 ID,用于标识一次更新操作的 Proposal(提议)ID。为了保证顺序性,该 zxid 必须单调递增。

​ Zxid 是一个 64 位的数字,其中低 32 位是一个简单的单调递增的计数器, 针对客户端每一个事务请求,计数器加 1;而高 32 位则代表 Leader 周期 epoch 的编号, 每个当选产生一个新的 Leader 服务器,就会从这个 Leader服务器上取出其本地日志中最大事务的 ZXID,并从中读取epoch 值,然后加 1,以此作为新的 epoch,并将低 32位从 0 开始计数。

epoch:可以理解为当前集群所处的年代或者周期,每个 leader 就像皇帝,都有自己的年号,所以每次改朝换代, leader 变更之后,都会在前一个年代的基础上加 1。这样就算旧的 leader 崩溃恢复之后,也没有人听他的了,因为 follower 只听从当前年代的 leader 的命令

6.2.2 ZAB协议模式

ZAB协议模式有两种模式:恢复模式(选主)广播模式(同步)

  • 恢复模式:当服务器启动或者Leader崩溃时就进入恢复模式。当Leader被选举出来,且大多数Server完成了与Leader的状态同步后,恢复模式就结束了。
  • 广播模式:状态同步保证了 leader 和 Server 具有相同的系统状态。
6.2.3 ZAB 协议4阶段
  • Leader Election(选举阶段,选出准leader)

    节点一开始都处于选举阶段,一个节点只要得到半数以上的票数,就可以当选为准Leader。只有到达广播阶段(broadcast),准Leader才能称为真正的Leader。这一阶段主要是为了选出准Leader,然后进入下一阶段。

  • Discovery(发现阶段,接收提议、生成epoch,接收epoch)

    在这一阶段Followers与准Leader进行通信,同步Followers最近接收的事务提议。这一阶段的主要目的是发现大多数节点接收的最新提议,并且准Leader生成新的epoch,让Followers接收,更新他们的Accepted epoch。一个Follower只会连接一个Leader,如果有一个节点f认为另一个Follower p是Leader时,f在尝试连接时会被p拒绝(p的zxid小于f),f被拒绝后就会重新进入选举阶段。

  • Synchronization(同步阶段)

    同步阶段主要是利用前一阶段Leader获得的最新提议历史,同步集群中的所有副本。只有当大多数节点完成同步后,准Leader才会成为真正的leader。follower只会接收zxid比自己lastZxid大的提议。

  • Broadcast(广播阶段)

    zookeeper在此阶段下才能对外提供服务。Leader会进行消息广播,如果有新集群加入,leader还会同步新集群。

ZAB提交事务不需要像2PC(2阶段提交)那样全部ACK,只要半数以上节点ACK即可

6.2.4 ZAB 协议的Java实现

Zab的java实现和协议定义有所不同。

  • 选举阶段使用的是Fast Leader Election,简称FLE,即选举拥有最新历史提议的节点作为Leader,省去了发现最新历史提议的步骤
  • 发现阶段和同步阶段合并为Recovery(恢复阶段)

实际实现只有三个阶段:Fast Leader Election(快速选举阶段)、Recovery(恢复阶段)和 Broadcast(广播阶段)。

6.2.5 投票机制
  1. 每个Server启动以后,都会询问其他的Server它要投票给谁。对于其他server的询问,server每次都会根据自己的状态回复自己推荐的Leader的id和上一次处理事务的zxid(系统启动是每个Server都会推荐自己)。
  2. 收到Server的所有回复以后,就计算出zxid最大的那个server。并将这个server设置下一次投票的server。
  3. 获得票数最多的为获胜者,获胜者票数超过半数就会被选为Leader。否则继续上述过程,直到Leader选出。
  4. Leader等待Follower的连接
  5. Follower连接server,将最大的Zxid发给leader。
  6. Leader根据Follower的Zxid确定同步点,至此选举阶段完成。
  7. 选举阶段完成后,Leader同步后通知Follower状态为updated。
  8. Follower状态为updated后,又可以接收client的连接。

7、Zookeeper部署

7.1 伪集群模式部署

安装依赖jdk,若没有安装jdk请先安装。检查jdk是否安装

java -version
openjdk version "11" 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)
  1. 下载zookeeper安装包,到环境上解压:

    【Apache Zookeeper】https://zookeeper.apache.org/releases.html。

    注意要下载后缀为bin.tar.gz的程序包,不带bin的为源码包!!!

    在linux环境上创建zookeeper目录,将安装包拷贝到此处并解压

    mkdir zookeeper
    tar -zxvf apache-zookeeper-3.5.7-bin
    
  2. 在zookeeper目录下创建配置目录config、数据目录data和日志目录log三个文件夹

    /zookeeper
    	|----apache-zookeeper-3.5.7-bin		#zookeeper的程序包
    	|----config		#存放zookeeper的配置文件
    	|----data		#存放zookeeper的数据
    	|----log		#存放zookeeper的日志
    
  3. zookeeper的配置参数放在apache-zookeeper-3.5.7-bin/conf/zoo_simple.cfg下,各项参数含义如下:

    • tickTime:ZK服务器与客户端通信心跳时间,单位ms。session的最小超时时间是2*tickTime
    • initLimit:集群中的Follower跟随者服务器与Leader领导者服务器之前初始连接时能容忍的最多心跳(tickTime)数量,用来限定集群中的Zookeeper服务器连接到Leader的时限。
    • syncLimit:集群中的Leader与Follower之间的最大响应时间单位,假如响应超过syncLimit*tickTime,Leader认为Follower死掉,从服务器列表中删除Follower。
    • dataDir:数据文件目录+数据持久化路径,主要保存Zookeeper的snapshot等数据。
    • clientPort:客户端连接的端口。
    • dataLogDir:日志存储文件。
    • extendedTypesEnabled:是否启用扩展功能。
    • server.A=B:C:D:集群部署模式参数。
      • A 是一个数字,表示这个是第几号服务器;集群模式下配置一个文件 myid,这个文件在 dataDir 目录下,这个文件里面有一个数据就是 A 的值,Zookeeper 启动时读取此文件,拿到里面的数据与 zoo.cfg 里面的配置信息比较从而判断到底是哪个 server。
      • B 是这个服务器的地址;
      • C 是这个服务器 Follower 与集群中的 Leader 服务器交换信息的端口;
      • D 是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口。
  4. 配置三个节点的配置文件并放置在config目录下,分别为zk1.cfgzk2.cfgzk3.cfg, 并在datalog目录下分别创建zk1zk2zk3目录。

    /zookeeper
    	|----apache-zookeeper-3.5.7-bin		#zookeeper的程序包
    	|----config		#存放zookeeper的配置文件
    		|----zk1.cfg
            |----zk2.cfg
            |----zk3.cfg
    	|----data		#存放zookeeper的数据
    		|----zk1
            |----zk2
            |----zk3
    	|----log		#存放zookeeper的日志
    		|----zk1
            |----zk2
            |----zk3
    

    其中zk1.cfg配置如下:

    # The number of milliseconds of each tick
    tickTime=2000
    # The number of ticks that the initial
    # synchronization phase can take
    initLimit=10
    # The number of ticks that can pass between
    # sending a request and getting an acknowledgement
    syncLimit=5
    # the directory where the snapshot is stored.
    # do not use /tmp for storage, /tmp here is just
    # example sakes.
    dataDir=/root/zookeeper/data/zk1
    dataLogDir=/root/zookeeper/log/zk1
    # the port at which the clients will connect
    clientPort=12181
    
    server.1=localhost:12000:13000
    server.2=localhost:12001:13001
    server.3=localhost:12002:13002
    

    对于zk2.cfgzk3.cfg分别修改dataDirdataLogDirclientPort

  5. 分别在/data/zk1/data/zk2/data/zk3,创建节点标识文件myid,并分别写入1、2、3.

    |----data		#存放zookeeper的数据
        |----zk1
        	|----myid  # 写入1
        |----zk2
        	|----myid  # 写入2
        |----zk3
        	|----myid  # 写入3
    
  6. 启动集群

    sh apache-zookeeper-3.5.7-bin/bin/zkServer.sh start config/zk1.cfg
    sh apache-zookeeper-3.5.7-bin/bin/zkServer.sh start config/zk2.cfg
    sh apache-zookeeper-3.5.7-bin/bin/zkServer.sh start config/zk3.cfg
    
  7. 查看节点状态

    sh apache-zookeeper-3.5.7-bin/bin/zkServer.sh status config/zk1.cfg
        ZooKeeper JMX enabled by default
        Using config: config/zk1.cfg
        Client port found: 12181. Client address: localhost.
        Mode: follower
    sh apache-zookeeper-3.5.7-bin/bin/zkServer.sh status config/zk2.cfg
        ZooKeeper JMX enabled by default
        Using config: config/zk1.cfg
        Client port found: 12182. Client address: localhost.
        Mode: leader
    sh apache-zookeeper-3.5.7-bin/bin/zkServer.sh status config/zk3.cfg
        ZooKeeper JMX enabled by default
        Using config: config/zk1.cfg
        Client port found: 12183. Client address: localhost.
        Mode: follower
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值