赞
踩
总的来说,Zookeeper 是一个开源的分布式的,为分布式应用提供协调服务的 Apache 项目。
具体来说,Zookeeper是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生了变化,Zookeeper 就负责通知已经在 Zookeeper 上注册的那些观察者做出相应的反应。
Zookeeper = 文件系统 + 通知机制。
(1)Zookeeper是由一个领导者(Leader)和多个跟随者(Follower)组成的集群。
(2)集群中只要有半数以上节点存活,Zookeeper 集群就能正常服务。
(3)全局数据一致性:每个 Server 保存一份相同的数据副本,Client 无论连接到哪个 server,数据都是一致的。
(4)更新请求 顺序性 ,来自同一个 Client 的更新请求按其发送顺序依次执行。
(5)数据更新原子性,一次数据更新要么成功,要么失败(保证了数据一致性)。
(6)实时性,在一定时间范围内,Client 能读到最新数据。
(1)统一命名服务:在分布式环境下,经常需要对服务进行统一命名,便于识别,例如 ip 地址。
(2)统一配置管理:在一个集群中,要求所有节点的配置信息是一致的
(3)统一集群管理:在一个集群中,需要实时监控每个节点的状态变化
(4)负载均衡:在Zookeeper中记录每个服务器的访问次数,再次请求的时候,让访问次数最少得服务器去处理当前的请求。
ZooKeeper最重要的功能之一是提供分布式系统的协调和管理服务,它能够协调分布式系统中各个节点的状态,维护分布式系统的配置信息,帮助分布式系统实现同步和通信。
选举机制总原则:集群中的每台机器都参与投票,通过交换选票信息得到每台机器的最终得票, 一旦出现得票数超过机器总数 一半以上 数量,当前机器即为 leader。
以一个简单的例子来说明整个选举的过程。
假设有五台服务器组成的 Zookeeper 集群,它们的 id 从 1-5,同时它们都是最新启动的,也就是没有历史数据,在存放数据量这一点上,都是一样的。假设这些服务器依序启动,来看看会发生什么。
(1)服务器 1 启动,发起一次选举。服务器 1 投自己一票。此时服务器 1 票数一票,不够半数以上(3票),选举无法完成,服务器 1 状态保持为LOOKING;
(2)服务器2启动,再发起一次选举。服务器 1 和 2 分别投自己一票并交换选票信息:此时服务器 1 发现服务器2的 ID 比自己目前投票推举的(服务器1)大,更改选票为推举服务器2。此时服务器 1 票数 0 票,服务器 2 票数 2 票,没有半数以上结果,选举无法完成,服务器1,2 状态保持 LOOKING;
(3)服务器 3 启动,发起一次选举。此时服务器 1 和 2 都会更改选票为服务器 3。此次投票结果:服务器1为0票,服务器2为0票,服务器 3 为 3 票。此时服务器 3 的票数已经超过半数,服务器 3 当选 Leader。服务器 1,2 更改状态为 FOLLOWING,服务器3更改状态为LEADING;
(4)服务器 4 启动,发现当前集群已经有 Leader,它自己自动成为 Follower;
(5)服务器5启动,同服务器 4一样。
当集群中的leader挂掉,集群会重新选出一个leader,此时首先会比较每一台机器的epoch,epoch大的直接选举为leader,epoch若是相同就比较每一台机器的事务id(zxid),zxid 最大的被选为 leader。极端情况,zxid 都相等的情况,那么就会直接比较服务器id(myid、sid)。
在 Zookeeper 集群中,epoch 是用来标识 Zookeeper 集群中的逻辑时期(epoch)。每当选举出一个新的 Leader 时,Zookeeper 集群的 epoch 就会增加,以标识当前的 Leader 任期。
(1)首先要有一个 main() 线程
(2)在 main() 线程中创建 ZooKeeper 客户端,这时就会创建两个线程,一个负责网络连接通信(connet),一个负责监听(listener)
(3)客户端通过 connet 线程将注册的监听事件发送给服务端
(4)在 ZooKeeper 的注册监听器列表中将注册的监听事件添加到列表中
(5)ZooKeeper 监听到有数据或路径的变化,就会将这个消息发送给 listener 线程
(6) 客户端 listener 线程内部调用 process() 方法做出相应处理
(1)因为 zookeeper 中只要有半数以上的机器正常工作,那么整个集群对外就是可用的。比如说如果有 2 个 zookeeper,那么只要 1 个死了 zookeeper 就不能用了,因为 1没有过半,那么 zookeeper 的死亡容忍度为 0,同理,如果有 3 个 zookeeper,如果死了 1个,还剩2个
正常,还是过半的,所以 zookeeper 的死亡容忍度为 1,我之前算过 4 个5 个 6 个等情况下的死亡容忍度,发现了一个规律,2n 和 2n-1 的容忍度是一样的,所以为了节约资源,就选择奇数台。
(2)防止因为集群脑裂造成集群用不了。比如有 4 个节点,脑裂为 2 个小集群,都为 2 个节点,这时候,不能满足半数以上的机器正常工作,因此集群就不可用了,那么当有 5 个节点的时候,脑裂为 2 个小集群,分别为2和 3,这时候 3 这个小集群仍然可以选举出 leader,因此集群还是可用的。
(1)部署方式
(2)zookeeper有三种角色:
(3)集群最少需要机器数:3,集群规则为2N+1台,N>0
(1) ls
:查看当前 znode 的子节点
(2)create
:创建节点
(3)set
:设置节点的值
(4) get
:获取节点的值
(5) stat
:查看节点的状态
(6) delete
:删除节点
(7) deleteall
:递归删除节点
ZooKeeper的目录结构采用类似Unix文件系统的树形结构。ZooKeeper 目录结构由 ZNode 组成,每个ZNode 默认情况下最多可以存储 1MB 的数据。ZNode是ZooKeeper中的基本数据单元,可以用于存储配置信息、状态信息等。
ZooKeeper目录结构的根节点为/,所有的ZNode都是以根节点为基础进行构建的。每个ZNode的名称是唯一的,并且可以包含多个子节点,每个子节点都是一个独立的ZNode。ZNode可以是永久节点,也可以是临时节点。
在ZooKeeper目录结构中,常用的ZNode包括:
分布式系统有三个指标:
分布式系统无法同时满足这三个指标,这个结论就是 CAP 理论。
Zookeeper 符合一致性、分区容错性。(CP)
Paxos 算法:一种基于消息传递且具有高度容错性的一致性算法。
Paxos 算法解决的问题:如何快速正确的在一个分布式系统中对某个数据的值达成一致,并且保证不论发生任何异常,都不会破坏整个系统的一致性。
在一个 Paxos 系统中,首先将所有的节点划分为Proposer(提议者)、Accepter(接受者)和 Learner(学习者)。(注意每个节点都可以身兼数职)
一个完整的 Paxos 算法流程分为三个阶段:
依赖了 ZAB 协议,ZAB 协议借鉴了 Paxos 算法,是专门为 ZooKeeper 设计的支持崩溃恢复的原子广播协议。Paxos 算法中采用多个Proposer 会存在竞争 Acceptor 的问题,ZooKeeper 设计为只有一个 Leader 负责处理外部的写事务请求,然后 Leader 将数据同步到其他 Follower 节点。即,ZooKeeper 只有一个 Leader 可以发起提议。
ZAB 协议包括两种基本的模式:消息广播(正常)、崩溃恢复(异常)。
这两个模式是相辅相成的,消息广播模式就是 Zookeeper 不出现任何问题,并且正常工作的模式,崩溃恢复看字面意思就是当 Zookeeper 出现故障时用于恢复的。
(1)消息广播
(2)崩溃恢复
相同点:
不同点:
ZAB(ZooKeeper Atomic Broadcast) 用来构建高可用的分布式数据主备系统(Zookeeper),Paxos 是用来构建分布式一致性状态机系统。而 Paxos 算法与 ZAB 协议不同的是,Paxos 算法的发起者可以是一个或多个。当集群中的 Acceptor 服务器中的大多数可以执行会话请求后,提议者服务器只负责发送提交指令,事务的执行实际发生在 Acceptor 服务器。这与 ZooKeeper 服务器上事务的执行发生在 Leader 服务器上不同。Paxos 算法在数据同步阶段,是多台 Acceptor 服务器作为数据源同步给集群中的多台 Learner 服务器,而 ZooKeeper 则是单台 Leader 服务器作为数据源同步给集群中的其他角色服务器。
注意:ZAB是在Paxos的基础上改进和演变过来的。
在分布式环境中,有些业务逻辑只需要集群中的某一台机器进行执行,其他的机器可以共享这个结果,这样可以大大减少重复计算,提高性能,于是就需要主节点。
ZooKeeper提供了一种心跳机制,即每个节点都会定期向其他节点发送心跳消息,如果一个节点超过一定时间没有收到其他节点的心跳消息,就会判定这个节点已经下线了。
心跳机制
ZooKeeper 服务器有四种工作状态:
(1)文件系统
(2)通知机制
ZooKeeper 不会自动进行日志清理,需要运维人员进行日志清理
(1)2888:Follower与Leader交换信息的端口
(2)3888:万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口
zk的负载均衡是可以调控,nginx只是能调权重,其他需要可控的都需要自己写插件;但是nginx的吞吐量比zk大很多,应该说按业务选择用哪种方式。
脑裂通常会出现在集群环境中,当集群中出现故障(比如网络故障),分成了“两个集群”,这两个集群无法互相通信,此时就会让集群觉得Leader挂了,这时候就会出现两个Leader节点,这就是脑裂。
实际上Zookeeper集群中是不会出现脑裂问题的,而不会出现的原因就跟过半机制有关。有了过半机制,对于一个Zookeeper集群,要么没有Leader,要没只有1个Leader,这样就避免了脑裂问题。
(1)Znode有两种类型:
(2)Znode有四种形式的目录节点(默认是persistent )
临时节点常用于实现分布式锁等功能,而永久节点则用于存储一些配置信息、元数据等。
ZooKeeper 中不能为临时节点创建子节点,如果需要创建子节点,应该将要创建子节点的节点创建为永久性节点
一般情况下,是客户端进程通过ZooKeeper的API在zk上注册临时节点。客户端注册的临时节点在客户端连接断开后会自动删除。
不是,一个Watch事件是一个一次性的触发器,当被设置了Watch的数据发生了改变的时候,则服务器将这个改变发送给设置了Watch的客户端,以便通知它们。
为什么不是永久的,举个例子,如果服务端变动频繁,而监听的客户端很多情况下,每次变动都要通知到所有的客户端,这太消耗性能了。在实际应用中,很多情况下,我们的客户端不需要知道服务端的每一次变动,我只要最新的数据即可。
可以分为两种情况,一是将写入请求直接发送给 leader ,一是将写入请求发给 follower(该情况也会将写入请求转发给 leader)。
(1)客户端会向ZK集群中的一台机器server1发送写数据的请求。
(2)server1接收到请求后,马上会通知leader 有写数据的请求来了
(3)leader拿到请求后,进行广播,让集群每一台机器都准备要写数据
(4)集群中的所有机机器接收到leader广播后都回应一下leader
(5) leader再次进行广播 开始写数据,其他机器接收到广播后也开始写数据
(6)数据成功写入后,回应leader,最后由leader来做整个事务提交
(7)当数据成功写入后,有最初和客户端发生连接的 server1 回应客户端数据写入成功。
(1)首先 zookeeper 集群接收到获取锁的请求时,就会在 locks 节点下创建一个临时顺序节点。
(2)然后先对当前节点下的所有子节点进行排序,判断自己是不是最小的节点,如果是,就可以获取到锁,如果不是,就说明锁已被其他客户端获取,然后可以对前一个节点进行监听,等待客户端把自己创建的节点删除。
(3)获取到锁后,进行业务的处理,释放锁的时候删除该临时节点,然后后面的节点就会接收到通知。
当一个Hadoop集群中的Active NameNode连接不上ZooKeeper时,它会尝试在一段时间内重新连接ZooKeeper。如果在此期间内,Active NameNode仍然无法连接到ZooKeeper,会直接转为standby。
(1)内存中(DataTree、DataNode、ZKDatabase):ZooKeeper 会将一部分数据存储在内存中,以提高读取速度和性能。
(2)磁盘上的快照文件:ZooKeeper 会定期将内存中的数据持久化到磁盘上的快照文件中,以便在重启后恢复状态。
(2)事务日志:ZooKeeper 会将所有更新操作记录在事务日志中,以确保数据的持久性和一致性。
(1)Hadoop HA:配置高可用
(2)HBase:保证master的高可用、RegionServer 的监控、元数据的入口以及集群配置的维护等工作。
(3)Kafka:controller的选举、broker 的注册、topic 的注册
在HDFS中实现高可用,需要使用Zookeeper来协调选举NameNode的过程。具体来说,我们需要启动两个NameNode,一个作为Active节点,一个作为Standby节点。同时,在Zookeeper上创建一个znode,作为一个lock的作用,来确保只有一个NameNode能够成为Active节点。
在启动时,Active节点会尝试去Zookeeper上创建这个lock,如果成功,则表示它已经成为Active节点,否则它会监视这个lock的状态,一旦该节点被释放,它就会重新尝试去获得这个lock。同时,Standby节点也会监视这个lock的状态,一旦Active节点出现故障或宕机,它会尝试去获得这个lock,并成为Active节点。
当Active节点宕机时,Standby节点会检测到这个故障,然后会尝试去获取这个lock。在获取到这个lock之后,它会启动自己的NameNode服务,并且接管原来Active节点的工作。
在整个过程中,Zookeeper起到了协调的作用,它可以保证只有一个NameNode节点被选举为Active节点,保证了系统的高可用性。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。