zk是一个开源的分布式协调服务,它是集群的管理者,监视着集群中各个节点的状态根据节点提交反馈进行下一步操作,最终将简单易用的接口和性能高效1、文档的系统提供给用户
分布式应用程序可以基于zk实现数据发布/订阅,负载均衡、Master选举、分布式锁、分布式队列等功能
特性
-
顺序一致性(有序性)
从同一个客户端发起的事务请求,最终将会严格地按照其发起顺序被应用到 Zookeeper 中去。
有序性是 Zookeeper 中非常重要的一个特性。
所有的更新都是全局有序的,每个更新都有一个唯一的时间戳,这个时间戳称为zxid(Zookeeper Transaction Id)。
而读请求只会相对于更新有序,也就是读请求的返回结果中会带有这个 Zookeeper 最新的 zxid 。
-
原子性
所有事务请求的处理结果在整个集群中所有机器上的应用情况是一致的,即整个集群要么都成功应用了某个事务,要么都没有应用。
-
单一视图
无论客户端连接的是哪个 Zookeeper 服务器,其看到的服务端数据模型都是一致的。
-
可靠性
一旦服务端成功地应用了一个事务,并完成对客户端的响应,那么该事务所引起的服务端状态变更将会一直被保留,除非有另一个事务对其进行了变更。
-
实时性
Zookeeper 保证在一定的时间段内,客户端最终一定能够从服务端上读取到最新的数据状态。
-
PERSISTENT 持久节点
创建之后一直存在,除非有删除操作,创建节点的客户端会话失效也不影响此节点。
-
PERSISTENT_SEQUENTIAL 持久顺序节点
跟持久一样,就是父节点在创建下一级子节点的时候,记录每个子节点创建的先后顺序,会给每个子节点名加上一个数字后缀。
-
EPHEMERAL 临时节点
创建客户端会话失效(注意是会话失效,不是连接断了),节点也就没了。不能建子节点。
-
EPHEMERAL_SEQUENTIAL 临时顺序节点
基本特性同临时节点,增加了顺序属性,节点名后边会追加一个由父节点维护的自增整型数字。
Zookeeper 允许客户端向服务端的某个 znode 注册一个 Watcher 监听,当服务端的一些指定事件触发了这个 Watcher ,服务端会向指定客户端发送一个事件通知来实现分布式的通知功能,然后客户端根据 Watcher 通知状态和事件类型做出业务上的改变。
整个流程如下:
- 第一步,客户端注册 Watcher 。
- 第二步,服务端处理 Watcher 。
- 第三步,客户端回调 Watcher 。
目前,在 Linux/Unix 文件系统中,使用 UGO(User/Group/Others) 权限模型,也是使用最广泛的权限控制方式。是一种粗粒度的文件系统权限控制模式。
一般我们管理后台,采用的 RBAC 居多,和 UGO 比较类似,差别在于一般将权限分配给 Role ,而不是直接给 User 。
对于 Zookeeper ,它采用 ACL(Access Control List)访问控制列表。包括三个方面:
-
权限模式(Scheme)
- IP :从 IP 地址粒度进行权限控制
- 【常用】Digest :最常用,用类似于
username:password
的权限标识来进行权限配置,便于区分不同应用来进行权限控制。 - World :最开放的权限控制方式,是一种特殊的 digest 模式,只有一个权限标识
“world:anyone”
。 - Super :超级用户。
-
授权对象
授权对象指的是权限赋予的用户或一个指定实体,例如 IP 地址或是机器等。
-
权限 Permission
- CREATE :数据节点创建权限,允许授权对象在该 znode 下创建子节点。
- DELETE :子节点删除权限,允许授权对象删除该数据节点的子节点。
- READ :数据节点的读取权限,允许授权对象访问该数据节点并读取其数据内容或子节点列表等。
- WRITE :数据节点更新权限,允许授权对象对该数据节点进行更新操作。
- ADMIN :数据节点管理权限,允许授权对象对该数据节点进行 ACL 相关设置操作。
-
1、Leader
- 事务请求的唯一调度和处理者,保证集群事务处理的顺序性。
- 集群内部各服务的调度者。
-
2、Follower
- 处理客户端的非事务请求,转发事务请求给 Leader 服务器。
- 参与事务请求 Proposal 的投票。 参与 Leader 选举投票。
-
3、Observer
3.3.0 版本以后引入的一个服务器角色,在不影响集群事务处理能力的基础上提升集群的非事务处理能力。
- 处理客户端的非事务请求,转发事务请求给 Leader 服务器
- 不参与任何形式的投票。
如果 ZooKeeper 集群的读取负载很高,或者客户端多到跨机房,可以设置一些 Observer 服务器,以提高读取的吞吐量。Observer 和 Follower 比较相似,只有一些小区别:
- 首先 Observer 不属于法定人数,即不参加选举也不响应提议,也不参与写操作的“过半写成功”策略;
- 其次是 Observer 不需要将事务持久化到磁盘,一旦 Observer 被重启,需要从 Leader 重新同步整个名字空间。
记住一个原则:过半存活即可用。所以挂掉 1 台可以继续工作,挂掉 2 台不可以工作。
在 3.5 版本开始,支持动态扩容。
而在 3.5 版本之前,Zookeeper 在这方面不太好。所以需要如下两种方式:
- 全部重启:关闭所有 Zookeeper 服务,修改配置之后启动。不影响之前客户端的会话。
- 逐个重启:顾名思义。这是比较常用的方式。
结合ZK介绍来讲
ZooKeeper 的核心是原子广播,这个机制保证了各个 Server 之间的同步。实现这个机制的协议叫做 Zab 协议。Zab 协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步):
-
选主:当服务启动或者 Leader 崩溃后,Zab 就进入了恢复模式,当新的 Leader 被选举出来,且大多数 Server 完成了和 Leader 的状态同步以后,恢复模式就结束了。
当整个 Zookeeper 集群刚刚启动,或者 Leader 服务器宕机、重启或者网络故障导致不存在过半的服务器与 Leader服务器保持正常通信时,所有进程(服务器)进入崩溃恢复模式。
- 首先,选举产生新的Leader服务器。
-
然后,集群中 Follower 服务器开始与新的 Leader 服务器进行数据同步。
- 当集群中超过半数机器与该Leader服务器完成数据同步之后,退出恢复模式进入消息广播模式,
-
同步:状态同步保证了 Leader 和 Server 具有相同的系统状态。 Leader 服务器开始接收客户端的事务请求,生成事务提案来进行事务请求处理。
选完 Leader 以后,Zookeeper 就进入状态同步过程。
- 1、Leader 等待 Server 连接。
- 2、Follower 连接 Leader ,将最大的 zxid 发送给 Leader 。
- 3、Leader 根据 Follower 的 zxid 确定同步点。
- 4、完成同步后通知 Follower 已经成为 update 状态。
- 5、Follower 收到 update 消息后,又可以重新接受 Client 的请求进行服务了。
当然,同步流程并不是像上述描述的这么简单,具体的,还是得看看 《Zookeeper Leader 和 Learner 的数据同步》 。
当 Leader 崩溃,或者 Leader 失去大多数的 Follower,这时 Zookeeper 进入恢复模式,恢复模式需要重新选举出一个新的 Leader,让所有的 Server 都恢复到一个正确的状态。
Zookeeper 的选举算法有两种:一种是基于 basic paxos 实现的,另外一种是基于 fast paxos 算法实现的。系统默认的选举算法为 fast paxos 。
相对详细的,可以看看 《【分布式】Zookeeper的Leader选举》 和 《Zookeeper 源码分析 —— Zookeeper Leader 选举算法》 。
- 不同阶段的选举流程
- 服务器启动时期的 Leader 选举。
- 服务器运行时期的 Leader 选举。
- 三种选举算法
- LeaderElection :使用 basic paxos 算法。
- FastLeaderElection :使用 fast paxos 算法。
- AuthFastLeaderElection :在 FastLeaderElection 的基础上,增加认证。
- 最终在 Zookeeper 3.4.0 版本之后,只保留 FastLeaderElection 版本。
-
fast paxos
由于 LeaderElection 收敛速度较慢,所以 Zookeeper 引入了 FastLeaderElection 选举算法,FastLeaderElection 也成了Zookeeper默认的Leader选举算法。
FastLeaderElection 是标准的 Fast Paxos 的实现。它首先向所有 Server 提议自己要成为 Leader ,当其它 Server 收到提议以后,解决 epoch 和 zxid 的冲突,并接受对方的提议,然后向对方发送接受提议完成的消息。重复这个流程,最后一定能选举出Leader。
FastLeaderElection 算法通过异步的通信方式来收集其它节点的选票,同时在分析选票时又根据投票者的当前状态来作不同的处理,以加快 Leader 的选举进程。