封装 WatchedEvent :
将通知状态(SyncConnected)、事件类型(NodeDataChanged)以及节点路径封装成一个WatchedEvent对象查询 Watcher :
从 WatchTable 中根据节点路径查找 Watcher 。
没找到 :说明没有客户端在该数据节点上注册过 Watcher 。
找到 :提取并从 WatchTable 和 Watch2Paths 中删除对应 Watcher (从这里可以看出Watcher 在服务端是一次性的,触发一次就失效了)。
3、调用 process 方法来触发 Watcher 。
这里 process 主要就是通过 ServerCnxn 对应的 TCP 连接发送 Watcher 事件通知。
?? 第三步,客户端回调 Watcher 实现?
客户端 SendThread 线程接收事件通知,交由 EventThread 线程回调Watcher 。客户端的 Watcher 机制同样是一次性的,一旦被触发后,该 Watcher 就失效了。
Zookeeper 采用什么权限控制机制?
在网上看到一个「你们的 Zookeeper 的节点加密是用的什么方式?」问题,应该也是问这个。
目前,在 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 相关设置操作。
?? Chroot 特性是什么?
Zookeeper 3.2.0 版本后,添加了 Chroot 特性。该特性允许每个客户端为自己设置一个命名空间。如果一个客户端设置了 Chroot ,那么该客户端对服务器的任何操作,都将会被限制在其自己的命名空间下。
通过设置 Chroot ,能够将一个客户端应用于 Zookeeper 服务端的一颗子树相对应,在那些多个应用公用一个Zookeeper 进群的场景下,对实现不同应用间的相互隔离非常有帮助。:貌似实际还用的比较少。
Zookeeper 的会话管理是怎么样的?
ZooKeeper 的每个客户端都维护一组服务端信息,在创建连接时由应用指定,客户端随机选择一个服务端进行连接,连接成功后,服务端为每个连接分配一个唯一标识。
客户端在创建连接时可以指定溢出时间,客户端会周期性的向服务端发送 PING 请求来保持连接。如果客户端异常下线,或者网络问题,导致一段时间没心跳给 Zookeeper 服务端,则会被 Zookeeper标记为下线。
当客户端检测到与服务端断开连接后,客户端将自动选择服务端列表中的另一个服务端进行重连。客户端允许应用修改服务端列表,但修改可能导致客户端与服务端的重连。详细的,推荐阅读如下两篇文章:
《ZooKeeper session 管理》《ZooKeeper 技术内幕:会话》 更原理层面。
Zookeeper 的部署方式?
Zookeeper 有两种部署方式:
1、单机2、集群
Zookeeper 集群,是一个由多个 Server 组成,一个 Leader,多个 Follower。(这个不同于我们常见的Master/Slave 模式)Leader 为客户端服务器提供读写服务,除了 Leader 外其他的机器只能提供读服务。每个 Server 保存一份数据副本全数据一致,分布式读 Follower ,写由 Leader 实施更新请求转发,由Leader 实施更新请求顺序进行,来自同一个 Client 的更新请求按其发送顺序依次执行数据更新原子性,一次数据更新要么成功,要么失败。
全局唯一数据视图,Client 无论连接到哪个 Server,数据视图都是一致的实时性,在一定事件范围内,Client 能读到最新数据。
一般来说,测试环境部署单机,而生产环境必须必须必须部署集群。
?? 集群中的机器角色有哪些?集群中一共有三种角色:
1、Leader
事务请求的唯一调度和处理者,保证集群事务处理的顺序性。集群内部各服务的调度者。
2、Follower
处理客户端的非事务请求,转发事务请求给 Leader 服务器。参与事务请求 Proposal 的投票。参与 Leader 选举投票。
3、Observer
3.3.0 版本以后引入的一个服务器角色,在不影响集群事务处理能力的基础上提升集群的非事务处理能力。
处理客户端的非事务请求,转发事务请求给 Leader 服务器不参与任何形式的投票。
如果 ZooKeeper 集群的读取负载很高,或者客户端多到跨机房,可以设置一些 Observer 服务器,以提高读取的吞吐量。Observer 和 Follower 比较相似,只有一些小区别:
首先 Observer 不属于法定人数,即不参加选举也不响应提议,也不参与写操作的“过半写成功”策略;
其次是 Observer 不需要将事务持久化到磁盘,一旦 Observer 被重启,需要从 Leader 重新同步整个名字空间。
在一个集群中,最少需要 3 台。或者保证 2N + 1 台,即奇数。为什么保证奇数?主要是为了选举算法。?? 集群如果有 3 台机器,挂掉 1 台集群还能工作吗?挂掉 2 台呢?
记住一个原则:过半存活即可用。所以挂掉 1 台可以继续工作,挂掉 2 台不可以工作。?? 集群支持动态添加机器吗?在 3.5 版本开始,支持动态扩容。
而在 3.5 版本之前,Zookeeper 在这方面不太好。所以需要如下两种方式:
全部重启:关闭所有 Zookeeper 服务,修改配置之后启动。不影响之前客户端的会话。逐个重启:顾名思义。这是比较常用的方式。?? Zookeeper 下 Server 工作状态?服务器具有四种状态,分别是:
LOOKING 寻找 Leader 状态
当服务器处于该状态时,它会认为当前集群中没有 Leader ,因此需要进入 Leader 选举状态。FOLLOWING 跟随者状态
表明当前服务器角色是 Follower 。LEADING 领导者状态
表明当前服务器角色是 Leader 。OBSERVING 观察者状态
表明当前服务器角色是 Observer 。
ZooKeeper 的工作原理?
ZooKeeper 的核心是原子广播,这个机制保证了各个 Server 之间的同步。实现这个机制的协议叫做 Zab 协议。Zab 协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步):
选主:当服务启动或者 Leader 崩溃后,Zab 就进入了恢复模式,当新的 Leader 被选举出来,且大多数Server 完成了和 Leader 的状态同步以后,恢复模式就结束了。更加详细的描述。
当整个 Zookeeper 集群刚刚启动,或者 Leader 服务器宕机、重启或者网络故障导致不存在过半的服务器与 Leader服务器保持正常通信时,所有进程(服务器)进入崩溃恢复模式。
首先,选举产生新的Leader服务器。
然后,集群中 Follower 服务器开始与新的 Leader 服务器进行数据同步。
当集群中超过半数机器与该Leader服务器完成数据同步之后,退出恢复模式进入消息广播模式,
同步:状态同步保证了 Leader 和 Server 具有相同的系统状态。更加详细的描述。
Leader 服务器开始接收客户端的事务请求,生成事务提案来进行事务请求处理。
?? ZooKeeper 是如何保证事务的顺序一致性的?
ZooKeeper 采用了递增的事务 id 来识别,所有的 proposal(提议)都在被提出的时候加上了 zxid 。zxid 实际上是一个 64 位数字。
高 32 位是 epoch 用来标识 Leader 是否发生了改变,如果有新的 Leader 产生出来,epoch会自增。低 32 位用来递增计数。
当新产生的 peoposal 的时候,会依据数据库的两阶段过程,首先会向其他的 Server 发出事务执行请求,如果超过半数的机器都能执行并且能够成功,那么就会开始执行。?? ZooKeeper 集群中个服务器之间是怎样通信的?
Leader 服务器会和每一个 Follower/Observer 服务器都建立 TCP 连接,同时为每个 Follower/Observer 都创建一个叫做 LearnerHandler 的实体。
LearnerHandler 主要负责 Leader 和 Follower/Observer 之间的网络通讯,包括数据同步,请求转发和Proposal 提议的投票等。
Leader 服务器保存了所有 Follower/Observer 的 LearnerHandler 。?? ZAB 和 Paxos 算法的联系与区别?
Paxos 算法是分布式选举算法,Zookeeper 使用的 ZAB 协议(Zookeeper 原子广播)。二者有相同的地方:
都有一个 Leader,用来协调 N 个 Follower 的运行
Leader 要等待超半数的 Follower做 出正确反馈之后才进行提案。
二者都有一个值来代表 Leader 的周期。ZAB 协议中,每个 Proposal 中都包含一个 epoch 值来代表当前的Leader周期,Paxos中名字为 Ballot 。不同的地方在于:
ZAB 用来构建高可用的分布式数据主备系统(Zookeeper),Paxos 是用来构建分布式一致性状态机系统。Paxos 算法、ZAB 协议要想讲清楚可不是一时半会的事儿,自 1990 年莱斯利·兰伯特提出 Paxos 算法以来,因为晦涩难懂并没有受到重视。后续几年,兰伯特通过好几篇论文对其进行更进一步地解释,也直到 06 年谷歌发表了三篇论文,选择 Paxos 作为 Chubby cell 的一致性算法,Paxo s才真正流行起来。
对于普通开发者来说,尤其是学习使用 Zookeeper 的开发者明确一点就好:分布式 Zookeeper 选举 Leader 服务器的算法,与 Paxos 有很深的关系。
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 版本。
?? 看下面的原理描述,还是有点懵逼。等后面自己去撸下源码,可能会清晰一些。?? Zookeeper 选主流程(basic paxos)?选择性了解。
1、选举线程由当前 Server 发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的 Server。
2、选举线程首先向所有 Server 发起一次询问(包括自己)。
3、选举线程收到回复后,验证是否是自己发起的询问(验证 zxid 是否一致),然后获取对方的 id(myid),并存储到当前询问对象列表中,最后获取对方提议的 Leader相关信息(id,zxid),并将这些信息存储到当次选举的投票记录表中。
4、收到所有 Server 回复以后,就计算出 zxid 最大的那个 Server ,并将这个 Server 相关信息设置成下一次要投票的 Server 。
5、线程将当前 zxid 最大的 Server 设置为当前 Server 要推荐的 Leader ,如果此时获胜的 Server 获得
n/2+1 的 Server 票数,设置当前推荐的 Leader 为获胜的 Server ,将根据获胜的 Server 相关信息设置自
当 Leader 崩溃,或者 Leader 失去大多数的 Follower,这时 Zookeeper 进入恢复模式,恢复模式需要重新选举出
己的状态,否则,继续这个过程,直到 Leader 被选举出来。