文章目录
Zookeeper介绍及基本概念
ZooKeeper 是分布式应用程序的分布式开源协调服务。
设计目标
ZooKeeper 允许分布式进程通过共享的分层命名空间相互协调,该命名空间的组织方式类似于标准文件系统。命名空间由数据寄存器组成——在 ZooKeeper 用语中称为 znodes——它们类似于文件和目录。与为存储而设计的典型文件系统不同,ZooKeeper 数据保存在内存中,这意味着 ZooKeeper 可以实现高吞吐量和低延迟数字。
数据模型和分层命名空间
ZooKeeper 提供的命名空间很像标准文件系统。名称是由斜杠 (/) 分隔的一系列路径元素。ZooKeeper 命名空间中的每个节点都由路径标识。
ZooKeeper 的分层命名空间
节点和临时节点
与标准文件系统不同,ZooKeeper 命名空间中的每个节点都可以拥有与其关联的数据以及子节点。这就像拥有一个允许文件也成为目录的文件系统。(ZooKeeper 被设计用来存储协调数据:状态信息、配置、位置信息等,所以每个节点存储的数据通常很小,默认能够存储 1 MB 的数据)
Znode 维护一个统计结构,其中包括数据更改、ACL 更改和时间戳的版本号,以允许缓存验证和协调更新。每次 znode 的数据更改时,版本号都会增加。例如,每当客户端检索数据时,它也会收到数据的版本。
存储在命名空间中每个 znode 的数据是原子读取和写入的。读取获取与 znode 关联的所有数据字节,写入替换所有数据。每个节点都有一个访问控制列表 (ACL),它限制谁可以做什么。
ZooKeeper 也有临时节点的概念。当client和server连接时,会产生一个会话(session),只要创建 znode 的会话处于活动状态,这些 znode 就存在。当会话结束时,znode 被删除。
有条件的更新和监视
ZooKeeper支持 watch 的概念。客户端可以在 znode 上设置监视。当 znode 发生变化时,watch 将被触发并移除。当 watch 被触发时,客户端会收到一个数据包,说明 znode 已更改。如果客户端和其中一个 ZooKeeper 服务器之间的连接断开,客户端将收到本地通知。
**3.6.0 中的新功能:**客户端还可以在 znode 上设置永久的递归监视,这些监视在触发时不会被删除,并且会以递归方式触发已注册 znode 以及任何子 znode 上的更改。
ZooKeeper 的复制集群结构
集群特点:
- zookeeper集群拥有一主(Leader)多从(Follower),主节点提供读写,其他节点提供查询。
- 集群中只要有过半的节点存活,Zookeeper 集群就能正常提供服务。
- 顺序一致性 ——来自客户端的更新将按照它们发送的顺序执行。
- 统一视图 ——客户端不管连接到哪个server,看到的数据都是一致的(包括客户端连接产生的session也会统一视图)。
- 原子性 ——更新要么成功要么失败,没有中间状态。
- 可靠性 ——应用更新后,它将从那时起持续存在,直到客户端覆盖更新(数据的持久化)。
- 及时性——系统的客户视图保证在一定的时间范围内是最新的(数据的最终一致性)。
扩展性:通过引入observer角色,增加集群的读写能力。
观察者:在不影响写入性能的情况下扩展 ZooKeeper
只有leader和follower的架构很难扩展到大量客户端。随着我们添加更多投票成员,写入性能下降。这是因为写入操作需要(通常)集成中至少一半节点的协议,因此随着更多选民的加入,投票的成本会显着增加。
引入Observer的新型 ZooKeeper 节点,它有助于解决这个问题并进一步提高 ZooKeeper 的可扩展性。观察者是一个整体中没有投票权的成员,他们只听到投票结果。除了这个简单的区别之外,观察者的功能与追随者完全相同——客户端可以连接到它们并向它们发送读写请求。观察者像追随者一样将这些请求转发给领导者。正因为如此,我们可以在不影响投票性能的情况下尽可能多地增加观察者的数量。
观察者还有其他优势。因为他们不投票,所以他们不是 ZooKeeper 集合的关键部分。因此,它们可能会失败,或者与集群断开连接,而不会损害 ZooKeeper 服务的可用性。对用户的好处是观察者可能通过比追随者更不可靠的网络链接进行连接。事实上,Observers 可用于与来自另一个数据中心的 ZooKeeper 服务器通信。Observer 的客户端将看到快速读取,因为所有读取都在本地提供,并且写入导致最小的网络流量,因为在没有投票协议的情况下所需的消息数量更少。
可靠性:通过ZAB协议(原子广播协议)(基于Paxos算法)实现数据的一致性,前提leader存活(服务可用)的情况下。
感兴趣的同学可以看一下关于Paxos算法(基于消息传递的一致性算法)和ZAB协议
[https://blog.csdn.net/xishilife/article/details/119962694]:
zk的两阶段提交(服务可用状态下)
-
客户端向一个follower节点提交create请求
-
follower将写入请求提交给leader
-
假如此事务id(zxid)为1,leader通过队列给两个follower发起写日志(日志是记录在磁盘中的)
-
4-1 follower 1收到并返回给leader一个ok,follower 2由于某些原因没有返回
4-2 由于leader加follower 1两票已达到过半通过,所以leader开始通过队列向两个follower写数据(数据是写在内存中)
-
给客户端返回ok
zk的投票选举(服务停止状态下)
什么场景下需要投票选举:
- 当集群第一次启动时。
- 服务运行期间leader故障挂掉时。
概念:
myid:服务器id,如有三台zk服务器,每个服务器都有自己的myid,myid越大,在选举时权重越大。
zxid:事务id,服务器中存放的数据的事务ID,值越大说明数据越新,zxid越大,在选举时权重越大。
选举过程:先判断zxid,再判断myid,当zxid相同时候,zk集群谦让(推选)制选举,优先选择myid大者为leader。
总结:
-
当集群第一次启动时,因为所有人的事务id相同,所以选myid大者为leader。
-
当服务运行期间leader故障挂掉时触发新一轮选举,其他服务器互相通信,将事务id最大且myid最大者为leader。