Zookeeper是CP的还是AP的?

典型回答 ZooKeeper作为分布式协调服务,它的职责是保证数据(注:配置数据,状态数据)在其管辖下的所有服务之间保持同步、一致。所以,我们可以认为Zookeeper是一个CP的分布式系统。所以他会牺牲可用性,也就是在极端环境下,ZooKeeper可能会丢弃一些请求,消费者程序需要重新请求才能获得结果。 这个 CP体现在以下几个情况下: 1、如果集群中的存活节点数低于总结点数的一半,那么整个集群将无法接受新的写请求。 2、在 ZK 的 master 选举过程中,在新的Master被选举出来之前,整个集群也无法接受新的写请求。 而且, 作为ZooKeeper的核心实现算法 Zab,就是解决了分布式系统下数据如何在多个服务之间保持同步问题的。 如果 ZooKeeper下所有节点都断开了,或者集群中出现了网络分割的故障(注:由于交换机故障导致交换机底下的子网间不能互访);那么ZooKeeper 会将它们都从自己管理范围中剔除出去,外界就不能访问到这些节点了,即便这些节点本身是“健康”的,可以正常提供服务的;所以导致到达这些节点的服务请求被丢失了。 但是,请一定要注意,这里面的一致性,他确实是强一致性,但是,Zookeeper保证的是强一致模型中的顺序一致性而不是线性一致性。 (这个很少有人提) ✅什么是分布式系统的一致性? 这一点在ZK的官网(https://zookeeper.apache.org/doc/r3.4.13/zookeeperProgrammers.html )上明确的说过: 这里明确的提了,Zookeeper是保证的顺序一致性,也就是说,ZooKeeper不保证在每个时间点,两个不同的客户端将具有相同的ZooKeeper数据视图。但是他能保证我们在每个节点上读取到的一定是他最后一次更新的内容。 具体的案例就是,当Zookeeper在进行数据同步的过程中,如果半数节点同步成功,它就提交当前事务,但此时集群内还有可能有节点没有同步到数据,如果此时读请求发送到没有同步到数据的节点,那么就会读到旧的数据。 但是Zookeeper是会保证这个节点最终也会按照顺序执行成功的。 扩展知识 如何保证真正的强一致性? 想要让Zookeeper真正的保证强一致性,或者说保证线性一致性也是有办法的,那就是通过sync命令。 当我们对一个Follower调用sync命令的时候,会使得他和Leader节点进行数据同步,并等待服务器同步完成之后再返回。这样下一次的read就能保证拿到的是最新数据了。(不发生脑裂的情况下)

March 22, 2026 · 1 min · santu

Zookeeper是选举机制是怎样的?

典型回答 ZooKeeper的选举机制是其实现分布式协调一致性的核心部分,它确保在ZooKeeper集群中选择一个Leader节点来协调和处理客户端请求。 一次完整的选举大概要经历以下几个步骤: 初始化阶段: 在一个ZooKeeper集群中,每个Follower节点都可以成为Leader。初始状态下,所有Follower节点都是处于"LOOKING"状态,即寻找Leader。每个节点都会监视集群中的其他节点,以侦听Leader选举消息。 提名和投票: 当一个节点启动时,它会向其他节点发送投票请求,称为提名。节点收到提名后可以选择投票支持这个提名节点,也可以不投票。每个节点只能在一个选举周期内投出一票。 在提名过程中,所有的投票者都遵守一个原则,那就是遇强投强。 怎么算强? 在Zookeeper中,通过数据是否足够新来判断这个节点是不是够强。在 Zookeeper 中以事务id(zxid)来标识数据的新旧程度,节点的zxid越大代表这个节点的数据越新,也就代表这个节点能力越强。 那么在投票过程中,节点首先会认为自己是最强的,所以他会在投票时先投自己一票,然后把自己的投票信息广播出去,这里面包含了zxid和sid,zxid就是自己的事务ID,sid就是标识出自己是谁的唯一标识。 这样集群中的节点们就会不断收到别人发过来的投票结果,然后这个节点就会拿别人的zxid和自己的zxid进行比较,如果别人的zxid更大, 说明他的数据更新,那么就会重新投票,把zxid和sid都换成别人的信息再发出去。 选举过程: 选举过程分为多个轮次,每个轮次被称为一个"选举周期"。在每个选举周期中,节点根据投票数来选择新的Leader候选者。如果一个候选者获得了大多数节点(超过半数)的投票,那么它就会成为新的Leader。否则,没有候选者能够获得足够的投票,那么这个选举周期失败,所有节点会继续下一个选举周期。 Leader确认: 一旦一个候选者获得了大多数节点的投票,它就会成为新的Leader。这个Leader会向其他节点发送Leader就绪消息,告知它们自己已经成为Leader,并且开始处理客户端的请求。 集群同步: 一旦新的Leader选举完成,其他节点会与新Leader同步数据,确保所有节点在一个一致的状态下运行。这个同步过程也包括了未完成的客户端请求,以保证数据的一致性。 扩展知识 选举状态 在整个选举过程中,节点的状态可能有4种,分别是 LOOKING,竞选状态。 FOLLOWING,随从状态,同步leader状态,参与投票。 OBSERVING,观察状态,同步leader状态,但是不参与投票。 LEADING,领导者状态。 Leader选举的场景 ZooKeeper其实会在两种情况下进行Leader选举,第一种是集群的启动阶段,第二个是Leader失效了的情况。 启动阶段: 当整个ZooKeeper集群启动时,这时候还没有Leader,那么就会进行一次Leader选举。 Leader失效:如果当前的Leader节点由于某种原因(如宕机、网络故障、连接丢失等)失效,剩余的节点会开始一个新的选举周期来选择新的Leader。 启动阶段的Leader选举 假设一个 Zookeeper 集群中有5台服务器,id从1到5编号,并且它们都是最新启动的,没有历史数据。 假设服务器依次启动,那么大致的选举过程: 服务器1启动,进入LOOKING状态,开始发起投票,服务器1投自己一票,<zxid=1,sid=1> 投票结果:服务器1,1票 服务器1状态:LOOKING 因为投票总数未过半,则继续选举。 服务器2启动,进入LOOKING状态,开始投票,服务器2投自己一票<zxid=2,sid=2>,并收到服务器1的投票<zxid=1,sid=1>。同时服务器1也收到服务器2的投票<zxid=2,sid=2>,经比对,服务器2的zxid更大,于是服务器1改票<zxid=2,sid=2> 投票结果:服务器2,2票 服务器1状态:LOOKING 服务器2状态:LOOKING 因为投票总数未过半,则继续选举。 服务器3启动,同样经过和服务器2一样的过程,之后服务器1,服务器2开始改投服务器3, 发起一次选举,服务器1、2、3先投自己一票,然后因为服务器3的id最大,两者更改选票投给为服务器3; 投票结果:服务器3,3票 服务器1状态:FOLLOWING 服务器2状态:FOLLOWING 服务器3状态:LEADING 服务器4启动,发现集群中已经有Leader,则自己变为Follower,进入FOLLOWING状态。 服务器1状态:FOLLOWING 服务器2状态:FOLLOWING 服务器3状态:LEADING 服务器4状态:FOLLOWING ...

March 22, 2026 · 1 min · santu

Zookeeper的watch机制是如何工作的?

典型回答 在Zookeeper中,watch机制是一种非常重要的特性,它能够让应用程序监听Zookeeper上节点的变化,从而及时做出响应。 Zookeeper的watch机制实现中,涉及到多个概念,首先是客户端和服务端,这个好理解,Zookeeper的集群就是服务端,调用ZK服务的机器就是客户端。 还有两个模块,分别叫做WatchManager和ZkWatcherManager。 WatchManager是Zookeeper服务端内部的一个模块,用于管理所有watcher的相关操作,包括watcher的注册、注销、触发等。 而ZkWatcherManager是Zookeeper客户端中的一个模块,用于管理客户端中watcher的相关操作,包括创建watcher、注册watcher、处理watcher事件等。 (PS:这俩模块所处的位置和职责都不一样,网上很多文章都搞混了,甚至只介绍了其中一个,或者干脆不介绍,所以很多人看完都不懂) 了解了这几个概念之后,再来说一下ZK的watch机制是如何工作的: 客户端连接到Zookeeper服务端,客户端创建一个ZkWatcherManager实例,用于管理客户端中所有的watcher。 当客户端想要监控某个znode节点时,它可以调用ZkWatcherManager中的方法创建watcher并将其注册到客户端中。客户端将watcher的信息发送到Zookeeper服务端。 Zookeeper服务端接收到客户端发送的watcher信息后,会将该watcher信息交给WatchManager处理。WatchManager会将该watcher注册到相应的znode节点上,并将watcher相关的信息保存在内存中。 当znode节点发生变化时,WatchManager会通知Zookeeper Server Zookeeper Server会根据变化类型通知相应的客户端,告知它们发生了哪些变化。 当客户端接收到Zookeeper Server的通知后,ZkWatcherManager会根据watcher的类型(data watcher或child watcher)来触发相应的事件处理方法,例如data watcher会触发processDataChanged()方法,child watcher会触发processChildChanged()方法等。

March 22, 2026 · 1 min · santu

Zookeeper的典型应用场景有哪些?

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务。常见的应用场景如下: 分布式配置管理:ZooKeeper可以存储配置信息,应用程序可以动态读取配置信息。 分布式同步:ZooKeeper可以协调各个节点的同步,确保数据的一致性。 命名服务:ZooKeeper可以作为一个命名服务,应用程序可以通过名字来找到所需的服务。 集群管理:ZooKeeper可以用来管理分布式集群,协调各个节点的加入和退出。 Master选举:ZooKeeper可以用来实现Master选举,选择一个节点作为Master节点。 分布式协调服务:Zookeeper提供了一些分布式协调服务,如分布式锁、唯一标识生成等,帮助系统中的各个组件之间进行协调。 服务注册和发现:Zookeeper可以用于注册和发现系统中的服务,简化服务的部署和更新。 负载均衡:Zookeeper可以用于动态地对请求进行负载均衡,以提高系统的可用性。 总之,ZooKeeper是一个非常适用于分布式应用程序的协调服务,它提供了强大的分布式协调功能,可以简化分布式应用程序的开发。

March 22, 2026 · 1 min · santu

Zookeeper的数据结构是怎么样的?

数据模型 ZK中数据是以目录结构的形式存储的。其中的每一个存储数据的节点都叫做Znode,每个Znode都有一个唯一的路径标识。和目录结构类似,每一个节点都可以可有子节点(临时节点除外)。节点中可以存储数据和状态信息,每个Znode上可以配置监视器(watcher),用于监听节点中的数据变化。节点不支持部分读写,而是一次性完整读写。 节点 Znode有四种类型,PERSISTENT(持久节点)、PERSISTENT_SEQUENTIAL(持久的连续节点)、EPHEMERAL(临时节点)、EPHEMERAL_SEQUENTIAL(临时的连续节点) Znode的类型在创建时确定并且之后不能再修改 临时节点 临时节点的生命周期和客户端会话绑定。也就是说,如果客户端会话失效,那么这个节点就会自动被清除掉。 1 2 3 4 5 6 7 8 9 10 11 String root = "/ephemeral"; String createdPath = zk.create(root, root.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println("createdPath = " + createdPath); String path = "/ephemeral/test01" ; createdPath = zk.create(path, path.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); System.out.println("createdPath = " + createdPath); Thread.sleep(1000 * 20); // 等待20秒关闭ZooKeeper连接 zk.close(); // 关闭连接后创建的临时节点将自动删除 临时节点不能有子节点 ...

March 22, 2026 · 2 min · santu

Zookeeper集群中的角色有哪些?有什么区别?

ZK中主要有以下角色: **领导者(leader):**负责进行投票的发起和决议,更新系统状态。为客户端提供读和写服务。 **跟随者(follower):**用于接受客户端请求并响应客户端返回结果,在选主过程中参与投票。为客户端提供读服务。 **观察者(observer):**可以接受客户端连接,将写请求转发给leader,但observer不参加投票过程,只同步leader的状态,observer的目的是为了扩展系统,提高读取速度。 **客户端(client):**请求发起方

March 22, 2026 · 1 min · santu

什么是脑裂?如何解决?

典型回答 脑裂是在分布式系统中经常出现的问题之一,它指的是由于网络或节点故障等原因,导致一个分布式系统被分为多个独立的子系统,每个子系统独立运行,无法相互通信,同时认为自己是整个系统的主节点,这就会导致整个系统失去一致性和可用性。 Zookeeper集群中的**脑裂出现的原因**通常有以下2种情况: 网络分区 当Zookeeper集群中的某些节点无法与其他节点通信时,就会出现网络分区现象。这时,无法确定哪个节点是主节点,容易导致多个主节点的情况。 主节点宕机 当Zookeeper集群中的主节点宕机时,其他节点可能会重新选举新的主节点。如果宕机的主节点恢复后,会与其他节点产生不一致,可能导致脑裂。 针对Zookeeper集群中的脑裂问题,可以采取以下几种方式进行**恢复脑裂**: 自动恢复机制 当Zookeeper集群中出现脑裂时,Zookeeper会自动发现并尝试恢复。当大多数节点恢复后,会重新选举主节点,并将状态同步给其他节点。 手动恢复 手动恢复可以通过在网络分区的节点上运行一个Zookeeper服务实例,并将其配置为独立的集群,等待分区恢复后将其重新合并。在主节点宕机时,可以使用手动恢复来恢复脑裂。这种方式需要手动干预,比较复杂,需要考虑数据同步、节点选举等问题。 那么,有没有办法**避免脑裂**的发生呢? 可以通过设置合适的选举超时时间、设置合适的节点数量等方式来减少脑裂的可能性。同时,可以使用ZooKeeper提供的Watch机制来监听节点状态的变化,及时发现并处理异常情况,从而避免脑裂的发生。 扩展知识 Zookeeper的自动恢复机制 当 ZooKeeper 集群中出现脑裂问题时,ZooKeeper 会自动检测到这种情况,并尝试进行自动恢复。那么过程是怎么样的呢? 识别集群分裂 当 ZooKeeper 集群中的某些节点与其他节点失去了联系,无法互相通信时,就会形成网络分区,导致集群分裂。这时候ZooKeeper就会发现集群分裂,会尝试解决这个问题。 选举新的主节点 在 ZooKeeper 集群中,所有的节点都有可能成为主节点,当旧的主节点无法与其他节点通信时,集群将选举一个新的主节点。在选举过程中,各个节点会向其他节点发送信息,包括选票和心跳包。如果有足够多的节点认为某个节点是主节点,该节点就会成为主节点。 数据同步 在选举新的主节点后,集群中的所有节点将尝试同步数据。ZooKeeper使用“原子广播”机制,确保数据在所有节点上是一致的。新的主节点将在其他节点上复制所有最新的数据,并在后续的操作中与其他节点同步。 恢复正常状态 一旦集群恢复到正常状态,ZooKeeper将更新集群状态,并将最新的状态同步给所有节点。此时,集群中只有一个主节点,并且所有节点都具有相同的数据,从而保证了集群的一致性。

March 22, 2026 · 1 min · santu

如何用Zookeeper实现分布式锁?

基于zookeeper临时有序节点可以实现的分布式锁。 大致思想即为:每个客户端对某个方法加锁时,在zookeeper上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点。 判断是否获取锁的方式很简单,只需要判断有序节点中序号最小的一个。 当释放锁的时候,只需将这个瞬时节点删除即可。同时,其可以避免服务宕机导致的锁无法释放,而产生的死锁问题。 来看下Zookeeper能不能解决以下问题。 锁无法释放?使用Zookeeper可以有效的解决锁无法释放的问题,因为在创建锁的时候,客户端会在ZK中创建一个临时节点,一旦客户端获取到锁之后突然挂掉(Session连接断开),那么这个临时节点就会自动删除掉。其他客户端就可以再次获得锁。 非阻塞锁?使用Zookeeper可以实现阻塞的锁,客户端可以通过在ZK中创建顺序节点,并且在节点上绑定监听器,一旦节点有变化,Zookeeper会通知客户端,客户端可以检查自己创建的节点是不是当前所有节点中序号最小的,如果是,那么自己就获取到锁,便可以执行业务逻辑了。 不可重入?使用Zookeeper也可以有效的解决不可重入的问题,客户端在创建节点的时候,把当前客户端的主机信息和线程信息直接写入到节点中,下次想要获取锁的时候和当前最小的节点中的数据比对一下就可以了。如果和自己的信息一样,那么自己直接获取到锁,如果不一样就再创建一个临时的顺序节点,参与排队。 单点问题?使用Zookeeper可以有效的解决单点问题,ZK是集群部署的,只要集群中有半数以上的机器存活,就可以对外提供服务。 可以直接使用zookeeper第三方库Curator客户端,这个客户端中封装了一个可重入的锁服务。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { try { return interProcessMutex.acquire(timeout, unit); } catch (Exception e) { e.printStackTrace(); } return true; } public boolean unlock() { try { interProcessMutex.release(); } catch (Throwable e) { log.error(e.getMessage(), e); } finally { executorService.schedule(new Cleaner(client, path), delayTimeForClean, TimeUnit.MILLISECONDS); } return true; } Curator提供的InterProcessMutex是分布式锁的实现。acquire方法用户获取锁,release方法用于释放锁。 ...

March 22, 2026 · 1 min · santu

怎样使用Zookeeper实现服务发现?

典型回答 服务发现是ZK的重要用途之一,当我们想要基于zk实现服务发现时,一般可以参考以下步骤: 向Zookeeper注册服务 服务提供者需要在Zookeeper上创建一个临时节点来注册自己的服务。节点的名称通常是服务名称和版本号等信息的组合,节点的数据可以包含服务的地址、端口、协议等信息。因为是临时节点,所以当服务提供者关闭或崩溃时,该节点将自动从Zookeeper中删除。 客户端订阅服务 服务消费者需要在Zookeeper上订阅自己所需的服务。它可以监听服务节点的变化,一旦节点发生变化,就会接收到通知。服务消费者可以根据需要选择自己感兴趣的服务节点。 服务消费者还可以通过Zookeeper提供的API获取当前可用的服务列表。它可以从服务节点的子节点中获取服务的地址和端口等信息,然后根据自己的业务逻辑选择一个合适的服务节点。还可以在服务节点上设置监听器,一旦节点发生变化,就会收到通知。这样可以保证服务消费者随时获取到最新的服务列表。 扩展知识 Zookeeper和Nacos、Eureka、Consul区别? 我们知道,服务发现有很多框架,比如Nacos、Eureka、Consul等,那这些工具和Zookeeper有什么不同呢,已经有了ZK为什么还需要这些工具呢? 虽然Zookeeper也可以用于实现服务发现,但是它并不是专门为服务发现而设计的,因此在某些场景下可能存在一些不足, 首先,Zookeeper的配置和使用相对较为复杂,需要熟悉它的底层原理和API,对于开发人员和运维人员都有一定的学习成本。 第二,Zookeeper主要是用于分布式协调和同步,对于高频率的服务注册和查询请求,其性能可能会受到影响。 第三,Zookeeper虽然支持服务注册和发现,但在某些方面可能不够灵活,比如对于服务的多种状态、元数据等的管理可能不够完善。 而Nacos、Eureka和Consul等专门的服务注册中心和发现组件,可以在做到简单易用,并且高性能的基础上,还能提供一些特色的功能,比如健康检查、负载均衡、流量控制等等。

March 22, 2026 · 1 min · santu

Zookeeper如何保证数据的一致性?

典型回答 zk是一个非常典型的CP的系统,在下面这篇文章中阐述过ZK的AP特性。 ✅Zookeeper是CP的还是AP的? 作为一个分布式一致性协调组件,他的主要目标就是保证数据一致性。**他主要的实现原理就是通过ZAB算法来实现强一致性。**ZAB算法是ZooKeeper 自研的一种一致性协议,类似于 Paxos / Raft,但针对其“读多写少”的场景做了优化。 ZAB的核心思想: 所有 写操作都由 Leader 节点处理并广播给所有 Follower。 所有节点按相同顺序接收并应用写操作,保证数据一致。 一次写操作必须获得过半节点(Quorum)确认才能提交。 ZooKeeper 通过 ZAB 协议 + Leader单节点写入 + Leader选举机制 + 多数写入确认 + 日志快照机制,确保分布式节点间的强一致性(顺序一致性),即所有节点在任意时刻看到的都是相同的数据状态。 写入(顺序)一致性保障 首先,zk规定了所有的所有的 create, setData, delete 等写请求,都会先发到 Leader。Leader会分配全局唯一的事务 ID(zxid),并广播给 Follower。只有当 超过半数节点写成功 后,才算提交成功。保证了全局写入顺序。 ✅Zookeeper是如何保证创建的节点是唯一的? 所有 Follower 节点只能处理读请求。写入完成后,所有节点的数据是完全一致的。如果客户端向 Follower 读数据,默认读取的是已提交状态(不强制最新,但始终是一致的)。 ZooKeeper 的节点(ZNode)版本号 version、zxid 是内置的。可以基于版本号进行原子更新,防止并发写冲突。 Leader选举机制 ✅Zookeeper是选举机制是怎样的? 在发生故障或重启时,节点间会进行 Leader 选举(基于 epoch + zxid)。选出数据最全的节点作为Leader,其他节点回滚或追赶日志,与 Leader 同步后再参与投票。系统进入一致状态后才对外服务**。** 持久化和日志机制 zk的所有事务操作都会持久化到事务日志。数据也会周期性快照到磁盘。节点重启后通过日志恢复,保证崩溃恢复后仍一致。

March 22, 2026 · 1 min · santu

留言给博主