Zookeeper原理解析

Zookeeper原理解析,第1张

微信公众号: Spark大数据

一、Zookeeper介绍

ZooKeeper是一种为分布式应用所设计的高可用、高性能且一致的开源协调服务,它提供了一项基本服务: 分布式锁服务 。

分布式应用可以基于它实现更高级的服务,实现诸如同步服务、配置维护和集群管理或者命名的服务。Zookeeper服务自身组成一个集群,2n+1个(奇数)服务允许n个失效,集群内一半以上机器可用,Zookeeper就可用。

假设 3台机器组成的集群,可以有允许一台失效,如果有2台失效,这个集群就不可用,1<15,一般的搭建zookeeper集群时,以奇数台机器来搭建。目的:是为了提高容错能允许多损失一台。

11 数据模型

1)ZooKeeper本质上是一个 分布式的小文件存储系统 ;

2)Zookeeper表现为一个分层的文件系统目录树结构(不同于文件系统的是,节点可以有自己的数据,而文件系统中的目录节点只有子节点), 每个节点可以存少量的数据(1M左右) 。

3)每个节点称做一个ZNode。 每个ZNode都可以通过其路径唯一标识 。

4)ZooKeeper中的 每个节点存储的数据要被原子性的 *** 作 。也就是说读 *** 作将获取与节点相关的所有数据,写 *** 作也将替换掉节点的所有数据。

5)在zookeeper创建顺序节点(create -s ),节点路径后加编号,这个计数对于此节点的父节点来说是唯一的。

/app/

/s100000000001

/s100000000002

6)ZooKeeper中的节点有两种,分别为 临时节点和永久节点 。节点的类型在创建时即被确定,并且不能改变。

① 临时节点 :在客户端用create -e创建,该节点的生命周期依赖于创建它们的会话。一旦会话(Session)结束,临时节点将被自动删除,当然可以也可以手动删除。虽然每个临时的Znode都会绑定到一个客户端会话,但他们对所有的客户端还是可见的。另外,ZooKeeper的临时节点不允许拥有子节点。

② 永久节点 :在客户端用create 创建,该节点的生命周期不依赖于会话,并且只有在客户端显示执行删除 *** 作的时候,他们才能被删除。

7) 客户端可以给节点设置watch,我们称之为监视器 。当节点状态发生改变时(Znode的增、删、改)将会触发watch所对应的 *** 作。当watch被触发时,ZooKeeper将会向客户端发送且仅发送一条通知。

分布式锁

zookeeper 是高可用协调流程图

12 zookeepr角色介绍

领导者(leader) ,负责进行投票的发起和决议,更新系统状态(数据同步),发送心跳。

学习者(learner) ,包括跟随者(follower)和观察者(observer)。

跟随者(follower) ,用于接受客户端请求、向客户端返回结果,在选主过程中参与投票。

观察者(Observer) ,可以接受客户端请求,会把请求转发给leader, 但observer不参加投票过程,只同步leader的状态 ,observer的目的是为了扩展系统,提高读取速度。

1)leader失效后会在follower中重新选举新的leader

2)每个follower都和leader有连接,接受leader的数据更新 *** 作

3)客户端可以连接到每个server,每个server的数据完全相同

4)每个节点的服务Server,记录事务日志和快照到持久存储

13 工作原理

Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。 Zab协议有两种模式 ,它们分别是恢复模式(选主)和广播模式(同步)。

恢复模式: 当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,恢复模式不接受客户端请求,当领导者被选举出来,且大多数Server完成了和leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。

广播模式: 一旦Leader已经和多数的Follower进行了状态同步后,他就可以开始广播消息了,即进入广播状态。这时候当一个Server加入ZooKeeper服务中,它会在恢复模式下启动,发现Leader,并和Leader进行状态同步。待到同步结束,它也参与消息广播。ZooKeeper的广播状态一直到Leader崩溃了或者Leader失去了大部分的Followers支持。

14 Zookeeper节点数据 *** 作流程

(1)写 *** 作

1)在Client向Follwer 或 Observer 发出一个写的请求;

2)Follwer 或 Observer 把请求发送给Leader;

3)Leader接收到以后向所有follower发起提案;

4)Follwer收到提案后执行写 *** 作,然后把 *** 作结果发送给Leader;

5)当多数follower返回提案结果后,leader会commit该提议,通知其他Follower 和 Observer 同步信息;

6)Follwer 或Observer把请求结果返回给Client。

(2)读 *** 作

1)在Client向Follwer 或 Observer 发出一个读的请求;

2)Follwer 或 Observer 把请求结果返回给Client;

15 主要特点

最终一致性 :client不论连接到哪个Server,展示给它都是同一个视图,这是zookeeper最重要的特性;

可靠性 :具有简单、健壮、良好的性能,如果消息被某一台服务器接受,那么它将被所有的服务器接受;

实时性 :Zookeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。但由于网络延时等原因,Zookeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口;

等待无关(wait-free) :慢的或者失效的client,不得干预快速的client的请求,使得每个client都能有效的等待;

原子性 :更新只能成功或者失败,没有中间状态;

顺序性 :按照客户端发送请求的顺序更新数据。

16 zookeepr应用场景

161 数据发布与订阅

发布与订阅即所谓的配置管理,顾名思义就是将数据发布到ZK节点上,供订阅者动态获取数据,实现配置信息的集中式管理和动态更新。

应用配置集中到节点上,应用启动时主动获取,并在节点上注册一个watcher,每次配置更新都会通知到应用。

162 命名空间服务  分布式命名服务,创建一个节点后,节点的路径就是全局唯一的,可以作为全局名称使用。

163 分布式通知/协调

不同的系统都监听同一个节点,一旦有了更新,另一个系统能够收到通知。

164 分布式锁

Zookeeper能保证数据的强一致性,用户任何时候都可以相信集群中每个节点的数据都是相同的。锁的两种体现方式:

(1)保持独占

一个用户创建一个节点作为锁,另一个用户检测该节点,如果存在,代表别的用户已经锁住,如果不存在,则可以创建一个节点,代表拥有一个锁。

(2)控制时序

有一个节点作为父节点,其底下是带有编号的子节点,所有要获取锁的用户,需要在父节点下创建带有编号的子节点,编号最小的会持有锁;当最我号的节点被删除后,锁被释放,再重新找最我号的节点来持有锁,这样保证了全局有序。

165 集群管理

每个加入集群的机器都创建一个节点,写入自己的状态。监控父节点的用户会收到通知,进行相应的处理。离开时删除节点,监控父节点的用户同样会收到通知。

共4239字,阅读需要15分钟

Zookeeper作为Dubbo生态的默认注册中心,得到了非常的普遍的应用,虽然后来阿里又出了nacos,但是不可否认的是ZK仍然是一款非常优秀的开源产品,非常优秀的注册中心备选方案。

ZK有很多特性,本篇文章主要介绍ZK的选主过程(后宫佳丽三千,我就独宠你一人)

要说选主的过程,我们首先得了解ZK到底有哪些节点,这些节点充当得角色是什么?

ZK本身得节点主要分为三类:

Leader:主要是负责数据的写入,如果超过半数同意,那么就广播进行写入;

Follower:主要负责查询请求并将写入请求发送给leader,参与选举和写入投票;

Observe:也是负责查询请求并将写入请求发送给leader,不参加投票,只被动接收结果

获取半数投票以上的节点成为leader节点。

万事万物都有一个准则,好的比较坏的,坏的比较更坏的,世上本没有痛苦,痛苦都是自己寻找的结果,海燕你可长点心吧,哎呀跑偏了。

ZK比较的时候有三个指标或者三个维度:

(1)任期

(2)事务ID(ZK中的事务ID)

(3)节点编号(集群中每个节点的编号)

根据以上三个指标就可以说出最终的结论了:选择任期大的,任期一样选择事务ID大的,前两个都一样,选择节点编号大的。

就这么简单?是的。规则就是这么简单,但是源码还是有那么一丢丢的绕。

源码看着相对比较枯燥,但是作为一个手艺人,怎么能不去了解怎么做的呢,我们先来梳理一下代码的流程,方便更好的看第四部分内容。

节点先投自己一票,然后进行广播

节点内部循环进行消息接收

收到消息后

如果消息为空,就进行重新发送消息或者建立连接

如果消息不为空,且消息接收者和投票的leader都是合法节点就进行下边步骤。

如果节点为looking节点

根据当前节点的投票和接收到的投票进行比较来决定是否需要再次发送投票并且记录投票的结果

每次都判断记录的票数,如果过半就进行节点状态的设置

选主的逻辑是在lookForLeader开始的,像金字塔的第一块砖一样,我们先看ZK选主的第一块砖lookForLeader,第一次看源码得时候一定要把握主线,忽略从线,等主线完全理清楚了之后才去处理从线,要不会陷入迷宫之中。

下边就是主要的投票代码,看里边的注释:

更新投票或者投票的方法为:

发送通知的方法为:

待到山花烂漫时,她在丛中笑,消息都已经发完了,肯定就到了接收到选票的时候应该怎么 *** 作了,接收选票的代码也是在lookForLeader中:

接上代码继续讨论,校验发送投票节点的状态,我们从本文的第一章节知道Observe节点是不参与投票的,只是转发写请求和被动接收数据,负责查询请求,所以从代码中我们也可以看出来:

当发送投票的节点状态是FOLLOWING和LEADING时,代表发送节点已经选举完成,所以处理方法的逻辑都是一样滴,这部分限于篇幅太长,暂时就不深入讨论了,感兴趣的朋友可以私信我或者加我微信号M_P_E_D进行交流和沟通。

终于到重头戏了,咱们看看LOOKING状态时的代码:

我们先把totalOrderPredicate方法放前边,这个其实就是选举leader的规则的实现。

道阻且长,行则将至,行而不辍,未来可期,加油。

分布式协调技术----zookeeper

分布式协调技术是用来解决分布式环境中多个进程间的同步控制,使他们能有序的访问某种临界资源,防止造成“脏数据”的后果,分布式并不是一个简单的调度算法就能轻易解决的,这是一种误解。如果进程全部是在一台机器上确实这么久好办,但是出于分布式的环境下该怎么解决呢?

给大家分析一下这个图,图中的三台机器,每个程序个跑一个应用程序,通过网络图将此连接起来,构成一个系统为用户提供服务,对用户来说这是个透明的架构的系统,我们可以把这个系统称之为分布式系统。

在分析一下这个分布式系统是如何对进程进行调度,假设在server1上挂载了一个资源,三个分布式的进程都要来竞争这个资源,但是又不希望他们同时访问,此时就需要一个“协调器”,让他们有序获取资源,“协调器”则被称为锁。比如“进程-1”说明程序在使用该资源时会先获取锁,“进程1”获取锁就会对资源独占,使用完将锁释放,让其他进程来获得锁。这个锁则是分布式锁,也是分布式协调技术。

分布式做的比较好的就是Google的Chubby和Apache的Zookeeper,Chubby是非开源的,后来雅虎模仿Chubby开发出了Zookeeper,也实现了类似的分布式功能,并把zookeeper作为开源程序捐给了Apache。Zookeeper用来构建我们的系统,不仅Bug少而且节约成本。

Zookeeper的优点是一种高可用、高性能且一直的开源协调工具。并且提供了“分布式锁服务”,功能强大,可以配置维护、组服务、分布式通知及分布式消息队列等。在性能方面它采用了Zab协议,数据结构用的Znode,在数据结构上定义了原语,通知机制用的Watcher机制,有严格的序列访问控制,不会因为一个节点的错误而崩溃。

(1)给Zookeeper起了俩主节点,主节点-A master-00001,主节点-B master-00002,启动后都像zookeeper注册一个节点,主节点-A变成了主节点,主节点-B变成了备用节点,对俩Master进程进行调度。

(2)主节点-A挂了,它注册的节点被自动删除,感知节点发起选举,经过选举后主节点-B变成了主节点,替代了主节点-A。

(3)Master恢复,它会在向zookeeper注册一个节点master-00003,再次选举后主节点-B依旧是主节点,主节点A变成了备用节点。

安装配置步骤:

试验机器:1921681010     hostname:zk1

1921681011    hostname:zk2

1921681012     hostname:zk3

1安装jdk

[^_^] ~# tar xf jdk-8u131-linux-x64targz -C /usr/local/

[^_^] ~# mkdir /usr/local/java

[^_^] java# mv jdk180_171 /usr/local/java

[^_^] ~# cat /etc/profiled/javash

JAVA_HOME=/usr/local/java/jdk180_131

JRE_HOME=/usr/local/java/jdk180_131/jre

CLASS_PATH=:$JAVA_HOME/lib/dtjar:$JAVA_HOME/lib/toolsjar:$JRE_HOME/lib

PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH

export JAVA_HOME JRE_HOME CLASS_PATH

[^_^] ~# source /etc/profiled/javash

验证:java -version

2安装zookeeper

[^_^] ~# cat /etc/hosts

127001  localhost localhostlocaldomain localhost4 localhost4localdomain4

::1        localhost localhostlocaldomain localhost6 localhost6localdomain6

1921683610  zk1

1921683611  zk2

1921683612  zk3

[^_^] ~# cat /etc/profiled/zksh

#Set Zookeeper Environment

export ZOOKEEPER_HOME=/usr/local/zookeeper-3411

export PATH=$PATH:$ZOOKEEPER_HOME/bin:$ZOOKEEPER_HOME/conf

[^_^] ~# source /etc/profiled/zksh

[^_^] ~#cp /usr/local/zookeeper/conf/zoo_samplecfg /usr/local/zookeeper/conf/zoocfg

[^_^] ~#mkdir -p /usr/local/zookeeper/data/log

[^_^] ~#echo "1" > /usr/local/zookeeper/data/myid    #三台zookeeper的myid是不一样的

[^_^] ~# egrep -v "^$|#" /usr/local/zookeeper-3411/conf/zoocfg

tickTime=2000

initLimit=10

syncLimit=5

dataDir=/tmp/zookeeper

dataLogDir=/tmp/zookeeper/log

clientPort=2181      #服务端口

server1=zk1:2888:3888  #2888是follower连leader的端口,3888是选leader端口

server2=zk2:2888:3888

server3=zk3:2888:3888

[^_^] ~# cd /usr/local/zookeeper-3411/bin/

[^_^] bin# /zkServersh start  &

[^_^] bin#jps     #查看是否启动成功

1155 Jps

1093 QuorumPeerMain  #QuorumPeerMain是zookeeper进程

[^_^] bin# /zkServersh status   #查节点状态

[^_^] bin#zkClish -server zk1:2181,zk2:2181,zk3:2181   #可以创建zk集群

在公司核心系统的开发过程中用到了ZooKeeper,简称zk,用于搭建分布式核心环境,开发过程中也经常会遇到zk出现的问题,看了几篇博客了解和总结一下zk的基本原理。

ZooKeeper 主要有几个重要的概念,简单总结下:

ZooKeeper 中主要有三种角色:Leader、Follower、Observer

一个 ZooKeeper 集群同一时刻只会有一个 Leader,其他都是 Follower 或 Observer。

ZooKeeper 集群的所有机器通过一个 Leader 选举过程来选定一台被称为『Leader』的机器,Leader服务器为客户端提供读和写服务。

Follower 和 Observer 都能提供读服务,不能提供写服务。两者唯一的区别在于,Observer机器不参与 Leader 选举过程,也不参与写 *** 作的『过半写成功』策略,因此 Observer 可以在不影响写性能的情况下提升集群的读性能。

每个子目录项如 NameService 都被称作为znode,和文件系统一样,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode,唯一的不同在于znode是可以存储数据的。 

Session 是指客户端会话。在ZooKeeper 中,一个客户端连接是指客户端和 ZooKeeper 服务器之间的TCP长连接。

ZooKeeper 对外的服务端口默认是2181,客户端启动时,首先会与服务器建立一个TCP连接,从第一次连接建立开始,客户端会话的生命周期也开始了,通过这个连接,客户端能够通过心跳检测和服务器保持有效的会话,也能够向 ZooKeeper 服务器发送请求并接受响应,同时还能通过该连接接收来自服务器的 Watch 事件通知。

Session 的 SessionTimeout 值用来设置一个客户端会话的超时时间。当由于服务器压力太大、网络故障或是客户端主动断开连接等各种原因导致客户端连接断开时,只要在SessionTimeout 规定的时间内能够重新连接上集群中任意一台服务器,那么之前创建的会话仍然有效。

zookeeper的结构其实就是一个树形结构,leader就相当于其中的根结点,其它节点就相当于follow节点,每个节点都保留自己的内容。

zookeeper的节点分两类: 持久节点 和 临时节点

持久节点:所谓持久节点是指一旦这个 树形结构上被创建了,除非主动进行对树节点的移除 *** 作,否则这个 节点将一直保存在 ZooKeeper 上。

临时节点:临时节点的生命周期跟客户端会话绑定,一旦客户端会话失效,那么这个客户端创建的所有临时节点都会被移除。

有四种类型的znode: 

1、PERSISTENT-持久化目录节点 

客户端与zookeeper断开连接后,该节点依旧存在 

2、PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点 

客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号 

3、EPHEMERAL-临时目录节点 

客户端与zookeeper断开连接后,该节点被删除 

4、EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点 

客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号 

每个 节点除了存储数据内容之外,还存储了 节点本身的一些状态信息。用 get 命令可以同时获得某个 节点的内容和状态信息

在 ZooKeeper 中,version 属性是用来实现乐观锁机制中的『写入校验』的(保证分布式数据原子性 *** 作)。

Zookeeper 的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和 leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。

在ZooKeeper中,能改变ZooKeeper服务器状态的 *** 作称为事务 *** 作。一般包括数据节点创建与删除、数据内容更新和客户端会话创建与失效等 *** 作。对应每一个事务请求,为了保证事务的顺序一致性,ZooKeeper都会为其分配一个全局唯一的事务ID,用 ZXID 表示,通常是一个64位的数字。每一个 ZXID对应一次更新 *** 作,从这些 ZXID 中可以间接地识别出 ZooKeeper 处理这些事务 *** 作请求的全局顺序。

ZooKeeper允许用户在指定节点上注册一些 Watcher,并且在一些特定事件触发的时候,ZooKeeper 服务端会将事件通知到感兴趣的客户端上去。该机制是 ZooKeeper 实现分布式协调服务的重要特性。

以上就是关于Zookeeper原理解析全部的内容,包括:Zookeeper原理解析、Zookeeper选主过程,理论和源码结合,看这一篇足够了、消息队列之zookeeper等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9778267.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-01
下一篇2023-05-01

发表评论

登录后才能评论

评论列表(0条)

    保存