Zookeeper专题

作为一个分布式架构中的协调组件,zookeeper起着举足轻重的作用。并且在多个分布式架构中,总是能够看到zookeeper的身影,例如dubbo+zookeeper通过rpc远程调用实现微服务架构,再比如kafka通过zookeeper作为元数据管理和协调。
那么下面我们就一起来探索一下如何搭建一个高可用的zookeeper集群以及zookeeper实现高可用的原理又是什么?

什么是zookeeper

Zookeeper是一个典型的分布式数据一致性解决方案,分布式应用程序可以基于Zookeeper实现诸 如数据发布/订阅,负载均衡,命名服务,分布式协调/通知,集群管理,Master选举,分布式锁和分布 式队列等功能。

在使用Zookeeper的时候,最好使用集群版Zookeeper,而且最好使用集群版服务器构成 Zookeeper集群。Zookeeper容错中,始终基于半数原则,即只有当集群中可用节点的数量大于集群总数量的一半时,才表示该集群状态为可用状态。

例如有5个zk节点的集群:

  1. 当宕调2个Zookeeper节点后,存活节点数仍然大于集群总数的一半(2.5),因此这个集群可用,整个Zookeeper才能依然使用。
  2. 当宕调3个Zookeeper节点后,存活节点数小于集群总数的一半(2.5),因此表示整个集群为不可用状态。

因此在使用zookeeper集群时,通常都选择部署奇数个节点,因为5个节点也只允许宕机两个节点,6个节点时,仍然只允许宕机两个节点。部署偶数个,会浪费钱

Zookeeper 的概念

  1. 基本概念:
  1. Zookeeper本身就是一个分布式程序,只要半数以上节点存活,Zookeeper就能正常提供服 务(过半原则)。
  2. Zookeeper将数据保存在内存中,保证了高吞吐和低延迟,但是内存限制了能够存储的容 量,这也限制了Znode中存储的数据量较小的原因。
  3. Zookeeper是高性能的,在读多于写的应用程序中才能发挥最高性能,因为写会导致所有服 务器进入同步状态。(因此说Zookeeper是基于CAP中的CP理论实现的分布式架构)
  4. Zookeeper有临时节点的概念,当创建临时节点的客户端会话一直保持活动,临时节点就一 直存在,而当会话终结时,临时节点被删除。持久节点是指一旦这个ZNode被创建,除非主动进行 ZNode的移除操作,否则这个ZNode将一直保存在Zookeeper上。
  5. Zookeeper底层其实提供了两个功能:
    • 管理用户程序提交的数据;
    • 为用户程序提供节点监听服务。
  1. Session会话
    Session会话就是指Zookeeper服务器与客户端的一次会话连接。
  1. TCP连接:在Zookeeper中,一个客户端连接是指客户端和 服务器之间的一个TCP长连接。在客户端启动的时候,首先会与服务器建立一个TCP连接,从第一次连接 建立开始,客户端会话的生命周期就开始了。通过这个连接,客户端能够通过心跳检测与服务器保持有 效的会话,也能够向Zookeeper服务器发送请求并接受响应,同时还能够通过该连接接收来自服务器的 Watch事件通知。
  2. session ID: 在为客户端创建会话之前,服务端首先会为每个客户端都分配一个Session ID,由于Session ID是 Zookeeper会话的一个重要标识,许多与会话相关的运行机制都是基于Session ID的,因此,无论是哪 台服务器为客户端分配的Session ID,都需要保证全局唯一。
  3. session timeout:客户端会话的超时事件。由于服务压力大,网络故障或者客户 端主动断开连接等各种原因导致客户端连接断开时,只要在Session Timeout规定的时间内能够重新连 接上集群中任意一台服务器,那么之前创建的会话仍然有效。
  1. ZNode节点:
  1. Zookeeper将所有数据存储在内存中,数据模型是一棵树,由"/"进行分割的路径,就是一个ZNode,每个节点上都会保存自己的数据内容,同时还会保存一系列属性信息。类似于文件系统的目录,和文件系统中目录不同的是,ZNode的每一个节点都可以存储数据,不管其下有没有子节点。
  2. Zookeeper中ZNode分为两类,分为持久节点和临时节点。同时Zookeepe还允许为每个节点添加 一个属性:SEQUENTIAL。一旦节点被标记上这个属性,那么这个节点被创建的时候,Zookeeper会自 动在其节点名后追加上一个整型数字,这个整型数字是由父节点维护的自增数字。
  1. Watcher事件监听

Zookeeper允许用于在指定节点上注册 一些Watcher,并且在一些特定事件触发的时候,Zookeeper服务端会将事件通知到感兴趣的客户端上 去,该机制是Zookeeper实现分布式协调服务的重要特性。
注意:Watcher事件监听一次,就只能被触发一次。触发之后,该事件监听器将被zookeeper移除,如果需要再次监听,则需要再次进行监听器(Watcher)的注册。

  1. ACL策略:

Zookeeper采用ACL策略来进行权限控制,分为:

  1. CREATE:创建子节点的权限。
  2. READ:获取节点数据和子节点列表的权限。
  3. WRITE:更新节点数据的权限。
  4. DELETE:删除子节点的权限。
  5. ADMIN:设置节点的ACL权限。

其中CREATE和DELETE这两种权限都是针对子节点的控制权限

Zookeeper 集群角色

  1. Leader 角色:Leader 服务器是整个 zookeeper 集群的核心,主要的工作任务有两项:
    1. 事务请求的唯一调度和处理者,保证集群事务处理的顺序性
    2. 集群内部各服务器的调度者
  2. Follower 角色:

Follower 角色的主要职责是

  1. 处理客户端非事务请求、转发事务请求给 leader 服务器
  2. 参与事物请求 Proposal 的投票(需要半数以上服务器通过才能通知 leader commit 数据; Leader 发起的提案,要求 Follower 投票)
  3. 参与 Leader 选举的投票
  1. Observer 角色:Observer 是 zookeeper3.3 开始引入的一个全新的服务器角色,从字面来理解, 该角色充当了观察者的角色。
  1. 任务:观察 zookeeper 集群中的最新状态变化并将这些状态变化同步到 observer 服务器上。
  2. 工作原理:Observer 的工作原理与follower 角色基本一致,也能够作为从节点提供非事务操作。
  3. Observer和 follower 角色唯一的不同 在于 observer 不参与任何形式的投票,包括事务请求Proposal的投票和leader选举的投票。简单来 说,observer服务器只提供非事务请求服务,通常在于不影响集群事务处理能力的前提下提升集群非事 务处理的能力
  1. 事务操作和非事务操作:简单来说就可以理解为写操作(事务操作)和读操作(非事务操作)。
  1. 事务操作:能改变 ZooKeeper服务器状态的操作称为事务操作,写操作。
  2. 非事务操作:不会改变 ZooKeeper服务器状态的操作称为事务操作,读操作。

搭建zookeeper伪分布式

结合上一节中介绍的集群中的各个重要角色,我将在这里搭建一个单机伪分布式的zookeeper集群。(真正的分布式集群原理也是一样的,不想起多个虚拟机来搞。电脑带不动)。

  1. 首先我们来看一下一个zookeeper的架构图
    Zookeeper专题_第1张图片

图示解析:

  1. 首先我们一共准备了4个节点,一个leader,两个follower还有一个observer节点。
  2. 客户端连接请求时,可以选择任意一个zookeeper集群中的可用节点进行连接。
  3. 当客户端连接了一个follower节点或者observer节点,并发出一个事务操作请求时,follower节点会将请求转发给leader节点进行执行。
  4. 集群中的leader节点在发生事务操作时,会阻塞。处理完成后,会将事务变更同步给follower节点和observer节点。
  5. leader节点宕机时,follower节点之间会重新选举出新的leader。
  1. 搭建准备
  1. 准备java环境,并下载zookeeper,解压。(可直接在官网下载,学习建议最新版本)
  1. 环境规划
节点 类型 myid 客户端端口 数据交换端口 节点选举端口
Node1 leader/follower 1 2181 4001 5001
Node2 leader/follower 2 2182 4002 5002
Node3 leader/follower 3 2183 4003 5003
Node4 observer 4 2184 4004 5004
  1. 解压缩zookeeper:
# 解压缩zookeeper
tar -zxvf apache-zookeeper-3.5.6-bin.tar.gz
# 该名字(或者建一个超链接):非必须
mv apache-zookeeper-3.5.6-bin zookeeper-3.5.6
  1. 配置zoo.cfg配置文件。

注意:由于采用的是伪分布式,因此每个实例的端口号不能重复。而且在zookeeper中一共涉及到多个端口号。

  1. clientPort=2181 # 客户端连接端口号
  2. server.1=localhost:4001:5001
    • ”1” 为该节点的编号,表示第几个节点。一般与设置的myid文件保持一致。
    • “localhost": 表示的是ip,如果是非本地部署,此处应该是节点实际的ip
    • “4001” : 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口
    • ”5001“:当leader宕机之后,各个节点之间进行投票选举的通信端口。

配置各个节点的zoo.cfg

tickTime=2000 #作为 Zookeeper #服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime #时间就会发送一个心跳。
initLimit=10 #集群中的follower服务器(F)与leader服务器(L)之间初始连接时能容忍的最多心跳数 (tickTime的数量)
syncLimit=5 #集群中的follower服务器与leader服务器之间请求和应答(数据同步)之间能容忍的最多 心跳数(tick#Time的数量)。
dataDir=/usr/local/zookeeper-3.4.6/data #数据持久化目录 
dataLogDir=/usr/local/zookeeper-3.4.6/logs #日志目录 
clientPort=2181 #客户端连接 Zookeeper 服务器的端口 用默认就行 
server.1=localhost:4001:5001
server.2=localhost:4002:5002
server.3=localhost:4003:5003
server.4=localhost:4004:5004:observer

### 注意,各个配置的内容基本一样,唯一需要修改的就是dataDir数据文件路径,dataLogDir日志路径以及clientPort客户端端口

  1. 依次启动zookeeper,并查看集群状态
  1. 启动:./zkServer.sh --config #{zoo.cfg配置文件路径} start
  2. 查看集群状态:./zkServer.sh --config #{zoo.cfg配置文件路径} status
    ** 注意:** 在成功建立集群之前,zk会一直发放心跳事件,此时集群状态为不可用状态。

什么是zab协议

ZAB(Zookeeper Atomic Broadcast) 协议是为分布式协调服务 ZooKeeper 专门设计的一种支持 崩溃恢复的原子广播协议。在 ZooKeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性,基于该协 议,ZooKeeper 实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性。ZAB 协议 包含两种基本模式,分别是: 原子广播崩溃恢复

  1. 原子广播 :消息广播的过程实际上是一个简化版本的二阶段提交过程:
    Zookeeper专题_第2张图片
  1. zookeeper集群接收到一个事务请求(如果不是事务请求,则不会发出原子广播协议,直接有follower处理),如果请求发给follower,follower会转发给leader节点。有leader节点进行事务处理。
  2. leader 接收到消息请求后,将消息赋予一个全局唯一的自增 id,叫:zxid,通过 zxid 的大小比较 即可以实现全局有序这个特征。
  3. leader 为每个 follower 准备了一个 FIFO 队列(通过 TCP协议来实现,以实现了全局有序这一个 特点)将带有 zxid的消息作为一个提案(proposal)分发给所有的 follower。
  4. 当 follower 接收到 proposal,先把 proposal 写到磁盘,写入成功以后再向 leader 回复一个 ack。
  5. 当 leader 接收到合法数量(超过半数节点)的 ACK 后,leader 就会向这些 follower 发送commit 命令,同时会在本地执行该消息
  6. 当 follower 收到消息的 commit 命令以后,会提交该消息。

注意:如果超过syncTimes(主从通信心跳次数),leader接收少于半数follower节点ack,那么执行
rollback命令,follower节点也会撤销本地保存的提案!

leader 的投票过程,不需要 Observer 的 ack,也就是Observer 不需要参与投票过程,但是
Observer 必须要同步 Leader 的数据从而在处理请求的时候保证数据的一致性

  1. 崩溃恢复: 针对是leader节点宕机的情况下,集群要怎么应对这些异常情况。如果follower宕机,只要在宕机不超多集群半数的情况下,对整个集群的可用性没有任何影响,重启后再次作为follower节点加入集群中即可。

在考虑leader几点宕机的异常情况时,就会涉及到集群的几种状态,也可以称为模式:

  1. 高可用状态:即集群中的各个节点都正常工作。
  2. 集群恢复模式(即新leader的选举过程):当 leader 节点出现网络中断、崩溃等情况时,ZAB 协议就 会进入集群恢复模式并选举产生新的 Leader,当 leader 服务器选举出来后,并且集群中有过半的机器和该 leader 节点完成数据同步后(同步指的是数据同步,用来保证集群中过半的机器能够和 leader 服务器 的数据状态保持一致),ZAB 协议就会退出集群恢复模式。
  3. 消息广播模式:当集群中已经有过半的 Follower 节点完成了和 Leader 状态同步以后,那么整个集群就进入了消息广播模式。
    4.数据恢复模式(个人认为数据同步模式更为合理): 在 Leader 节点正常工作时, 启动一台新的服务器加入到集群,那这个服务器会直接进入数据恢复模式,和 leader 节点进行数据同 步。同步完成后即可正常对外提供非事务请求的处理。

2.1 已经处理的消息不能丢失:主要针对的是,在超过半数的follower节点响应ACK后,Leader节点在提交commit请求时,leader宕机。导致leader节点和部分follower节点没有收到commit请求。这时,要保证这个已经处理过的消息,在leader节点恢复后不能丢失。
Zookeeper专题_第3张图片
2.2 被丢弃的消息不能再次出现: 当 leader 接收到消息请求生成 proposal 后就挂了,其他 follower 并没有收到此 proposal,因此经过恢复模式重新选了 leader 后,这条消息是被跳过的。 此时,之前挂 了的 leader 重新启动并注册成了follower,他保留了被跳过消息的 proposal 状态,与整个系统的状态 是不一致的,需要将其删除。
Zookeeper专题_第4张图片

你可能感兴趣的:(中间件,分布式)