Zookeeper笔记

概述

Zookeeper是一种分布式协调服务。

作用:方便分布式系统开发,提供选举主节点、管理组内成员关系、管理元数据等功能。通过Zookeeper构建分布式系统。

可以把系统中的数据分为应用数据和协同数据,Zookeeper用于管理应用协作的关键数据,不适用于存储海量应用数据。

对分布式系统来说,使用一个独立的协调组件有几个重要的好处:首先,我们可以独立地设计和实现该组件,这样独立的组件可以跨多个应用共享。其次,可以简化应用系统架构师在协作方面的工作。最后,系统可以独立地运行和协作这些组件,独立这样的组件,也简化了生产环境中解决实际问题的任务。这也正是Zookeeper被独立领出来的原因。

 

层级树状结构

很多用于协作的原语常常在很多应用之间共享,因此,设计一个用于协作需求的服务的方法往往是提供原语列表,暴露出每个原语的实例化调用方法,并直接控制这些实例。比如,我们可以说分布式锁机制组成了一个重要的原语,同时暴露出创建、获取和释放三个调用方法。

不过,这种方式使得应用丧失了灵活性。

因此,Zookeeper另辟蹊径。Zookeeper并不直接暴露原语,取而代之,它暴露了由一小部分调用方法组成的类似文件系统的API,以便允许应用实现自己的原语。

Zookeeper操作和维护了一些小型的数据节点,这些节点被称为znode,采用类似于文件系统的层级树状结构进行管理。

(注意:这里的数据节点与分布式系统节点是不同的,系统节点指的是单独的进程,这里的数据节点是抽象概念类似文件或目录)

如图,根节点包含4个子节点。

./workers节点,其下每个znode子节点保存了系统中的一个可用从节点信息(Zookeeper集群中的一个节点)。

./tasks节点,其下每个znode子节点保存了所有已经创建并等待从节点执行的任务的信息。

./assign节点,其下每个znode子节点保存了分配到某个从节点的一个任务信息。

#Znode的类型

znode一共有4种类型:持久的、临时的、持久有序的、临时有序的。

临时节点:一个临时节点,在以下两种情况下将会被删除:

1.当创建该znode的客户端的会话因超时或主动关闭而中止时。

2.当某个客户端(不一定是创建者)主动删除该节点时。

注意:临时节点不能拥有子节点。

持久节点:持久节点只能通过delete来进行删除。

有序节点:在节点创建时,会在路径之后追加一个单调递增的整数,如/tasks/task-1。有序znode提供了创建具有唯一名称的znode的简单方式,同时也能通过这种方式看到znode的创建顺序。

#Znode版本号

每个znode都有一个版本号,它随着每次数据变化而自增。setData和delete操作以版本号作为传入参数,只有当传入的版本号与服务器上的版本号一致时调用才会成功。

 

监视和通知

客户端可以向Zookeeper注册监听指定的znode,即设置监视点(watch)。监视点是一个单次触发操作。为了接收多个通知,客户端必须在每次通知后设置一个新的监视点。当节点变化是,客户端就能获得通知。

注意:在设置新监视点之前,节点状态可能已经发送变化。这里要求在设置新的监视点前,要查看节点状态。Zookeeper的所有读操作API(getData、getChildren、exists等)均可以选择在读取的znode节点上设置监视点。

Zookeeper可以设置多种监视点,如监视znode的数据变化、监视znode子节点的变化、监视znode的创建或删除。

客户端设置的监视点与会话关联,如果会话过期,等待中的监视点将被删除。不过监视点可以跨越不同服务端的连接而保持。

监视点有两种类型:数据监视点和子节点监视点。创建、删除或设置一个znode节点的数据都会触发数据监视点,exists和getData操作可以设置数据监视点,只有getChildren操作可以设置子节点监视点,这种监视点只有在znode子节点创建或删除时才被触发。

 

Zookeeper架构

Zookeeper集群可以由一个(standalone独立模式)或多个节点(quorum仲裁模式)组成,它们之间会进行状态复制,并同时服务于客户端的请求。

#Zookeeper仲裁(法定人数)

在仲裁模式下,Zookeeper复制集群中的所有服务器的数据树。但如果让客户端等待每个服务器完成数据保存后再继续,将会有很大的延迟,这是无法接受的。因此Zookeeper有法定人数的概念,就行在立法领域有投票所需立法者最小数量,在Zookeeper中指能使Zookeeper有效运行的最少服务器数量。比如,我们一共有5个Zookeeper服务器,法定人数为3个,这样,只要任何3个服务器保存了数据,客户端就可以继续,而其他两个服务器最终也将捕获到数据,并保存数据。

##脑裂(split-brain)与法定人数的设置

假设我们共有5个集群节点,设置的法定人数为2。现在由于网络问题,其中两个(A组)与另外三个节点(B组)产生了分区隔离。此时,客户端向A组中的一个节点提交数据修改,A组内部成功完成了数据复制,由于设置的法定人数是2,所以服务返回客户端指出修改已经完成。这时,另外三个节点并不知道发生了数据修改,从而造成了数据的不一致。这就是脑裂问题。

为了避免脑裂问题,需要把法定人数设置为占集群数的多数。并最好使集群节点数保持奇数。

#会话

在对Zookeeper集合执行任何请求前,一个客户端必须先与服务建立会话。当一个会话因某种原因而中止时,在这个会话期间创建的临时节点将会消失。客户端初始连接到集合中某一个服务器,当会话无法与当前连接的服务器继续通信时,会话就可能转移到另一个服务器上。Zookeeper客户端库透明地转移一个会话到不同的服务器。

会话提供了顺序保障,同一个会话中的请求会以FIFO顺序执行。

#集群角色

群首(leader):群首作为中心点处理所有对Zookeeper系统变更的请求,就像一个定序器,建立了所有对Zookeeper状态的更新的顺序。

追随者(follower):追随者接收群首所发出更新操作请求,并对这些请求进行处理。

观察者(observer):观察者不会参与决策哪些请求可被接受的过程,观察者的设计只是为了系统的可扩展性。

##观察者

群首和追随者会被记入法定人数,参与决定选举和节点修改。而观察者,仅仅是决定的执行者,不参与决定本身。引入观察者,是为了在不牺牲写操作的吞吐率的前提下服务更多的读操作。

 

Zookeeper内部原理

读取操作会在接收服务器上直接处理,写操作会被转发给群首。

#Zookeeper事务

Zookeeper保证每次变更都以原子方式执行。在Zookeeper中每次写操作都会被转发给群主,群主根据请求改变相应节点的数据信息,并增加该节点的版本号。针对每次修改,群首都会产生一个事物,这个事物中包含(节点数据和节点版本号),每个事务会有一个标识符,称之为zxid。当处理事务时,服务端会用事务中的数据信息来替换节点中原来的数据信息,并会用事务中的版本号更新该节点,而不是增加版本号的值。每个节点中都会有特定数量的线程来执行事务。

zxid为一个64位long型整数,分两部分:时间戳(32位)和计数器(32位)。通过zxid标识事务,就可以按照群首所指定的顺序在各个服务器中顺序执行每个修改。通过zxid也能看到各个节点执行了多少事务。

总结起来是这样的,在接收到一个写请求操作后,追随者会将请求转发给群首,群首将探索性地执行该请求,并将执行结果以事务的方式对状态更新进行广播。一个事务中包括服务器需要执行变更的确切操作,当事务提交时,服务器就会将这些变更反馈到数据树上。

服务器如何确认一个事务是否已经提交呢?其实是通过Zookeeper原子广播协议,过程是这样的:

1.群首会向所有追随者发送一个PROPOSAL消息p。

2.当一个追随者接收到消息p后,会响应群首一个ACK消息,通知群首其已接收提案(proposal)。

3.当收到仲裁数量的服务器发送的确认消息后(该仲裁数包括群首自己),群首就会发送消息通知追随者进行事务提交(COMMIT)操作。

#群首选举

群首为集群中的服务器选出来的一个服务器,设置群首的目的是为了对客户端所发起的Zookeeper状态变更请求进行排序。群首将每一个请求转换为一个事务。将这些事务发送给追随者,确保集群按群首确定的顺序接受并处理这些事务。

一个服务器必须被仲裁的法定数量的服务器认可,才能成为群首。

每个服务器启动后进入LOOKING状态,开始选举一个新的群首或查找已经存在的群首,如果群首已经存在,其他服务器会通知这个新启动的服务器,告知哪个服务器是群首,与此同时,新的服务器会与群首建立连接,以确保自己的状态与群首一致。

如果集群中所有的服务器均处于LOOKING状态,这些服务器就会进行通信来选举一个群首。选举胜出的服务器将进入LEADING状态,而集群中其他服务器将会进入FOLLOWING状

 

访问控制

Zookeeper使用访问访问控制表(ACL)来控制访问权限。

具体可以参考https://blog.csdn.net/cdu09/article/details/51637451

 

Zookeeper的应用

#使用Zookeeper实现锁

假设有多个进程尝试获取一个锁,每个进程都尝试创建名为/lock,如果其中一个进程成功创建了该节点,就表示它获得了锁。其他进程因为节点已经存在而创建/lock失败。当进程监听到/lock的变化,并检测到/lock被删除时,可以再次尝试创建/lock节点来获得锁。为了避免出现死锁问题,我们需要设置/lock节点为临时节点,这样一旦获得锁的进程过掉,锁也会自动释放。

#使用Zookeeper实现选主

应用客户端可以通过创建/master节点来推选自己为主节点,如果节点已存在,应用客户端确认自己不是主要主节点并返回。我们还需要在/master上设置监视点,来监听主节点崩溃。

 

Zookeeper常用命令

zkCli.sh -server 10.77.20.23:2181   (连接到zookeeper服务)

ls / 

create /path data

delete /path

rmr /path 【删除整个节点,包括子节点】

exists /path

setData /path data

getData /path

getChildren /path

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值