Skip to content

ZooKeeper

zk是个数据库,文件存储系统,并且有监听通知机制(观察者模式).

zk存储的节点

  • 持久化节点(zk断开节点还在)
  • 持久化顺序编号目录节点
  • 临时目录节点(客户端断开后节点就删除了)
  • 临时目录编号目录节点(可以实现分布式锁)

节点名称都是唯一的

zk应用场景

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

zk工作原理

ZooKeeper(后面简称zk)的核心是原子广播,这个机制保证了各个 server 之间的同步。实现这个机制的协议叫做 Zab (ZooKeeper Atomic Broadcast)协议。Zab 协议有两种模式,它们分别是恢复模式和广播模式。原子广播用于保证所有的变更操作按照相同的顺序在所有节点上被应用。

细节:

  • 数据模型: ZooKeeper维护一个分层的命名空间,类似于文件系统,其中每个节点称为”znode”。每个znode都可以存储一小段数据,同时每个znode都有一个版本号(version),用于实现乐观并发控制
  • 分布式存储: Zookeeper的数据存储分布在多个节点上,这些节点称为”ZooKeeper服务器”或”ZooKeeper集群”。数据的每次变更都需要经过多数节点的一致性确认,以确保数据的可靠性和一致性。
  • Zab协议: Zab协议是ZooKeeper的核心组件,用于确保数据的一致性。它基于Paxos算法,但针对ZooKeeper的需求进行了定制。Zab协议分为两个阶段(准备阶段&&提交阶段):Leader Election(领导者选举)和Atomic Broadcast(原子广播)。领导者选举阶段用于选举一个Leader节点,而原子广播阶段用于保证所有的变更操作按照相同的顺序在所有节点上被应用。

    Zab协议通过原子广播的方式,在分布式系统中实现了一致性和可靠性,保证了数据的一致性和正确性

  • Leader-Follower模型: ZooKeeper集群中有一个Leader节点和多个Follower节点。Leader节点负责处理客户端的读写请求,而Follower节点负责复制Leader的数据。如果Leader节点发生故障,集群会重新选举一个新的Leader。新的 Leader 通过比对已完成的事务日志和未完成的临时提案来进行恢复
  • 客户端交互: 客户端通过连接到ZooKeeper集群中的任何一个节点来与ZooKeeper交互。客户端可以发送读取请求(例如get操作)和写入请求(例如create、set和delete操作)。
  • 顺序性操作: Zookeeper保持客户端请求的顺序,以确保一致性。每个操作都会分配一个全局唯一的序列号(zxid),并且只有在Leader节点成功将操作应用到大多数Follower节点后,才会被认为是提交成功。
  • 事件通知: ZooKeeper支持事件通知机制,客户端可以注册对特定znode的事件关注,一旦该znode发生变化,ZooKeeper将通知相关客户端。

zk相关的问题

在看zk的时候,突然想到Apollo配置中心,它的服务注册发现没有使用zk,而是使用了eureka。

该图片来自互联网

dubbo为什么选择zk作为注册中心?

  1. Zookeeper的数据模型很简单,有一系列被称为ZNode的数据节点组成,与传统的磁盘文件系统不同的是,zk将全量数据存储在内存中,可谓是高性能,而且支持集群,可谓高可用,另外支持事件监听。这些特点决定了zk特别适合作为注册中心(数据发布/订阅)
  2. 注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小。
  3. Zookeeper 是 Apacahe Hadoop 的子项目,是一个树型的目录服务,支持变更推送,适合作为Dubbox 服务的注册中心,工业强度较高,可用于生产环境。
  4. 使用zk的优势:
    1. 当提供程序意外停止时,注册表服务器可以自动删除其信息。
    2. 注册表服务器重新启动时,可以自动恢复所有注册数据和订阅请求。
    3. 会话过期后,可以自动恢复所有注册数据和订阅请求。

该图片来自互联网

zk与eureka区别

  • zookeeper保证CP(一致性)

    所以在很多微服务上,用作注册中心,这样多个微服务的数据都是一致的

  • zk在选举期间注册服务瘫痪,期间不可用
  • eureka保证AP(可用性)
  • eureka各个节点平等关系,只要有一台就可保证服务可用(只不过查询到的数据可能不是最新的),可以很好应对网络故障导致部分节点失联情况
  • zk有leader和follower角色,eureka各个节点平等
  • zk采用半数存活原则(避免脑裂),eureka采用自我保护机制来解决分区问题

eureka本质是个工程,zk只是一个进程。 zk基于CP,不保证高可用,如果zk正在选主,或者zk集群中半数以上机器不可用,那么将无法获得数据。 Eureka基于AP,能保证高可用,即使所有机器都挂了,也能拿到本地缓存的数据。作为注册中心,其实配置是不经常变动的,只有发版(发布新的版本)和机器出故障时会变。对于不经常变动的配置来说,CP是不合适的,而AP在遇到问题时可以用牺牲一致性来保证可用性,既返回旧数据,缓存数据。 所以【理论上Eureka是更适合做注册中心】。而现实环境中大部分项目可能会使用ZooKeeper,那是因为集群不够大,并且基本不会遇到用做注册中心的机器一半以上都挂了的情况。所以实际上也没什么大问题。

eureka自我保护机制

  • eureka不移除长时间没收到心跳而应该过期的服务
  • 仍然接受新服务注册和查询请求,但是不会同步到其它节点(高可用)
  • 当网络稳定后,当前实例新注册信息会同步到其它节点(最终一致性)

ZooKeeper 如何进行崩溃修复?

在 ZooKeeper 中有三种节点类型,它们分别是:

  • Leader(主节点):能够处理读写请求,也同时负责同步写事务请求给其他节点且需要保证事务的顺序性,是整个集群的老大。
  • Follower(跟随者):只负责处理读请求,无权写,因此收到写请求需要转发给 Leader 处理,待 Leader 写完后再同步给 Follower。如果 Leader 挂了,那么 Follower 是有资格参与竞选的。
  • Observer(观察者):和 Follower 一样,唯一不同的是,不参与 Leader 的选举,可以利用不参与 Leader 选举的特性用来线性扩展读的 QPS。

也就是说,所有写操作会先到 Leader 节点,然后 Leader 节点在通过 2PC(两阶段提交:预提交、ACK、确认提交等流程)来进行数据同步,当写入成功过半就认为信息写入成功。而跟随者和观察者是为了增加读性能的,只不过跟随者还可以通过竞选主节点来保证集群的稳定性。