文章目录

  • Zookeeper是什么?
  • Zookeeper架构是什么样子的?
  • Zookeeper 下 Server 工作状态
  • Zookeeper应用场景?
  • Zookeeper部署模式?
  • Zookeeper的数据节点Znode?
  • Zookeeper命令实战
  • get:可用于获取节点的值
  • set:可用于给节点赋值
  • create :可用于创建节点
  • delete :可用于删除节点
  • 创建其他类型的节点
  • Zookeeper 事件监听机制
  • Zookeeper选举过程?
  • Zookeeper实现配置中心原理
  • Zookeeper 实现注册中心原理
  • Zookeeper实现分布式锁?
  • Zookeeper实现分布式锁可能出现的问题?
  • ZAB协议
  • 1. 崩溃恢复
  • 2. 消息广播
  • ZK ACL 权限控制


Zookeeper是什么?

Zookeeper是为分布式应用提供一致性服务的软件,什么意思呢,它并不用来存储海量数据,更多的是给整个数据库集群提供一致性服务,保存的也是机器相关的数据。

Zookeeper架构是什么样子的?

zookeeper sessionTimeout设置 zookeeper refusing session_客户端

  • Leader 领导
  • Follower 跟随者
  • Client 客户端

一般来说,同一时刻有一个Leader,多个Follower。

Zookeeper 下 Server 工作状态

服务器具有四种状态,分别是 LOOKING、FOLLOWING、LEADING、OBSERVING。

(1)LOOKING:寻 找 Leader 状态,也叫投票状态。当服务器处于该状态时,它会认为当前集群中没有 Leader,因此需要进入 Leader 选举状态。

(2)FOLLOWING:跟随者状态。表明当前服务器角色是 Follower。

(3)LEADING:领导者状态。表明当前服务器角色是 Leader。

(4)OBSERVING:观察者状态。表明当前服务器角色是 Observer。

Zookeeper应用场景?

  • 服务注册与订阅(共用节点):
  • 分布式通知(监听znode):
  • 服务命名(znode特性):
  • 数据订阅、发布(watcher):
  • 分布式锁(临时节点):

Zookeeper部署模式?

  • 单机部署
  • 集群部署
  • 伪集群部署

Zookeeper的数据节点Znode?

  • 持久结点:若非主动删除,否则结点一直存在于Zookeeper上。
  • 临时结点:生命周期与客户端会话绑定,随着会话失效,结点自动删除,但这个删除是有时延的。
  • 顺序持久结点:在持久结点的基础上,增加顺序特性,通过父节点维护的自增整形数字来实现
  • 顺序临时结点:在临时结点的基础上,增加顺序特性,通过父节点维护的自增整形数字来实现

在Zookeeper3.5之后,增加了容器节点TTL节点

下面是apache对创建节点模式的定义,可以看到除了我们常用的四种节点之外,还有三种与容器节点和TTL节点有关

package org.apache.zookeeper;
public enum CreateMode {
    PERSISTENT(0, false, false, false, false),
    PERSISTENT_SEQUENTIAL(2, false, true, false, false),
    EPHEMERAL(1, true, false, false, false),
    EPHEMERAL_SEQUENTIAL(3, true, true, false, false),
    CONTAINER(4, false, false, true, false),
    PERSISTENT_WITH_TTL(5, false, false, false, true),
    PERSISTENT_SEQUENTIAL_WITH_TTL(6, false, true, false, true);

Zookeeper命令实战

Zookeeper很像文件系统,但是文件系统的目录是无法保存数据的,Zookeeper的每个节点都可以保存数据。

下面以持久化节点操作为例,

get:可用于获取节点的值
[zk: localhost:2181(CONNECTED) 4] get /node
null

带参数get -s

[zk: localhost:2181(CONNECTED) 8] get -s /node
wyh
cZxid = 0x2 // 事务ID
ctime = Wed Aug 18 09:57:48 CST 2021
mZxid = 0x3
mtime = Wed Aug 18 09:58:06 CST 2021
pZxid = 0x2 // 子节点ID
cversion = 0
dataVersion = 1 
aclVersion = 0 
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0
set:可用于给节点赋值
[zk: localhost:2181(CONNECTED) 5] set /node wyh
[zk: localhost:2181(CONNECTED) 6] get /node
wyh
create :可用于创建节点

创建根节点

[zk: localhost:2181(CONNECTED) 3] create /node
Created /node

创建子节点

[zk: localhost:2181(CONNECTED) 9] create /node/subnode
Created /node/subnode
delete :可用于删除节点

delete如果有子节点,不可以直接删除,需挨个删除

创建其他类型的节点

临时节点 create -e

create -e /expireNode

顺序节点, create -s

zookeeper sessionTimeout设置 zookeeper refusing session_数据_02


可以看到,它为每个节点的名字加上了顺序号,保证节点是顺序的

Zookeeper 事件监听机制

可以通过-w 指定对数据进行监听,当节点发生变化时,会监听到该事件

[zk: localhost:2181(CONNECTED) 18] get -w /node/subnode # 设置监听
null
[zk: localhost:2181(CONNECTED) 19] set /node/subnode hello # 改变数据

WATCHER::# 监听到
[zk: l
WatchedEvent state:SyncConnected type:NodeDataChanged path:/node/subnode
ocalhost:2181(CONNECTED) 20]

同时,也可以对某个目录进行监听,通过ls -w 实现,这样该目录下产生结点变化,便可以监听到。

Zookeeper选举过程?

zookeeper提供了三种选举Leader的方式:

  • LeaderElection
  • AuthFastLeaderElection
  • FastLeaderElection (最新默认)

LeaderElection:这是一种基于洪泛的选举算法,其中每个节点向其他节点发送消息,直到一个节点被大多数节点选中为领导者。这种算法简单易实现,但是选举过程可能会导致网络拥塞,尤其是在大规模分布式系统中。

AuthFastLeaderElection:这是一种改进版的 LeaderElection 算法,其中每个节点在选举过程中携带一个身份验证标识,以减少恶意节点对选举结果的干扰。这种算法的选举速度较快,但是需要额外的存储空间来存储每个节点的身份验证标识。

FastLeaderElection:这是一种基于环的选举算法,其中每个节点维护一个环形结构,并通过在环上发送消息来选举领导者。这种算法的选举速度非常快,并且可以容忍节点的故障和网络的延迟。

默认的选举算法是FastLeaderElection

可简述为:

  1. 每个候选人为自己投票
  2. 如果票数相同,则观察编号大小,大的占优势
  3. 成为Leader的一个条件是投票数过半,否则已投票人仍为Looking状态

Zookeeper实现配置中心原理

配置中心主要用来解决每次修改配置文件都需要重启,不能动态修改配置,且在分布式情况下,不易管理。

Zookeeper可以实现配置中心,前面我们知道可以通过create /node_name 来创建结点,并且该结点是可以保存数据的

可以把配置文件保存到某结点,之后让多个服务通过客户端-w 去监听该节点的变化,若出现变化,则在监听到事件后,便去重新加载该配置文件。

Zookeeper 实现注册中心原理

  • 生产者 通过创建临时结点去注册服务,该临时节点主要保存的是IP、PORT、API等信息
  • 消费者 根据生产者注册的服务名称去Zookeeper拿到已注册的服务数据,拉到本地并解析,并在之后通过-w 去监听,例如有新的机器加进来提供相同的服务,那么就会触发事务监听机制,从而消费者可以更新本地的服务信息。

Zookeeper实现分布式锁?

Zookeeper提供实现独占锁和共享锁两种,对于独占锁,同一时刻,只能有一个客户端操作资源,对于共享锁,则是读共享,读写互斥。

zk是基于前面提到的四个结点来实现分布式锁的,因为zk结点是有唯一的特性的。

创建结点实现加锁,删除结点实现释放锁,在释放锁之后通知其他客户端来加锁走业务。

  1. 考虑到机器可能宕机,导致结点无法删除,锁也就无法删除了,故采用临时节点比较好。
  2. 但通知/监听机制可能会导致“羊群效应”,如下所示,用顺序节点可以解决这个问题。

当变化发生时,ZooKeeper会触发一个特定的znode节点的变化导致的所有监视点的集合。
如果有1000个客户端通过exists操作监视这个znode节点,那么当znode节点创建后就会发送1000个通知,因而被监视的znode节点的一个变化会产生一个尖峰的通知,该尖峰可能带来影响,例如,在尖峰时刻提交的操作延迟。可能的话,我们建议在使用ZooKeeper时,避免在一个特定节点设置大量的监视点,最好是每次在特定的znode节点上,只有少量的客户端设置监视点,理想情况下最多只设置一个。

  1. 综上,最好是选用临时顺序结点来实现分布式锁。

Zookeeper实现分布式锁可能出现的问题?

如果由于网络抖动,客户端A成功获取了锁,进行业务操作,而之后zk与客户端A的连接断了,删除掉临时结点,此时客户端B就可以进行加锁,产生并发问题。

ZAB协议

ZAB 协议是 Zookeeper 专门设计的一种支持崩溃恢复的原子广播协议。通过该协议,Zookeeper 基于主从模式的系统架构来保持集群中各个副本之间数据的一致性。具体如下:

Zookeeper 使用一个单一的主进程来接收并处理客户端的所有事务请求,并采用原子广播协议将数据状态的变更以事务 Proposal 的形式广播到所有的副本进程上去。如下图:

zookeeper sessionTimeout设置 zookeeper refusing session_客户端_03


具体流程如下:

所有的事务请求必须由唯一的 Leader 服务来处理,Leader 服务将事务请求转换为事务 Proposal,并将该 Proposal 分发给集群中所有的 Follower 服务。如果有半数的 Follower 服务进行了正确的反馈,那么 Leader 就会再次向所有的 Follower 发出 Commit 消息,要求将前一个 Proposal 进行提交。

ZAB 协议包括两种基本的模式,分别是崩溃恢复和消息广播:

1. 崩溃恢复

当整个服务框架在启动过程中,或者当 Leader 服务器出现异常时,ZAB 协议就会进入恢复模式,通过过半选举机制产生新的 Leader,之后其他机器将从新的 Leader 上同步状态,当有过半机器完成状态同步后,就退出恢复模式,进入消息广播模式。

2. 消息广播

ZAB 协议的消息广播过程使用的是原子广播协议。在整个消息的广播过程中,Leader 服务器会每个事物请求生成对应的 Proposal,并为其分配一个全局唯一的递增的事务 ID(ZXID),之后再对其进行广播。具体过程如下:

  • Leader 服务会为每一个 Follower 服务器分配一个单独的队列,然后将事务 Proposal 依次放入队列中,并根据 FIFO(先进先出) 的策略进行消息发送。
  • Follower 服务在接收到 Proposal 后,会将其以事务日志的形式写入本地磁盘中,并在写入成功后反馈给 Leader 一个 Ack 响应。
  • 当 Leader 接收到超过半数 Follower 的 Ack 响应后,就会广播一个 Commit 消息给所有的 Follower 以通知其进行事务提交,之后 Leader 自身也会完成对事务的提交。
  • 而每一个 Follower 则在接收到 Commit 消息后,完成事务的提交。
  • zookeeper sessionTimeout设置 zookeeper refusing session_结点_04

说实话,这里感觉跟Raft协议很TM像!可以学学 分布式共识算法 Raft

ZK ACL 权限控制

为了避免存储在 Zookeeper 上的数据被其他程序或者人为误修改,Zookeeper 提供了 ACL(Access Control Lists) 进行权限控制。只有拥有对应权限的用户才可以对节点进行增删改查等操作。

Zookeeper 的权限由[scheme : id :permissions]三部分组成,其中 SchemesPermissions 内置的可选项分别如下:

Permissions 可选项

  • CREATE:允许创建子节点;
  • READ:允许从节点获取数据并列出其子节点;
  • WRITE:允许为节点设置数据;
  • DELETE:允许删除子节点;
  • ADMIN:允许为节点设置权限。

Schemes 可选项

  • world:默认模式,所有客户端都拥有指定的权限。world 下只有一个 id 选项,就是 anyone,通常组合写法为 world:anyone:[permissons]
  • auth:只有经过认证的用户才拥有指定的权限。通常组合写法为 auth:user:password:[permissons],使用这种模式时,你需要先进行登录,之后采用 auth 模式设置权限时,userpassword 都将使用登录的用户名和密码;
  • digest:只有经过认证的用户才拥有指定的权限。通常组合写法为 auth:user:BASE64(SHA1(password)):[permissons],这种形式下的密码必须通过 SHA1 和 BASE64 进行双重加密;
  • ip:限制只有特定 IP 的客户端才拥有指定的权限。通常组成写法为 ip:182.168.0.168:[permissions]
  • super:代表超级管理员,拥有所有的权限,需要修改 Zookeeper 启动脚本进行配置。

经过上述介绍,也可知id可能是anyone、user:password几种