文章目录
- 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架构是什么样子的?
- 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 事件监听机制
可以通过-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
可简述为:
- 每个候选人为自己投票
- 如果票数相同,则观察编号大小,大的占优势
- 成为Leader的一个条件是投票数过半,否则已投票人仍为Looking状态
Zookeeper实现配置中心原理
配置中心主要用来解决每次修改配置文件都需要重启,不能动态修改配置,且在分布式情况下,不易管理。
Zookeeper可以实现配置中心,前面我们知道可以通过create /node_name
来创建结点,并且该结点是可以保存数据的
可以把配置文件保存到某结点,之后让多个服务通过客户端-w
去监听该节点的变化,若出现变化,则在监听到事件后,便去重新加载该配置文件。
Zookeeper 实现注册中心原理
- 生产者 通过创建临时结点去注册服务,该临时节点主要保存的是IP、PORT、API等信息
- 消费者 根据生产者注册的服务名称去Zookeeper拿到已注册的服务数据,拉到本地并解析,并在之后通过-w 去监听,例如有新的机器加进来提供相同的服务,那么就会触发事务监听机制,从而消费者可以更新本地的服务信息。
Zookeeper实现分布式锁?
Zookeeper提供实现独占锁和共享锁两种,对于独占锁,同一时刻,只能有一个客户端操作资源,对于共享锁,则是读共享,读写互斥。
zk是基于前面提到的四个结点来实现分布式锁的,因为zk结点是有唯一的特性的。
创建结点实现加锁,删除结点实现释放锁,在释放锁之后通知其他客户端来加锁走业务。
- 考虑到机器可能宕机,导致结点无法删除,锁也就无法删除了,故采用临时节点比较好。
- 但通知/监听机制可能会导致“羊群效应”,如下所示,用顺序节点可以解决这个问题。
当变化发生时,ZooKeeper会触发一个特定的znode节点的变化导致的所有监视点的集合。
如果有1000个客户端通过exists操作监视这个znode节点,那么当znode节点创建后就会发送1000个通知,因而被监视的znode节点的一个变化会产生一个尖峰的通知,该尖峰可能带来影响,例如,在尖峰时刻提交的操作延迟。可能的话,我们建议在使用ZooKeeper时,避免在一个特定节点设置大量的监视点,最好是每次在特定的znode节点上,只有少量的客户端设置监视点,理想情况下最多只设置一个。
- 综上,最好是选用临时顺序结点来实现分布式锁。
Zookeeper实现分布式锁可能出现的问题?
如果由于网络抖动,客户端A成功获取了锁,进行业务操作,而之后zk与客户端A的连接断了,删除掉临时结点,此时客户端B就可以进行加锁,产生并发问题。
ZAB协议
ZAB 协议是 Zookeeper 专门设计的一种支持崩溃恢复的原子广播协议。通过该协议,Zookeeper 基于主从模式的系统架构来保持集群中各个副本之间数据的一致性。具体如下:
Zookeeper 使用一个单一的主进程来接收并处理客户端的所有事务请求,并采用原子广播协议将数据状态的变更以事务 Proposal 的形式广播到所有的副本进程上去。如下图:
具体流程如下:
所有的事务请求必须由唯一的 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 消息后,完成事务的提交。
说实话,这里感觉跟Raft协议很TM像!可以学学 分布式共识算法 Raft
ZK ACL 权限控制
为了避免存储在 Zookeeper 上的数据被其他程序或者人为误修改,Zookeeper 提供了 ACL(Access Control Lists) 进行权限控制。只有拥有对应权限的用户才可以对节点进行增删改查等操作。
Zookeeper 的权限由[scheme : id :permissions]
三部分组成,其中 Schemes
和 Permissions
内置的可选项分别如下:
Permissions 可选项:
- CREATE:允许创建子节点;
- READ:允许从节点获取数据并列出其子节点;
- WRITE:允许为节点设置数据;
- DELETE:允许删除子节点;
- ADMIN:允许为节点设置权限。
Schemes 可选项:
- world:默认模式,所有客户端都拥有指定的权限。world 下只有一个 id 选项,就是 anyone,通常组合写法为
world:anyone:[permissons]
; - auth:只有经过认证的用户才拥有指定的权限。通常组合写法为
auth:user:password:[permissons]
,使用这种模式时,你需要先进行登录,之后采用 auth 模式设置权限时,user
和password
都将使用登录的用户名和密码; - digest:只有经过认证的用户才拥有指定的权限。通常组合写法为
auth:user:BASE64(SHA1(password)):[permissons]
,这种形式下的密码必须通过 SHA1 和 BASE64 进行双重加密; - ip:限制只有特定 IP 的客户端才拥有指定的权限。通常组成写法为
ip:182.168.0.168:[permissions]
; - super:代表超级管理员,拥有所有的权限,需要修改 Zookeeper 启动脚本进行配置。
经过上述介绍,也可知id可能是anyone、user:password几种