Zookeeper基本原理
# Zookper基本原理
# 什么是ZAB协议
ZAB协议是Zookeeper⽤来实现⼀致性的原⼦⼴播协议,该协议描述了Zookeeper是如何实现⼀致性 的,分为三个阶段:
- 领导者选举阶段:从Zookeeper集群中选出⼀个节点作为Leader,所有的写请求都会由Leader节点 来处理
- 数据同步阶段:集群中所有节点中的数据要和Leader节点保持⼀致,如果不⼀致则要进⾏同步
- 请求⼴播阶段:当Leader节点接收到写请求时,会利⽤两阶段提交来⼴播该写请求,使得写请求像 事务⼀样在其他节点上执⾏,达到节点上的数据实时⼀致
但值得注意的是,Zookeeper只是尽量的在达到强⼀致性,实际上仍然只是最终⼀致性的。
# 为什么Zookeeper可以⽤来作为注册中⼼
可以利⽤Zookeeper的临时节点和watch机制来实现注册中⼼的⾃动注册和发现,另外Zookeeper中的 数据都是存在内存中的,并且Zookeeper底层采⽤了nio,多线程模型,所以Zookeeper的性能也是⽐较 ⾼的,所以可以⽤来作为注册中⼼,但是如果考虑到注册中⼼应该是注册可⽤性的话,那么Zookeeper 则不太合适,因为Zookeeper是CP的,它注重的是⼀致性,所以集群数据不⼀致时,集群将不可⽤,所 以⽤Redis、Eureka、Nacos来作为注册中⼼将更合适。
# Zookeeper中的领导者选举的流程是怎样的?
对于Zookeeper集群,整个集群需要从集群节点中选出⼀个节点作为Leader,⼤体流程如下:
- 集群中各个节点⾸先都是观望状态(LOOKING),⼀开始都会投票给⾃⼰,认为⾃⼰⽐较适合作为 leader
- 然后相互交互投票,每个节点会收到其他节点发过来的选票,然后pk,先⽐较zxid,zxid⼤者获 胜,zxid如果相等则⽐较myid,myid⼤者获胜
- ⼀个节点收到其他节点发过来的选票,经过PK后,如果PK输了,则改票,此节点就会投给zxid或 myid更⼤的节点,并将选票放⼊⾃⼰的投票箱中,并将新的选票发送给其他节点
- 如果pk是平局则将接收到的选票放⼊⾃⼰的投票箱中
- 如果pk赢了,则忽略所接收到的选票
- 当然⼀个节点将⼀张选票放⼊到⾃⼰的投票箱之后,就会从投票箱中统计票数,看是否超过⼀半的 节点都和⾃⼰所投的节点是⼀样的,如果超过半数,那么则认为当前⾃⼰所投的节点是leader
- 集群中每个节点都会经过同样的流程,pk的规则也是⼀样的,⼀旦改票就会告诉给其他服务器,所 以最终各个节点中的投票箱中的选票也将是⼀样的,所以各个节点最终选出来的leader也是⼀样 的,这样集群的leader就选举出来了
# Zookeeper集群中节点之间数据是如何同步的
- ⾸先集群启动时,会先进⾏领导者选举,确定哪个节点是Leader,哪些节点是Follower和Observer
- 然后Leader会和其他节点进⾏数据同步,采⽤发送快照和发送Diff⽇志的⽅式
- 集群在⼯作过程中,所有的写请求都会交给Leader节点来进⾏处理,从节点只能处理读请求
- Leader节点收到⼀个写请求时,会通过两阶段机制来处理
- Leader节点会将该写请求对应的⽇志发送给其他Follower节点,并等待Follower节点持久化⽇志成 功
- Follower节点收到⽇志后会进⾏持久化,如果持久化成功则发送⼀个Ack给Leader节点
- 当Leader节点收到半数以上的Ack后,就会开始提交,先更新Leader节点本地的内存数据
- 然后发送commit命令给Follower节点,Follower节点收到commit命令后就会更新各⾃本地内存数 据
- 同时Leader节点还是将当前写请求直接发送给Observer节点,Observer节点收到Leader发过来的 写请求后直接执⾏更新本地内存数据
- 最后Leader节点返回客户端写请求响应成功
- 通过同步机制和两阶段提交机制来达到集群中节点数据⼀致
# 简述zk的命名服务、配置管理、集群管理
命名服务: 通过指定的名字来获取资源或者服务地址。Zookeeper可以创建⼀个全局唯⼀的路径,这个路径就可以 作为⼀个名字。被命名的实体可以是集群中的机器,服务的地址,或者是远程的对象等。⼀些分布式服 务框架(RPC、RMI)中的服务地址列表,通过使⽤命名服务,客户端应⽤能够根据特定的名字来获取 资源的实体、服务地址和提供者信息等 配置管理: 实际项⽬开发中,经常使⽤.properties或者xml需要配置很多信息,如数据库连接信息、fps地址端⼝等 等。程序分布式部署时,如果把程序的这些配置信息保存在zk的znode节点下,当你要修改配置,即 znode会发⽣变化时,可以通过改变zk中某个⽬录节点的内容,利⽤watcher通知给各个客户端,从⽽ 更改配置。 集群管理: 集群管理包括集群监控和集群控制,就是监控集群机器状态,剔除机器和加⼊机器。zookeeper可以⽅ 便集群机器的管理,它可以实时监控znode节点的变化,⼀旦发现有机器挂了,该机器就会与zk断开连接,对应的临时⽬录节点会被删除,其他所有机器都收到通知。新机器加⼊也是类似。
# Zookeeper中的watch机制
客户端,可以通过在znode上设置watch,实现实时监听znode的变化 Watch事件是⼀个⼀次性的触发器,当被设置了Watch的数据发⽣了改变的时候,则服务器将这个改变 发送给设置了Watch的客户端
- ⽗节点的创建,修改,删除都会触发Watcher事件。
- ⼦节点的创建,删除会触发Watcher事件。
⼀次性:⼀旦被触发就会移除,再次使⽤需要重新注册,因为每次变动都需要通知所有客户端,⼀次性 可以减轻压⼒,3.6.0默认持久递归,可以触发多次
轻量:只通知发⽣了事件,不会告知事件内容,减轻服务器和带宽压⼒ Watcher 机制包括三个⻆⾊:客户端线程、客户端的 WatchManager 以及 ZooKeeper 服务器
- 客户端向 ZooKeeper 服务器注册⼀个 Watcher 监听,
- 把这个监听信息存储到客户端的 WatchManager 中
- 当 ZooKeeper 中的节点发⽣变化时,会通知客户端,客户端会调⽤相应 Watcher 对象中的回调 ⽅法。watch回调是串⾏同步的
# Zookeeper和Eureka的区别
zk:CP设计(强⼀致性),⽬标是⼀个分布式的协调系统,⽤于进⾏资源的统⼀管理。 当节点crash后,需要进⾏leader的选举,在这个期间内,zk服务是不可⽤的。
eureka:AP设计(⾼可⽤),⽬标是⼀个服务注册发现系统,专⻔⽤于微服务的服务发现注册。 Eureka各个节点都是平等的,⼏个节点挂掉不会影响正常节点的⼯作,剩余的节点依然可以提供注册和 查询服务。⽽Eureka的客户端在向某个Eureka注册时如果发现连接失败,会⾃动切换⾄其他节点,只要有⼀台Eureka还在,就能保证注册服务可⽤(保证可⽤性),只不过查到的信息可能不是最新的(不保 证强⼀致性) 同时当eureka的服务端发现85%以上的服务都没有⼼跳的话,它就会认为⾃⼰的⽹络出了问题,就不会 从服务列表中删除这些失去⼼跳的服务,同时eureka的客户端也会缓存服务信息。eureka对于服务注册 发现来说是⾮常好的选择。