文章目录
- 简单介绍Zookeeper
- Zookeeper是如何保证事务的顺序一致性的
- Zookeeper是如何选取主leader的
- 为什么Zookeeper集群的数目一般为奇数个?
- zk的节点类型。
- zookeeper是否支持动态进行机器扩容
- 创建的临时节点什么时候会被删除
- 客户端如何正确处理CONNECTIONLOSS(连接断开) 和 SESSIONEXPIRED(Session 过期)两类连接异常
- ZooKeeper 集群中服务器之间是怎样通信的
- 能否收到每次节点变化的通知
- zk是如何持久化的?讲一下 ZooKeeper 的持久化机制
- zk实现分布式锁
- zk的监听原理是什么
- ZK写数据流程
- 说说 ZooKeeper 一般都有哪些使用场景?
- 描述一下 ZAB 协议
- ZAB 和 Paxos 算法的联系与区别
- Zookeeper 是如何解决脑裂问题的
- 说说 Zookeeper 的 CAP 问题上做的取舍
- Zookeeper脑裂是什么原因导致的
- Zookeeper 对节点的 watch 监听通知是永久的吗
- Zookeeper 的通知机制是什么
- zk 节点宕机如何处理
- Zookeeper 是如何保证事务的顺序一致性的
- zk集群数据是如何同步的
简单介绍Zookeeper
Zookeeper是一个开源的分布式应用程序协调服务,在业内很多中间件都有使用,比如Kafka、Dubbo等知名框架。很多技术都是使用动物命名的,如Hive(蜜蜂)、Hadoop(小象)、Tomcat猫,而Zookeeper是动物园饲养员的意思,就是管理这些动物的。
zk是一个强一致性的服务,所有的请求都需要通知到半数以上的服务器同意,才会具体的执行。
在使用场景上,
- 用作注册中心,如Dubbo、Kafka等的注册中心。
- 用作集群管理,故障情况可协助选举主服务器。
- zk可以用作配置中心,所有配置的变更可以通过zk的观察者模式同步到每个客户端。
- 用作分布式锁,可以实现公平锁的能力,通过Curator封装的可重入锁实现可以快速使用zk锁。
- 用作分布式调度服务框架的服务器,例如tbschedule,使用zk来分发任务。
Zookeeper是如何保证事务的顺序一致性的
zk采用递增的事务zxid来标识,所有的proposal都在被提出的时候加上了zxid,zxid是一个32位epoch+32位递增计数的64位数字。当新proposal产生时,会依据数据库两阶段提交过程,首先会向其他的Server发出事务执行请求,如果超过半数的机器都能执行并且都能成功,那么就开始执行。
Zookeeper是如何选取主leader的
phase0~3:选举、发现、同步、广播
快速选举:
Fast Leader Election:快速选举leader,每个人都选举自己并广播。
Recovery Phase:根据lastZxid决定如何同步数据。
Broadcast:leader对外进行消息广播,提供事务,有新节点加入时需要同步数据。
参考《Zookeeper 集群中是怎样选举leader的》
为什么Zookeeper集群的数目一般为奇数个?
Zookeeper集群的数目一般为奇数个,主要是出于以下两方面的考虑:
- 防止脑裂:如果Zookeeper集群的节点数为偶数个,那么在集群发生脑裂并分成两个均等子集群的情况下,可能导致整个Zookeeper集群都无法正常工作。而如果集群节点数为奇数个,则即使发生脑裂并分成两个子集群,每个子集群都至少会有一个节点可以正常工作,从而保证集群的可用性。
- 便于选举:在Zookeeper集群中,需要选出一个新的leader。在奇数个节点的情况下,当节点数量的一半比另一半多1时,多的那个节点就可以作为投票箱中的一票,确保了选举过程的顺利进行。如果节点数为偶数个,可能会出现半数以上节点与另一半节点投票结果不一致的情况,增加选举的复杂性。
因此,为了确保Zookeeper集群的稳定性和可用性,通常采用奇数个节点。
zk的节点类型。
临时节点、临时有序节点、永久节点、永久有序节点
zookeeper是否支持动态进行机器扩容
zk的3.4.3版本还不支持动态扩容,但3.5.0版本后已经支持。
创建的临时节点什么时候会被删除
临时节点在client连接断开时不会马上删除,只有session_expired的时候,会把这个会话创建的临时数据移除。因此临时节点也不允许创建子节点。
客户端如何正确处理CONNECTIONLOSS(连接断开) 和 SESSIONEXPIRED(Session 过期)两类连接异常
zk的client与server维持着一个长链接,client会定时向服务器发送heart beat,更新服务器上session_timeout。在session_timeout时间范围内,连接断开,客户端会自动连接上新的zk机器,如果一直连不上,超时了,服务端会删除这个过期的session,客户端需要手动删除这个过期的session并重连。
ZooKeeper 集群中服务器之间是怎样通信的
ZooKeeper集群中的服务器之间使用TCP协议进行通信,Leader和每一个Follower/Observer服务器都建立TCP连接,同时为每个F/O都创建一个叫LearnerHandler的实体,LearnerHandler主要负责Leader与F/O之间的网络通信,包括数据同步、请求转发、Proposal提议的投票等。Leader服务器保存了所有F/O的LearnerHandler。这个通信过程包括以下关键部分:
- Leader和Follower:在ZooKeeper集群中,有一个服务器被选为领导者(Leader),其余服务器成为跟随者(Follower)。Leader负责处理所有客户端请求,而Followers主要用于接收Leader的数据更新。
- 通信机制:每个服务器创建TCP连接,使用LearnerHandler实体来处理与其他服务器的网络通信。LearnerHandler的主要职责是接收来自其他服务器的数据更新,并将其传递给应用程序。
- 客户端请求:客户端通过ZooKeeper客户端库连接到集群中的任一服务器,并向其中一个服务器发送请求。该服务器会将请求传递给Leader或直接处理请求。
- 数据同步:Leader负责处理客户端请求,并将数据更新广播给所有Followers。Followers会应用这些更新以保持数据一致性。
- 故障处理:如果Leader服务器发生故障,ZooKeeper使用选举机制来选举新的Leader,以确保集群的高可用性。
总之,ZooKeeper的通信原理是基于客户端/服务器模型的,客户端发送请求,服务器接收和处理请求,然后返回响应。这个通信过程确保了ZooKeeper集群中数据的一致性和高可用性。
能否收到每次节点变化的通知
如果节点数据更新频率很高的话,不能。
原因:Watches通知是一次性的,当一次数据修改,通知客户端,客户端再次注册watch,在这个过程中,数据发生了修改便不会通知到客户端。
zk是如何持久化的?讲一下 ZooKeeper 的持久化机制
Zookeeper虽然是内存数据库,但为了保证高可靠性,其同时提供了持久化功能,通过快照和事务日志将数据保存在磁盘中.
Zookeeper的持久化机制主要涉及两种数据存储方式:内存存储和磁盘存储。
- 内存存储:这是Zookeeper默认的数据存储方式。在内存存储中,Zookeeper将所有数据保存在内存中,而不是磁盘上。当Zookeeper关闭或发生故障时,内存中的数据会丢失。为了提高性能,Zookeeper采用了延迟写盘的策略,即将数据先写入内存,再异步地写入磁盘。这种方式可以减少磁盘I/O操作,提高系统的响应速度。
- 磁盘存储:为了解决内存存储数据丢失的问题,Zookeeper提供了磁盘存储的持久化方式。在磁盘存储中,Zookeeper将数据保存在磁盘上,并在启动时从磁盘加载数据。为了提高写入性能,Zookeeper采用了两种机制:快照(snapshot)和事务日志(transaction log)。快照是Zookeeper数据树的一个完整拷贝,而事务日志记录了所有的数据更改操作。通过这两种机制,Zookeeper可以在系统故障时恢复数据。
Zookeeper的持久化机制可以根据实际需求进行选择和配置。对于需要高可用性和实时性的场景,可以选择内存存储;对于需要更可靠性和可恢复性的场景,可以选择磁盘存储。
zk实现分布式锁
顺序发号器: ZooKeeper的每一个节点,都是自带顺序生成器:在每个节点下面创建临时节点,新的子节点后面,会添加一个次序编号,这个生成的编号,会在上一次的编号进行 +1 操作
有序递增: ZooKeeper节点有序递增,可以保证锁的公平性,我们只需要在一个持久父节点下,创建对应的临时顺序节点,每个线程在尝试占用锁之前,会调用watch,判断自己当前的序号是不是在当前父节点最小,如果是,那么获取锁
Znode监听: 每个线程在抢占锁之前,会创建属于当前线程的ZNode节点,在释放锁的时候,会删除创建的ZNode,当我们创建的序号不是最小的时候,会等待watch通知,也就是上一个ZNode的状态通知,当前一个ZNode删除的时候,会触发回调机制,告诉下一个ZNode,你可以获取锁开始工作了
临时节点自动删除:ZooKeeper还有一个好处,当我们客户端断开连接之后,我们所创建的临时节点会进行自动删除操作,所以我们在使用分布式锁的时候,一般都是会去创建临时节点,这样可以避免因为网络异常等原因,造成的死锁。
羊群效应: ZooKeeper节点的顺序访问性,后面监听前面的方式,可以有效的避免 羊群效应,什么是羊群效应:当某一个节点挂掉了,所有的节点都要去监听,然后做出回应,这样会给服务器带来比较大压力,如果有了临时顺序节点,当一个节点挂掉了,只有它后面的那一个节点才做出反应。
参考:ZK(ZooKeeper)分布式锁实现
zk的监听原理是什么
ZK写数据流程
说说 ZooKeeper 一般都有哪些使用场景?
- 分布式协调:这个其实就是 zk 很经典的一个用法,Zookeeper 可以为分布式系统中的各个参与者提供一个协调器,处理各种协调操作,例如任务分配、等待与通知等。简单来说,就好比,你系统 A发送个请求到 mq,然后 B消费了之后处理。那 A系统如何知道 B系统的处理结果?用 zk 就可以实现分布式系统之间的协调工作。A系统发送请求之后可以在 zk 上对某个节点的值注册个监听器,一旦 B系统处理完了就修改 zk 那个节点的值,A立⻢就可以收到通知,完美解决。
- 分布所锁:对某一个数据联系发出两个修改操作,两台机器同时收到请求,但是只能一台机器先执行另外一个机器再执行,那么此时就可以使用 zk 分布式锁,一个机器接收到了请求之后先获取 zk 上的一把分布式锁,就是可以去创建一个 znode,接着执行操作,然后另外一个机器也尝试去创建那个 znode,结果发现自己创建不了,因为被别人创建了,那只能等着,等等一个机器执行完了自己再执行。
- 配置信息管理:zk 可以用作很多系统的配置信息的管理,发布者将数据发布到 ZooKeeper 节点上,供订阅者动态获取数据,实现配置信息的集中式管理和动态更新。比如 kafka,storm 等等很多分布式系统都会选用 zk 来做一些元数据,配置信息的管理,包括 dubbo 注册中心不也支持 zk么。
- HA高可用性:这个应该是很常⻅的,比如 hdfs,yarn 等很多大数据系统,都选择基于 zk 来开发 HA高可用机制,就是一个重要进程一般会主备两个,主进程挂了立⻢通过 zk 感知到切换到备份进程。
- 集群管理:Zookeeper 可以帮助构建分布式系统,提供集群管理的功能,包括节点监控、异常处理、状态同步等。
- 命名服务:Zookeeper 可以作为一个分布式命名服务,为网络中的对象提供唯一的名称。
描述一下 ZAB 协议
ZAB协议(Zookeeper Atomic Broadcast)是Zookeeper中用于实现分布式一致性的协议。该协议旨在确保分布式系统中的数据一致性和可靠性,并具有以下特点:
- 支持崩溃恢复和消息广播:ZAB协议能够在Leader节点崩溃或因其他原因导致Leader缺失时,自动进入崩溃恢复模式,重新选举Leader节点,并继续进行消息广播。
- 原子性保证:ZAB协议确保消息的原子性,即所有的事务请求都会被成功执行或全部失败回滚,不会出现部分成功的情况。
- 一致性保证:ZAB协议通过多副本同步和消息广播机制,确保所有节点数据的一致性,避免数据不一致导致的系统故障。
ZAB协议包括三个阶段:
- 准备阶段(Prepare):Leader节点准备数据并通知所有Follower节点。
- 确认阶段(Confirm):Follower节点接收准备消息并准备自己所在的服务,并回复确认消息。
- 广播阶段(Broadcast):Leader节点将数据广播给所有Follower节点。
如果在确认阶段,Follower节点没有收到确认消息,那么会进入崩溃恢复模式,重新选举Leader节点。ZAB协议是实现分布式一致性和协调服务的核心协议之一。
ZAB 和 Paxos 算法的联系与区别
ZAB(ZooKeeper Atomic Broadcast)算法和Paxos算法都是分布式系统中用于实现数据一致性的算法。
两者的主要联系在于它们都采用了类似领导者的选举机制,通过多数派的投票来保证系统的稳定性。在ZAB中,这体现在它使用了一种类似于Paxos的领导者选举过程,其中有一个领导者(leader)来协调多个跟随者(follower)的操作。而在Paxos中,一个提案需要被大多数的进程接受并返回结果,才能被确定。
两者的区别在于它们的目标和实现方式不同:
- 目标:ZAB算法是为了构建一个高可用的分布式数据主备系统(如ZooKeeper),而Paxos算法则是为了构建一个分布式一致性状态机系统。
- 实现方式:ZAB算法使用了消息广播的方式来实现分布式系统的协调,它要求每个消息都必须得到大多数节点的反馈才能确认,从而确保消息的一致性。同时,ZAB算法还引入了一个重要的概念,即消息的epoch,用来保证在领导者出现故障时,能够正确地选择新的领导者。Paxos算法则更加通用,它可以处理更广泛的一致性问题,而不仅仅是消息广播。然而,Paxos算法的实现较为复杂,因为它需要处理多种可能的情况,包括领导者故障、消息丢失等。
综上所述,ZAB和Paxos的联系在于采用了领导者的选举机制和多数派的投票原则,而区别在于它们的目标和实现方式不同。
Zookeeper 是如何解决脑裂问题的
Zookeeper的解决方案是通过
过半机制
来避免脑裂问题的发生。
具体来说,在Zookeeper的领导者选举过程中,如果某台ZookeeperServer获得了超过半数的选票,则此ZookeeperServer就可以成为Leader。举个简单的例子,如果现在集群中有5台ZookeeperServer,那么过半数就是2.5,也就是说,领导者选举的过程中至少要有三台ZookeeperServer投了同一个ZookeeperServer,才会选出来一个Leader。
过半机制中是大于而不是大于等于,这是为了减少脑裂的概率,假设现在有一个由6台zkServer所组成的一个集群,部署在了两个机房,每个机房都有3台zkServer,那么如果机房之间的网络断了之后,两个机房内的zkServer还是可以相互通信的,如果不考虑过半机制,那么就会出现每个机房内部都将选出一个Leader。
因此,Zookeeper通过过半机制来保证在发生脑裂问题时,集群仍然能够正常工作,避免因为脑裂问题导致集群失效的问题。
说说 Zookeeper 的 CAP 问题上做的取舍
Zookeeper 在 CAP 问题上选择了 CP,也就是说,在一致性和可用性之间,Zookeeper 选择了
强一致性
。
Zookeeper 是一个分布式协调服务,它的主要职责是维护整个系统的状态,并提供一致性的服务。因此,为了保证数据的一致性,Zookeeper 必须确保在分布式节点之间进行同步的时候,不能出现不一致的情况。这就意味着,在出现网络故障或者消息丢失的情况下,Zookeeper 不能牺牲用户的体验,也就是不能出现部分节点可用而部分节点不可用的情况。
然而,这并不意味着 Zookeeper 完全牺牲了可用性。尽管它选择了一致性优先的策略,但它还是通过一些机制来尽可能地提高可用性。例如,它允许客户端在多个服务器之间进行备份,以防止单个服务器故障导致服务不可用。此外,它还提供了实时性和持久性的选择,以满足不同应用场景的需求。
总的来说,Zookeeper 在 CAP 问题上的取舍是为了保证数据的一致性,虽然在一定程度上牺牲了可用性,但通过一些机制尽可能地提高服务的可用性。
Zookeeper脑裂是什么原因导致的
Zookeeper脑裂是指一个集群环境中出现了多个Master节点,导致数据不一致和数据问题。这种情况通常发生在网络故障导致集群中部分节点失去与Master节点的连接,而在这些节点看来,Master节点已经失效,因此它们会选举新的Master节点。在这个过程中,可能会出现多个Master节点,导致脑裂问题。
脑裂问题的主要原因是网络环境不稳定和假死现象。例如,当集群中的部分节点由于网络原因无法连接到Master节点时,这些节点会认为Master节点已经失效,从而发起新的选举。然而,如果网络不稳定,可能会出现Master节点重新进入集群的情况,导致出现多个Master节点。
解决Zookeeper脑裂问题的方法包括:
- 增加网络稳定性,避免网络故障导致的问题。
- 调整Zookeeper集群的选举机制和超时设置,使其更适应网络环境和集群架构。
- 及时发现并处理多个Master节点,避免数据不一致和其他问题的发生。
Zookeeper 对节点的 watch 监听通知是永久的吗
在 ZooKeeper 中,节点监视(watch)通知不是永久的,而是一次性触发。当客户端注册一个监视事件,例如监视一个节点的数据变化或子节点的变化时,如果相应的节点状态发生了变化,ZooKeeper 会通知客户端,并触发监视事件。一旦监视事件被触发,它会从客户端的监视列表中删除,客户端需要再次显式设置监视,以便继续监视节点的状态变化。这种一次性的监视通知机制有助于避免客户端在不再需要监视的情况下浪费资源。如果客户端需要持续监视节点状态的变化,它必须在每次触发监视后重新设置监视,以确保不会错过后续的变化通知。
值得注意的是,从 ZooKeeper 版本 3.5.0 开始,引入了永久监听(persistent watch)的支持。这意味着一旦触发了监听事件,除非客户端显式取消监听,否则 ZooKeeper 将持续向客户端发送通知,而不仅仅触发一次。这对于需要持续监视节点状态的情况非常有用,客户端不需要反复设置监视,可以持续接收到节点状态的变化通知。
这个改进提高了 ZooKeeper 的灵活性和适用性,允许开发人员更精细地控制监视行为,以满足不同应用场景的需求。
Zookeeper 的通知机制是什么
Zookeeper的机制可以感知某些事件的发生,并将这些事件通知给客户端。这种通知机制是异步的,也就是说,当事件发生时,Zookeeper会选择一种方式将事件通知给客户端,而不需要等待客户端的回应。
具体来说,Zookeeper允许客户端向服务端的某个Znode注册一个Watcher监听,当这个Znode的一些指定事件(如数据改变、节点删除、子节点状态变更等)发生时,Zookeeper就会通知客户端。这种Watcher机制使得Zookeeper能够实现分布式锁、发布订阅等功能。
另外,Zookeeper的机制也允许客户端在每个Znode节点上设置一个观察,如果被观察的Znode节点有变更,那么这个观察就会被触发,然后Zookeeper就会将这个观察所属的客户端接收一个通知包,告知节点已经发生了什么事件。
zk 节点宕机如何处理
Zookeeper 必须集群部署,推荐配置不少于 3 个节点。Zookeeper 自身也要保证当一个节点宕机时,其他节点会继续提供服务。
- 如果是一个 Follower 宕机,还有 2 台服务器提供访问,因为 Zookeeper 上的数据是有多个副本的,数据并不会丢失。
- 如果是一个 Leader 宕机,Zookeeper 会选举出新的 Leader。
因此,Zookeeper 可以容忍一部分节点的宕机,但前提是要保证超过一半的节点是正常工作的。在这种情况下,Zookeeper 集群仍然可以正常提供服务。如果 Zookeeper 节点挂得太多,只剩一半或不到一半节点能工作,集群就会失效。
Zookeeper 是如何保证事务的顺序一致性的
Zookeeper保证事务的顺序一致性是通过两个机制实现的:事务的严格串行化和锁定机制。
- 事务的严格串行化:在Zookeeper中,所有的写操作都必须经过一个称为“提交”(commit)的阶段。在一个事务还没有被提交之前,任何客户端都无法读取该事务。 这种机制确保了所有事务按照严格的顺序执行,保证了事务的顺序一致性。
- 锁定机制:Zookeeper使用锁定机制来保证事务的顺序一致性。在某些情况下,不同的事务可能需要访问同一个资源,这时就需要使用锁定机制来协调它们之间的访问。Zookeeper提供了两种类型的锁:共享锁和排他锁。共享锁允许多个事务同时访问同一个资源,而排他锁则阻止其他事务访问该资源。
通过以上两个机制,Zookeeper确保了事务的顺序一致性,从而保证了数据的一致性和系统的可靠性。
zk集群数据是如何同步的
Zookeeper集群的数据同步过程如下:
- 集群启动时,会先进行领导者选举,确定哪个节点是Leader,哪些节点是Follower和Observer。
- Leader会和其他节点进行数据同步,采用发送快照和发送Diff日志的方式。
- 集群在工作过程中,所有的写请求都会交给Leader节点来进行处理,从节点只能处理读请求。
- Leader节点收到一个写请求时,会通过两阶段提交机制来处理。
- Leader节点会将该写请求对应的日志发送给其他Follower节点,并等待Follower节点持久化日志成功。
- Follower节点收到日志后会进行持久化,如果持久化成功则发送一个Ack给Leader节点。
- 当Leader节点收到半数以上的Ack后,就会开始提交,先更新Leader节点本地的内存数据。
- 然后发送commit命令给Follower节点,Follower节点收到commit命令后也会更新本地内存中的数据。
这样,Zookeeper集群的数据同步就完成了。