赞
踩
Zookeeper是Apache软件基金会的一个软件项目,它为大型计算机提供开源的分布式配置服务,同步服务和命名注册.Zookeeper曾经是Hadoop一个子项目,但现在作为一个独立的顶级项目.
1.tickTime: Zookeeper服务器之间或客户端与服务器之间维持心跳的时间间隔,也就 是每个 tickTime时间就会发送一个心跳。tickTime以毫秒为单位。该参数用来定义心跳 的间隔时间, zookeeper的客户端和服务端之间也有和web开发里类似的session的概 念,而zookeeper里最小 的session过期时间就是tickTime的两倍。 2.initLimit: Follower在启动过程中,会从Leader同步所有最新数据,然后确定自己 能够对外服务的 起始状态。Leader允许F在initLimit时间内完成这个工作。通常情况 下,我们不用太在意这个参 数的设置。如果ZK集群的数据量确实很大了,F在启动的时 候,从Leader上同步数据的时间也会 相应变长,因此在这种情况下,有必要适当调大这 个参数了。默认为10。 3.syncLimit:在运行过程中,Leader负责与ZK集群中所有机器进行通信,例如通过一些 心跳检测 机制,来检测机器的存活状态。如果L发出心跳包在s yncLimit之后,还没有从 F那里收到响应, 那么就认为这个F已经不在线了。注意:不要把这个参数设置得过大,否 则可能会掩盖一些问 题。 4.dataDir:存储快照文件snapshot的目录。默认情况下,事务日志也会存储在这里。建 议同时配置 参数dataLogDir,事务日志的写性能直接影响zk性能。 5.clientPort:客户端连接服务器的端口 6.maxClientCnxns 7.autopurge.snapRetainCount 8.autopurge.purgeInterval 简化一下文件: tickTime=2000 initLimit=10 syncLimit=5 dataDir=/tmp/zookeeper clientPort=2181
两种角色时:每个节点这样配置
三种角色时:这样配置
领导者(Leader):负责进行投票的发起和决议,最终更新状态。
跟随者(Follower) : Follower用于接收客户请求并返回客户结果。参与Leader发起
的投票。
观察者(observer) : Oberserver可以接收客户端连接,将写请求转发给leader节
点。但是Observer不参加投票 过程,只是同步leader的状态。Observer为系统扩展提
供了一种方法。
学习者(Learner ):和leader进行状态同步的s erver统称Learner,上述Follower
和。bserver都是Learner。
如果client连接的节点为Leader,那么就不需要转发,直接进行相关操作.
如果client连接的节点为Follower/observer那么需要把请求转发到Leader,然后由leader进行相关操作.
上图的流程:
ack: 命令正确应答
三种角色都可以连接客户端,但是只有Leader才能处理写请求.
Follower,observer连接客户端,如果接受到写请求,那么要转发给Leader进行处理.
Leader接收到写请求后,会向所有的follower发送 写数据入的提议命令,Follower响应提议并发送ack给Leader,Leader根据接收到的ack进行统计并采用过半机制进行判断,判断成功,则向所有Follower和observer发送commit 写请求的命令,同时Leader也会commit提交写请求, 这样Leader,Follower,observer数据就一致了.(特殊情况:如果zk3 在就收到commit指令后挂掉了,则此时数据不一致,那么当zk3重启后,leader会对它进行数据同步,从而保证数据一致性)
当zk集群 1个Leader,2个follower,1个observer, 当新增一个节点时,则Leader节点需要向新增的节点同步数据,从而保证各个节点数据一致.
注意:当Follower节点过多时,会对写操作有很大影响, 需要很多节点接受提议,然后应答,当达到半数时,才能触发写操作.
为什么要有observer
ZooKeeper服务中的每个Server可服务于多个Client,并且Client可连接到ZK服务中的 任一台Server来提交请 求。若是读请求,则由每台S erver的本地副本数据库直接响 应。若是改变S erver状态的写请求,需要通过一致 性协议来处理,这个协议就是我们前 面介绍的Zab协议。 简单来说,Zab协议规定:来自Client的所有写请求,都要转发给ZK服务中唯一的 Server-Leader,由Leader 根据该请求发起一个Proposalo然后,其他的Server对该 Proposal进行投票。之后,Leader对投票进行收集, 当投票数量过半时Leader会向所 有的S erver发送一个通知消息。最后,当C lient所连接的S erver收到该消息时, 会 把该操作更新到内存中并对Client的写请求做出回应。 ZooKeeper服务器在上述协议中实际扮演了两个职能。它们一方面从客户端接受连接与操 作请求,另一方面对 操作结果进行投票。这两个职能在ZooKeeper集群扩展的时候彼此制 约。例如,当我们希望增加ZK服务中 Client数量的时候,那么我们就需要增加Server 的数量,来支持这么多的客户端。然而,从Zab协议对写请求的 处理过程中我们可以发 现,增加服务器的数量,则增加了对协议中投票过程的压力。因为Leader节点必须等待 集群中过半S erver响应投票,于是节点的增加使得部分计算机运行较慢,从而拖慢整个 投票过程的可能性也随 之提高,写操作也会随之下降。这正是我们在实际操作中看到的问 题一一随着ZooKeeper集群变大,写操作的 吞吐量会下降。 所以,我们不得不,在增加Client数量的期望和我们希望保持较好吞吐性能的期望间进行 权衡。要打破这一耦 合关系,我们引入了不参与投票的服务器,称为Observer。 Observer可以接受客户端的连接,并将写请求转 发给Leader节点。但是,Leader节点 不会要求Observer参加投票。相反,Observer不参与投票过程,仅仅在 上述第3步那 样,和其他服务节点一起得到投票结果。 这个简单的扩展,给ZooKeeper的可伸缩性带来了全新的镜像。我们现在可以加入很多 Observer节点,而无 须担心严重影响写吞吐量。但他并非是无懈可击的,因为协议中的 通知阶段,仍然与服务器的数量呈线性关 系。但是,这里的串行开销非常低。因此,我们 可以认为在通知服务器阶段的开销无法成为主要瓶颈。
Zookeeper中的CAP
Zookeeper至少满足了 CP,牺牲了可用性,比如现在集群中有Leader和Follower两种角
色,那么当其中任意一 台服务器挂掉了,都要重新进行选举,在选举过程中,集群是不可
用的,这就是牺牲的可用性。
但是,如果集群中有Leader、Follower, Observer三种角色,那么如果挂掉的是
Observer,那么对于集群来说 并没有影响,集群还是可以用的,只是Observer节点的数
据不同了,从这个角度考虑,Zookeeper又是牺牲了 —致性,满足了 AP
1.统一命名服务: 命名服务也是分布式系统中比较常见的一类场景。在分布式系统中,通过使用命名服务, 客户端应用能够根据 指定名字来获取资源或服务的地址,提供者等信息。被命名的实体通 常可以是集群中的机器,提供的服务地 址,远程对象等等一一这些我们都可以统称他们为 名字(Name)。其中较为常见的就是一些分布式服务框架 中的服务地址列表。通过调用 ZK提供的创建节点的API,能够很容易创建一个全局唯一的path,这个path就可 以作为 一个名称。 2.配置中心: 配置的管理在分布式应用环境中很常见,例如同一个应用系统需要多台PC Server运行, 但是它们运行的应用 系统的某些配置项是相同的,如果要修改这些相同的配置项,那么就 必须同时修改每台运行这个应用系统的 PC Server,这样非常麻烦而且容易出错。 像这样的配置信息完全可以交给Zookeeper来管理,将配置信息保存在Zookeeper的某个 目录节点中,然后 将所有需要修改的应用机器监控配置信息的状态,一旦配置信息发生变 化,每台应用机器就会收到Zookeeper 的通知,然后从Zookeeper获取新的配置信息应用 到系统中。 3.集群管理与Master选举: 集群机器监控:这通常用于那种对集群中机器状态,机器在线率有较高要求的场景,能够 快速对集群中机器变 化作出响应。这样的场景中,往往有一个监控系统,实时检测集群机 器是否存活。过去的做法通常是:监控系 统通过某种手段(比如ping)定时检测每个机 器,或者每个机器自己定时向监控系统汇报“我还活着”。 利用ZooKeeper有两个特性,就可以实时另一种集群机器存活性监控系统: (1).客户端在节点x上注册一个Watcher,那么如果x?的子节点变化了,会通知该客户端。 (2).创建EPHEMERAL类型的节点,一旦客户端和服务器的会话结束或过期,那么该节点就 会消失。 例如,监控系统在/clusterServers节点上注册一个Watcher,以后每动态加机器,那么就往/clusterServers下 创建一个EPHEMERAL类型的节点:/clusterServers/{hostname}.这样,监控系统就能够实时知道机器的增减 情况,至于后续处理就是监控系统的业务了。 在分布式环境中,相同的业务应用分布在不同的机器上,有些业务逻辑(例如一些耗时的 计算,网络I/。处 理),往往只需要让整个集群中的某一台机器进行执行,其余机器可以 共享这个结果,这样可以大大减少重复 劳动,提高性能,于是这个master选举便是这种 场景下的碰到的主要问题。 4.分布式锁: 分布式锁,这个主要得益于ZooKeeper为我们保证了数据的强一致性。锁服务可以分为两 类,一个是保持独 占,另一个是控制时序。 所谓保持独占,就是所有试图来获取这个锁的客户端,最终只有一个可以成功获得这把 锁。通常的做法是把zk 上的一个znode看作是一把锁,通过c reate znode的方式来实 现。所有客户端都去创建/distribute_lock节点, 最终成功创建的那个客户端也即拥有 了这把锁。控制时序,就是所有试图来获取这个锁的客户端,最终都是会 被安排执行,只 是有个全局时序了。做法和上面基本类似,只是这里/distribute_lock已经预先存在,客户端在 它下面创建临时有序节点(这个可以通过节点的属性控制:CreateMode.EPHEMERAL_SEQUENTIAL来指 定)。Zk的父节点(/distribute_lock) 维持一份sequence,保证子节点创建的时序性,从而也形成了每个客户端 的全局时序。
一次会话(session)指的是:就好比打电话,A给B打电话,接通之后,会话开始,直到挂断电话,该次会话就结束了,而浏览器访问服务器,就跟打电话一样,浏览器A给服务器发送请求,访问web程序,该次会话就已经接通,其中不管浏览器发送多少请求(就相当于接通电话后说话一样),都视为一次会话,直到浏览器关闭,本次会话结束。其中注意,一个浏览器就相当于一部电话,如果使用火狐浏览器,访问服务器,就是一次会话了,然后打开google浏览器,访问服务器,这是另一个会话,虽然是在同一台电脑,同一个用户在访问,但是,这是两次不同的会话。
1.持久节点:所谓持久节点,是指在节点创建后,就一直存在,直到有删除操作来主动
清除这个节点。
2.临时节点:和持久节点不同的是,临时节点的生命周期和客户端会话绑定。也就是说,如
果客户端会话失效,那么这个节点就 会自动被清除掉。注意,这里提到的是会话失效,而
非连接断开。另外,在临时节点下面不能创建子节点。(会话:session) (连接:connection) 会话和连接是两个东西, 临时节点是和session绑在一起的.
临时节点特殊之处:
临时节点随着session的关闭而被清除(临时节点只与session有关)
3.持久顺序节点:这类节点的基本特性和持久节点是一致的。额外的特性是,在ZK中,每个
父节点会为他的第一级子节点维护一 份时序,会记录每个子节点创建的先后顺序。基于这
个特性,在创建子节点的时候,可以设置这个属性,那么在创建节点过程 中,ZK会自动为
给定节点名加上一个数字后缀,作为新的节点名。这个数字后缀的范围是整型的最大值。
4.临时顺序节点:类似临时节点和顺序节点
注意:zookeeper默认对每个结点的最大数据量有一个上限是1M (也可以自己设置)
ZooKeeper命名空间中的每个znode都有一个与之关联的stat结构,类似于Unix/Linux文件系统中文件的stat结构。znode的stat结构中的 字段显示如下,各自的含义如下:
• cZxid :创建znode的事务ID。
• mZxid :最后修改znode的事务ID。
• pZxid:最后修改添加或删除子节点的事务ID。
• ctime:表示从1970-01-01T00:00:00Z开始以毫秒为单位的znode创建时间。
• mtime:表示从1970-01-01T00:00:00Z开始以毫秒为单位的znode最近修改时间。
• dataVersion :表示对该znode的数据所做的更改次数。
• eversion:这表示对此znode的子节点进行的更改次数。
• aelVersion :表示对此znod e的ACL进行更改的次数。
• ephemeralOwner:如果znode是ephemeral类型节点,则这是znode所有者的 session ID。如果znode不是ephemeraI节点,则该字段设置为零。
• dataLength:这是znode数据字段的长度。
• numChildren:这表示znode的子节点的数量。
Zxid(zab算法)
类似于RDBMS中的事务ID,用于标识一次更新操作的Proposal ID。为了保证顺序性,该
Zxid必须单调递增。因此ZooKeeper使用一个 64位的数来表示,高32位是Leader的
epoch,从1开始,每次选出新的Leader, epoch加一。低32位为该epoch内的序号,每次
epoch变 化,都将低32位的序号重置。这样保证了 Zxid的全局递增性。
一个zk的节点可以被监控,包括这个目录中存储的数据的修改,子节点目录的变化,一旦
变化可以通知设置监控的客户端,这个功能是 zookeeper对于应用最重要的特性,通过这
个特性可以实现的功能包括配置的集中管理,集群管理,分布式锁等等。
watch机制官方说明:一个Watch事件是一个一次性的触发器,当被设置了 Watch的数据
发生了改变的时候,则服务器将这个改变发送给设置了 Watch的客户端,以便通知它们。
可以注册watcher的方法:getData、exists、getChildren。
可以触发watcher的方法:create、delete、setData。连接断开的情况下触发的
watcher会丢失。
一个Watcher实例是一个回调函数,被回调一次后就被移除了。如果还需要关注数据的变
化,需要再次注册watcher。
New ZooKeeper时注册的watcher叫default watcher,它不是一次性的,只对client的
连接状态变化作出反应。
注意: exits和getData设置数据监视,而getChildren设置子节点监视
event For “/path” | event For “/path/child” | |
---|---|---|
create("/path”) | EventType.NodeCreated | 无 |
delete("/path”) | EventType.NodeDeleted | 无 |
setData("/path") | EventType.NodeDataChanged | 无 |
create("/path/child") | EventType.NodeChildrenChanged (getChild) | EventType.NodeCreated |
delete("/path/child") | EventType.NodeChildrenChanged (getChild) | EventType.NodeDeleted |
setData("/path/child") | 无 | EventType.NodeDataChanged |
event For “/path” | Default Watcher | exists("/path“) | getData("/path“) | getChildren("/path’’) |
---|---|---|---|---|
EventType.None | V | V | V | V |
EventType.NodeCreated | V | V | ||
EventType.NodeDeleted | V | V | ||
EventType.NodeDataChanged |
用给定的路径创建一个节点0 flag参数指定创建的节点是临时的,持久的还是顺序的。 默认情况下,所有节点都是持久的。 当会话过期或客户端断开连接时,临时节点(flag: -e)将被自动删除。 顺序节点保证节点路径将是唯一的。 ZooKeeper集合将向节点路径填充10位序列号。例如,节点路径/myapp将转换 为/myapp0000000001,下一个序列号将 为/myapp0000000002。如果没有指定flag,则节点被认为是持久的。 语法: create /path data 示例: create /FirstNode first 输出: [zk: localhost:2181(CONNECTED) 3] create /FirstNode first Created /FirstNode 要创建顺序节点,请添加flag: -s,如下所示。 语法: create -s /path data 示例: create -s /FirstNode second 输出: [zk: localhost:2181(CONNECTED) 4] create -s /FirstNode second Created /FirstNode0000000018 要创建临时节点,请添加flag: -e,如下所示。 语法: create -e /path data 示例: create -e /FirstNode-ephemeral ephemeral 输出: [zk: localhost:2181(CONNECTED) 6] create -e /FirstNode-ephemeral ephemeral Created /FirstNode-ephemeral 记住当客户端断开连接时,临时节点将被删除。你可以通过退出ZooKeeper CLI,然后重新打开CL I来尝试。
它返回节点的关联数据和指定节点的元数据。你将获得信息,例如上次修改数据的时间,修改的位置以及数据的相关信息。 于分配监视器以显示数据相关的通知。 语法: 示例: get /FirstNode 输出: [zk: localhost:2181(CONNECTED) 7] get /FirstNode first cZxid = 0xa2 ctime = Wed Dec 12 13:29:14 CST 2018 mZxid = 0xa2 mtime = Wed Dec 12 13:29:14 CST 2018 pZxid = 0xa2 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 5 numChildren = 0 要访问顺序节点,必须输入znode的完整路径。 示例: get /FirstNode0000000018 输出: [zk: localhost:2181(CONNECTED) 9] get /FirstNode0000000018 second cZxid = 0xa3 ctime = Wed Dec 12 13:30:44 CST 2018 mZxid = 0xa3 mtime = Wed Dec 12 13:30:44 CST 2018 pZxid = 0xa3 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 6 numChildren = 0
设置指定znode的数据。完成此设置操作后,你可以使用get CLI命令检查数据。 语法: set /path /data 示例: set /FirstNode first_update 输出: [zk: localhost:2181(CONNECTED) 12] set /FirstNode first_update WATCHER:: WatchedEvent state:SyncConnected type:NodeDataChanged path:/FirstNode cZxid = 0xa2 ctime = Wed Dec 12 13:29:14 CST 2018 mZxid = 0xa6 mtime = Wed Dec 12 13:51:39 CST 2018 pZxid = 0xa2 cversion = 0 dataVersion = 1 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 12 numChildren = 0
创建子节点类似于创建新的znodeo唯一的区别是,子znode的路径也将具有父路径。
语法:
create /parent/path/subnode/path data
示例:
create /FirstNode/Child firstchildren
输出:
[zk: localhost:2181(CONNECTED) 13] create /FirstNode/Child firstchildren
Created /FirstNode/Child
[zk: localhost:2181(CONNECTED) 14] create /FirstNode/Child2 secondchildren
Created /FirstNode/Child2
此命令用于列出和显示znode的子项。
语法:
ls /path
实例:
ls /FirstNode
输出:
[zk: localhost:2181(CONNECTED) 15] ls /FirstNode
[Child2, Child]
状态描述指定的znode的元数据。它包含时间戳,版本号,ACL,数据长度和子znode等细项。 语法: stat /path 示例: stat /FirstNode 输出: [zk: localhost:2181(CONNECTED) 16] stat /FirstNode cZxid = 0xa2 ctime = Wed Dec 12 13:29:14 CST 2018 mZxid = 0xa6 mtime = Wed Dec 12 13:51:39 CST 2018 pZxid = 0xa8 cversion = 2 dataVersion = 1 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 12 numChildren = 2
移除指定的znode并递归其所有子节点。只有在znode可用的情况下才会发生。 语法: rmr /path 示例: rmr /FirstNode 输出: [zk: localhost:2181(CONNECTED) 17] rmr /FirstNode [zk: localhost:2181(CONNECTED) 18] get /FirstNode Node does not exist: /FirstNode 删除(delete /path)命令类似于remove命令,但是只适用于没有子节点的znode 0 ACL zk做为分布式架构中的重要中间件,通常会在上面以节点的方式存储一些关键信息,默认情况下,所有应用都可以读写任何节点,在复 杂的应用中,这不太安全,ZK通过ACL机制来解决访问权限问题。 • ZooKeeper的权限控制是基于每个znode节点的,需要对每个节点设置权限 •每个znode支持设置多种权限控制方案和多个权限 •子节点不会继承父节点的权限,客户端无权访问某节点,但可能可以访问它的子节点 ACL权限控制,使用:schema:id:permission来标识、主要涵盖3个方面: •权限模式(Schema):鉴权的策略 •授权对象(ID) •权限(Permission)
• world:只有一个用户:anyone,代表所有人(默认)
• ip:使用IP地址认证
• auth:使用已添加认证的用户认证
• digest :使用"用户名:密码"方式认证
授权对象ID是指,权限赋予的用户或者一个实体,例如:IP地址或者机器。授权模式schema与授权对象ID之间关系:
• world:只有一个id,即anyone
• ip:通常是一个ip地址或地址段,比如192.168.0.110或192.168.0.1/24
• auth:用户名
• digest :自定义:通常是"username:BASE64(SHA-1(username:password))"
• CREATE,简写为c,可以创建子节点
• DELETE,简写为d,可以删除子节点(仅下一级节点),注意不是本节点
• READ,简写为r,可以读取节点数据及显示子节点列表
• WRITE,简写为w,可设置节点数据
• ADMIN,简写为a,可以设置节点访问控制列表
查看ACL
getAcl /parent
返回
[zk: localhost:2181(CONNECTED) 122] getAcl /parent
'world,'anyone
:cdrwa
默认创建的节点的权限是最开放的,所有都可以增删查改管理。
设置节点对所有人都有写和管理权限
setAcl /parent world:anyone:wa
所以去读取数据的时候会提示
[zk: localhost:2181(CONNECTED) 124] get /parent
Authentication is not valid : /parent
先添加用户:
addauth digest zhangsan:12345
再设置权限,这个节点只有zhangsan这个用户拥有所有权限
setAcl /parent auth:zhangsan:123456:rdwca
1.Recipes:Zookeeper典型应用场景的实现,这些实现是基CuratorFramework。
2.Framework: Zookeeper API的高层封装,大大简化Zookeeper客户端编程,添加了例如Zookeeper连接管理、重试机制等。
3.Utilities:为Zookeeper提供的各种实用程序。
4.Client:Zookeeper client的封装,用于取代原生的Zookeeper客户端(ZooKeeper类),提供一些非常有用的客户端特性。
5.Errors:Curator如何处理错误,连接问题,可恢复的例外等。
6.LeaderLatch和LeaderSelector用于实现zk的选举
1.封装 ZooKeeper client 与 ZooKeeper serve「之间的连接处理
2.提供了一套Fluent风格的操作API
3.提供ZooKeeper各种应用场景(recipe,比如共享锁服务,集群领导选举机制)的抽象封装
客户端在连接服务端是会设置一个sessionTimeout (session过期时间),并且客户端会给服务端发送心跳以刷新服务端的session时间。当网络断开后,服务端无法接受到心跳,会进行session倒计时,判断是否超过了 session过期时间,一旦超过了过期时间,就发送了Session过期,就算后来网络通了,客户端从新连接上了服务端,就会接受session过期的事件,从而删除临时节点和watcher等等。原生客户端不会重建session 0
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。