如何用zookeeper 命名服务实现统一命名服务

qw87112 的BLOG
用户名:qw87112
文章数:98
评论数:48
访问量:73205
注册日期:
阅读量:5863
阅读量:12276
阅读量:408477
阅读量:1096706
51CTO推荐博文
一、ZooKeeper概述ZooKeeper是一种为分布式应用所设计的高可用、高性能且一致的开源协调服务,是Google的Chubby一个开源实现,是Hadoop和Hbase的重要组件,它提供了一项基本服务:分布式锁服务。由于ZooKeeper的开源特性,后来我们的开发者在分布式锁的基础上,摸索了出了其他的使用方法:配置维护、组服务、分布式消息队列、分布式通知/协调等。zookeeper是基于内存同步数据的,所以集群内的节点其内存中的数据结构是完全相同的,因此效率非常高。ZooKeeper具备的几个特点决定了它能够用在大型的、分布式的系统当中:顺序一致性从同一个客户端发起的事务请求,最终将会严格按照其发起顺序被应用到zookeeper中原子性所有事物请求的处理结果在整个集群中所有机器上的应用情况是一致的,即,要么整个集群中所有机器都成功应用了某一事务,要么都没有应用,一定不会出现集群中部分机器应用了改事务,另外一部分没有应用的情况。单一视图无论客户端连接的是哪个zookeeper服务器,其看到的服务端数据模型都是一致的。可靠性一旦服务端成功的应用了一个事务,并完成对客户端的响应,那么该事务所引起的服务端状态变更将会一直保留下来,除非有另一个事务又对其进行了改变。实时性zookeeper并不是一种强一致性,只能保证顺序一致性和最终一致性,只能称为达到了伪实时性。二、zookeeper 数据模型ZooKeeper拥有一个层次的命名空间,这个和标准的文件系统非常相似,如图:ZooKeeper采用树形层次结构,树中的每个节点被称为―Znode,Znode也可以拥有子节点。引用方式:Zonde通过路径引用,如同Unix中的文件路径。必须是绝对路径,因此他们必须由斜杠字符来开头。除此以外,他们必须是唯一的,也就是说每一个路径只有一个表示,因此这些路径不能改变。在ZooKeeper中,路径由Unicode字符串组成,并且有一些限制。字符串"/zookeeper"用以保存管理信息,比如关键配额信息。Znode 结构ZooKeeper命名空间中的Znode,兼具文件和目录两种特点。既像文件一样维护着数据、元信息、ACL、时间戳等数据结构,又像目录一样可以作为路径标识的一部分。每个Znode由3部分组成 :1、stat:此为状态信息, 描述该Znode的版本, 权限等信息2、data:与该Znode关联的数据3、children:该Znode下的子节点ZooKeeper虽然可以关联一些数据,但并没有被设计为常规的数据库或者大数据存储,相反的是,它用来管理调度数据,比如分布式应用中的配置文件信息、状态信息、汇集位置等等。这些数据的共同特性就是它们都是很小的数据,通常以KB为大小单位。ZooKeeper的服务器和客户端都被设计为严格检查并限制每个Znode的数据大小至多1M,但常规使用中应该远小于此值。三、节点类型ZooKeeper中的节点有两种,分别为临时节点和永久节点。节点的类型在创建时即被确定,并且不能改变。临时节点:该节点的生命周期依赖于创建它们的会话。一旦会话(Session)结束,临时节点将被自动删除,当然可以也可以手动删除。虽然每个临时的Znode都会绑定到一个客户端会话,但他们对所有的客户端还是可见的。另外,ZooKeeper的临时节点不允许拥有子节点。永久节点:该节点的生命周期不依赖于会话,并且只有在客户端显示执行删除操作的时候,他们才能被删除。顺序节点当创建Znode的时候,用户可以请求在ZooKeeper的路径结尾添加一个递增的计数。这个计数对于此节点的父节点来说是唯一的,它的格式为"%10d"(10位数字,没有数值的数位用0补充,例如"")。当计数值大于232-1时,计数器将溢出。监视器客户端可以在节点上设置watch,我们称之为监视器。当节点状态发生改变时(Znode的增、删、改)将会触发watch所对应的操作。当watch被触发时,ZooKeeper将会向客户端发送且仅发送一条通知,因为watch只能被触发一次,这样可以减少网络流量。ZooKeeper有多种记录时间的形式,其中包含以下几个主要属性:(1) Zxid致使ZooKeeper节点状态改变的每一个操作都将使节点接收到一个Zxid格式的时间戳,并且这个时间戳全局有序。也就是说,也就是说,每个对节点的改变都将产生一个唯一的Zxid。如果Zxid1的值小于Zxid2的值,那么Zxid1所对应的事件发生在Zxid2所对应的事件之前。实际上,ZooKeeper的每个节点维护者三个Zxid值,为别为:cZxid、mZxid、pZxid。1、cZxid: 是节点的创建时间所对应的Zxid格式时间戳。2、mZxid:是节点的修改时间所对应的Zxid格式时间戳。实现中Zxid是一个64为的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个 新的epoch。低32位是个递增计数。&(2) 版本号对节点的每一个操作都将致使这个节点的版本号增加。每个节点维护着三个版本号,他们分别为:1、version:节点数据版本号2、cversion:子节点版本号3、aversion:节点所拥有的ACL版本号ZooKeeper节点属性:四、ZooKeeper 安装配置ZooKeeper的工作模式有三种:单机模式、集群模式、伪集群模式。单机模式:Zookeeper只运行在一台服务器上,适合测试环境;伪集群模式:就是在一台物理机上运行多个Zookeeper 实例;集群模式:Zookeeper运行于一个至少有三个节点以上集群中,适合生产环境;Zookeeper通过复制来实现高可用性,只要集群中半数以上的节点处于可用状态,它就能够保证服务继续。为什么一定要超过半数呢?这跟Zookeeper的复制策略有关:zookeeper确保对znode 树的每一个修改都会被复制到集群中超过半数的节点上。服务器角色有两种:1、leader -主节点2、follower -从节点在一个集群中通常只有一个leader和多个follower,当leader下线时,follower能根据选举策略,选举一个新的leader保证集群的正常工作。下面我们来构建一个单机模式的ZooKeeper节点:可以去Apache的镜像站点下载zookeeper: http://www.apache.org/dyn/closer.cgi/zookeeper/安装ZooKeeper之前首先需要安装JDK,在oracle官网可以下载到。(建议下载rpm包安装)1、解压zookeepertar&xf&zookeeper-3.4.9.tar.gz
cd&zookeeper-3.4.92、创建配置文件#&conf/zoo.cfg
tickTime=2000
dataDir=/tmp/zookeeper
clientPort=21813、启动服务bin/zkServer.sh&startZooKeeper伪集群模式ZooKeeper提供了伪集群模式,也就是可以在同一台机器上启动多个zookeeper服务,当手头机器不足时,又需要做实验,提供了很大的便利。注: 在同一台机器上部署3个zookeeper&server时,需要为每个server创建独立的配置文件,并且保证每个配置文件中的端口不能冲突,除了clientPort不同之外,另外,还要在dataDir所对应的目录中创建myid文件来指定对应的zookeeper server 实例。需要注意的几个配置项:clientPort端口:如果在1台机器上部署多个server,那么每台机器都要不同的 clientPort,比如 server1是2181,server2是2182,server3是2183dataDir和dataLogDir:dataDir和dataLogDir也需要区分下,将数据文件和日志文件分开存放,同时每个server的这两变量所对应的路径都是不同的server.X和myid: server.X 这个数字就是对应,data/myid中的数字。在3个server的myid文件中分别写入了0,1,2,那么每个server中的zoo.cfg都配 server.0 server.2,server.3就行了。因为在同一台机器上,后面连着的2个端口,3个server都不要一样,否则端口冲突启动命令#&这时使用单机模式的启动命令是不行的,需要在指令后面跟上不同实例的配置文件名称。如下:
bin/zkServer.sh&start&zoo1.cfg
bin/zkServer.sh&start&zoo2.cfg
bin/zkServer.sh&start&zoo3.cfg五、集群实战 ― 构建一个3节点的 ZooKeeper 集群实验环境:服务器IPmyid192.168.1.2111192.168.1.2212192.168.1.2313注:(1) zk服务器集群规模不得小于3个节点(2) 要求各服务器之间系统时间要保持一致。为了实现高可用的ZooKeeper服务,应该把zk部署在一个集群中,每台机器只跑一个zk实例。配置方式和前面差不多,只是每台机器上的配置文件 conf/zoo.cfg 完全相同。创建myid#&为每台机器创建myid文件
#&192.168.1.21
echo&11&&/u01/zookeeper/zookeeper-3.4.9/data/myid
#&192.168.1.22
echo&12&&/u01/zookeeper/zookeeper-3.4.9/data/myid
#&192.168.1.23
echo&13&&/u01/zookeeper/zookeeper-3.4.9/data/myid创建配置文件可以复制 zoo_sample.cfg 到 zoo.cfg 以下为配置文件的参数设置:#&The&number&of&milliseconds&of&each&tick
tickTime=2000
#&The&number&of&ticks&that&the&initial&
#&synchronization&phase&can&take
initLimit=10
#&The&number&of&ticks&that&can&pass&between&
#&sending&a&request&and&getting&an&acknowledgement
syncLimit=5
#&the&directory&where&the&snapshot&is&stored.
#&do&not&use&/tmp&for&storage,&/tmp&here&is&just&
#&example&sakes.
dataDir=/u01/zookeeper/zookeeper-3.4.9/data
#&the&port&at&which&the&clients&will&connect
clientPort=2181
#&the&maximum&number&of&client&connections.
#&increase&this&if&you&need&to&handle&more&clients
#maxClientCnxns=60
server.11=192.168.1.21:
server.12=192.168.1.22:
server.13=192.168.1.23:改好配置文件后,同步到集群内的所有节点。常用配置参数解析:dataLogdDir=/path1&&#&指定事务日志的存储路径,可以和dataDir在不同设备,这意味着可以使用一个日志的专用磁盘,避免日志IO和快照竞争。
dataDir=/path2&&&&&&#&运行数据的存放路径
tickTime=2000&&&&&&&#&这个时间是作为Zookeeper服务器之间或客户端与服务器之间维持心跳的时间间隔,每隔tickTime时间就会发送一个心跳;最小&的session过期时间为2倍tickTime&
maxClientCnxns=0&&&&#&最大的并发连接数限制,设置为0或者不设置该参数,表示不进行连接数的限制。
minSessionTimeout&&&#&最小的会话超时时间,默认值&minSession=2*tickTime
maxSessionTimeout&&&#&最大的会话超时时间,默认值&maxSession=20*tickTime
initLimit=10&&&&&&&&#&此配置表示,允许follower(相对于Leaderer言的“客户端”)连接并同步到Leader的初始化连接时间,以tickTime为单位。当初始化连接时间超过该值,则表示连接失败。
syncLimit=5&&&&&&&&&#&此配置项表示Leader与Follower之间发送消息时,请求和应答时间长度。如果follower在设置时间内不能与leader通信,那么此follower将会被丢弃。
#&集群模式最关键的配置参数
server.11=192.168.1.21:
#&server.myid=ip:leader_port:inner_port
#&myid&为服务器编号,用于标识服务器,这个值必须和dataDir目录下myid文件中的值保证一致
#&ip&为当前服务器IP,
#&leader_port&&Leader的端口
#&inner_port&&zk服务器之间内部通信端口
#&同一个集群内的服务器,需要把该集群内的服务器列表信息都写在配置文件中。启动服务 & 查看节点的角色分配情况#&192.168.1.21
bin/zkServer.sh&start
bin/zkServer.sh&status
#&ZooKeeper&JMX&enabled&by&default
#&Using&config:&/u01/zookeeper/zookeeper-3.4.9/bin/../conf/zoo.cfg
#&Mode:&leader
#&192.168.1.22
bin/zkServer.sh&start
bin/zkServer.sh&status
#&ZooKeeper&JMX&enabled&by&default
#&Using&config:&/u01/zookeeper/zookeeper-3.4.9/bin/../conf/zoo.cfg
#&Mode:&follower
#&192.168.1.23
bin/zkServer.sh&start
bin/zkServer.sh&status
#&ZooKeeper&JMX&enabled&by&default
#&Using&config:&/u01/zookeeper/zookeeper-3.4.9/bin/../conf/zoo.cfg
#&Mode:&follower由此可见,集群已经正常运行;六、ZooKeeper的四字命令客户端可以通过nc或telnet连接ZooKeeper Server提交指令简单用例:#&检查服务器状态是否正常
echo&ruok&|&nc&localhost&2181
#&输出服务器配置信息
echo&conf&|&nc&localhost&2181
clientPort=2181
dataDir=/u01/zookeeper/zookeeper-3.4.9/data/version-2
dataLogDir=/u01/zookeeper/zookeeper-3.4.9/data/version-2
tickTime=2000
maxClientCnxns=60
minSessionTimeout=4000
maxSessionTimeout=40000
serverId=11
initLimit=10
syncLimit=5
electionAlg=3
electionPort=3888
quorumPort=2888
peerType=0
#&输出服务器状态信息
echo&stat&|&nc&localhost&2181
Zookeeper&version:&3.4.9-1757313,&built&on&08/23/&GMT
&/127.0.0.1:60822[0](queued=0,recved=1,sent=0)
Latency&min/avg/max:&0/1/1591
Received:&200338
Sent:&200389
Connections:&1
Outstanding:&0
Mode:&follower
Node&count:&166七、ZooKeeper Client 简单操作9个基本操作指令:简单用例:#&连接&ZooKeeper&服务器
bin/zkCli.sh&-server&localhost:2181
#&查看根下有哪些节点
[zk:&localhost:2181(CONNECTED)&1]&ls&/
[controller_epoch,&controller,&brokers,&zookeeper,&admin,&isr_change_notification,&consumers,&config]
#&查看&brokers&下有哪些子节点
[zk:&localhost:2181(CONNECTED)&4]&ls&/brokers
[ids,&topics,&seqid]
#&在根下创建一个&"tuchao"&节点,并设置数据为&"hello&zookeeper"
[zk:&localhost:2181(CONNECTED)&5]&create&/tuchao&"hello&zookeeper"
#&查看是否创建成功
[zk:&localhost:2181(CONNECTED)&6]&ls&/
[controller_epoch,&controller,&brokers,&zookeeper,&tuchao,&admin,&isr_change_notification,&consumers,&config]
#&查看&/tuchao&中的数据
[zk:&localhost:2181(CONNECTED)&7]&get&/tuchao
hello&zookeeper
cZxid&=&0x20049ab24
ctime&=&Sun&Oct&09&15:45:02&CST&2016
mZxid&=&0x20049ab24
mtime&=&Sun&Oct&09&15:45:02&CST&2016
pZxid&=&0x20049ab24
cversion&=&0
dataVersion&=&0
aclVersion&=&0
ephemeralOwner&=&0x0
dataLength&=&15
numChildren&=&0
#&可以看到刚刚设置的数据。
#&修改&/tuchao&中的数据为&"Happy&birthday"
[zk:&localhost:2181(CONNECTED)&8]&set&/tuchao&"Happy&birthday"
cZxid&=&0x20049ab24
ctime&=&Sun&Oct&09&15:45:02&CST&2016
mZxid&=&0x20049b2cc
mtime&=&Sun&Oct&09&15:51:17&CST&2016
pZxid&=&0x20049ab24
cversion&=&0
dataVersion&=&1&&&#&可以发现,当数据变更时,数据版本号增加了。
aclVersion&=&0
ephemeralOwner&=&0x0
dataLength&=&14
numChildren&=&0
#&再查看一次&/tuchao&中的数据
[zk:&localhost:2181(CONNECTED)&9]&get&/tuchao
Happy&birthday
cZxid&=&0x20049ab24
ctime&=&Sun&Oct&09&15:45:02&CST&2016
mZxid&=&0x20049b2cc
mtime&=&Sun&Oct&09&15:51:17&CST&2016
pZxid&=&0x20049ab24
cversion&=&0
dataVersion&=&1
aclVersion&=&0
ephemeralOwner&=&0x0
dataLength&=&14
numChildren&=&0
#&给&/tuchao&创建一个子节点&/tuchao/abc1
[zk:&localhost:2181(CONNECTED)&10]&create&/tuchao/abc1&"abc1&node"
Created&/tuchao/abc1
[zk:&localhost:2181(CONNECTED)&11]&ls&/tuchao&&
#&删除节点&/tuchao/abc1
[zk:&localhost:2181(CONNECTED)&0]&delete&/tuchao/abc1
[zk:&localhost:2181(CONNECTED)&1]&ls&/tuchao
#&查看命令帮助,输入&h
[zk:&localhost:2181(CONNECTED)&2]&h
ZooKeeper&-server&host:port&cmd&args
stat&path&[watch]
set&path&data&[version]
ls&path&[watch]
delquota&[-n|-b]&path
ls2&path&[watch]
setAcl&path&acl
setquota&-n|-b&val&path
redo&cmdno
printwatches&on|off
delete&path&[version]
listquota&path
get&path&[watch]
create&[-s]&[-e]&path&data&acl
addauth&scheme&auth
getAcl&path
connect&host:port参考文献:/sunddenly/p/4033574.html本文出自 “” 博客,请务必保留此出处
了这篇文章
类别:未分类┆阅读(0)┆评论(0)zookeeper原理(转) - 翻过这座山,就到菩提洞了 - ITeye技术网站
博客分类:
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,它包含一个简单的原语集,分布式应用程序可以基于它实现同步服务,配置维护和命名服务等。Zookeeper是hadoop的一个子项目,其发展历程无需赘述。在分布式应用中,由于工程师不能很好地使用锁机制,以及基于消息的协调机制不适合在某些应用中使用,因此需要有一种可靠的、可扩展的、分布式的、可配置的协调机制来统一系统的状态。Zookeeper的目的就在于此。本文简单分析zookeeper的工作原理,对于如何使用zookeeper不是本文讨论的重点。
1 Zookeeper的基本概念
Zookeeper中的角色主要有以下三类,如下表所示:
系统模型如图所示:
1.2 设计目的
1.最终一致性:client不论连接到哪个Server,展示给它都是同一个视图,这是zookeeper最重要的性能。
2 .可靠性:具有简单、健壮、良好的性能,如果消息m被到一台服务器接受,那么它将被所有的服务器接受。
3 .实时性:Zookeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。但由于网络延时等原因,Zookeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口。
4 .等待无关(wait-free):慢的或者失效的client不得干预快速的client的请求,使得每个client都能有效的等待。
5.原子性:更新只能成功或者失败,没有中间状态。
6 .顺序性:包括全局有序和偏序两种:全局有序是指如果在一台服务器上消息a在消息b前发布,则在所有Server上消息a都将在消息b前被发布;偏序是指如果一个消息b在消息a后被同一个发送者发布,a必将排在b前面。
2 ZooKeeper的工作原理
Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。
为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。
每个Server在工作过程中有三种状态:
LOOKING:当前Server不知道leader是谁,正在搜寻
LEADING:当前Server即为选举出来的leader
FOLLOWING:leader已经选举出来,当前Server与之同步
2.1 选主流程
当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的Server都恢复到一个正确的状态。Zk的选举算法有两种:一种是基于basic paxos实现的,另外一种是基于fast paxos算法实现的。系统默认的选举算法为fast paxos。先介绍basic paxos流程:
1 .选举线程由当前Server发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的Server;
2 .选举线程首先向所有Server发起一次询问(包括自己);
3 .选举线程收到回复后,验证是否是自己发起的询问(验证zxid是否一致),然后获取对方的id(myid),并存储到当前询问对象列表中,最后获取对方提议的leader相关信息(id,zxid),并将这些信息存储到当次选举的投票记录表中;
收到所有Server回复以后,就计算出zxid最大的那个Server,并将这个Server相关信息设置成下一次要投票的Server;
线程将当前zxid最大的Server设置为当前Server要推荐的Leader,如果此时获胜的Server获得n/2 + 1的Server票数, 设置当前推荐的leader为获胜的Server,将根据获胜的Server相关信息设置自己的状态,否则,继续这个过程,直到leader被选举出来。
通过流程分析我们可以得出:要使Leader获得多数Server的支持,则Server总数必须是奇数2n+1,且存活的Server的数目不得少于n+1.
每个Server启动后都会重复以上流程。在恢复模式下,如果是刚从崩溃状态恢复的或者刚启动的server还会从磁盘快照中恢复数据和会话信息,zk会记录事务日志并定期进行快照,方便在恢复时进行状态恢复。选主的具体流程图如下所示:
fast paxos流程是在选举过程中,某Server首先向所有Server提议自己要成为leader,当其它Server收到提议以后,解决epoch和zxid的冲突,并接受对方的提议,然后向对方发送接受提议完成的消息,重复这个流程,最后一定能选举出Leader。其流程图如下所示:
2.2 同步流程
选完leader以后,zk就进入状态同步过程。
1. leader等待server连接;
2 .Follower连接leader,将最大的zxid发送给leader;
3 .Leader根据follower的zxid确定同步点;
4 .完成同步后通知follower 已经成为uptodate状态;
5 .Follower收到uptodate消息后,又可以重新接受client的请求进行服务了。
流程图如下所示:
2.3 工作流程
2.3.1 Leader工作流程
Leader主要有三个功能:
1 .恢复数据;
2 .维持与Learner的心跳,接收Learner请求并判断Learner的请求消息类型;
3 .Learner的消息类型主要有PING消息、REQUEST消息、ACK消息、REVALIDATE消息,根据不同的消息类型,进行不同的处理。
PING消息是指Learner的心跳信息;REQUEST消息是Follower发送的提议信息,包括写请求及同步请求;ACK消息是Follower的对提议的回复,超过半数的Follower通过,则commit该提议;REVALIDATE消息是用来延长SESSION有效时间。Leader的工作流程简图如下所示,在实际实现中,流程要比下图复杂得多,启动了三个线程来实现功能。
2.3.2 Follower工作流程
Follower主要有四个功能:
1. 向Leader发送请求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息);
2 .接收Leader消息并进行处理;
3 .接收Client的请求,如果为写请求,发送给Leader进行投票;
4 .返回Client结果。
Follower的消息循环处理如下几种来自Leader的消息:
1 .PING消息: 心跳消息;
2 .PROPOSAL消息:Leader发起的提案,要求Follower投票;
3 .COMMIT消息:服务器端最新一次提案的信息;
4 .UPTODATE消息:表明同步完成;
5 .REVALIDATE消息:根据Leader的REVALIDATE结果,关闭待revalidate的session还是允许其接受消息;
6 .SYNC消息:返回SYNC结果到客户端,这个消息最初由客户端发起,用来强制得到最新的更新。
Follower的工作流程简图如下所示,在实际实现中,Follower是通过5个线程来实现功能的。
对于observer的流程不再叙述,observer流程和Follower的唯一不同的地方就是observer不会参加leader发起的投票。
主流应用场景:
Zookeeper的主流应用场景实现思路(除去官方示例) (1)配置管理集中式的配置管理在应用集群中是非常常见的,一般商业公司内部都会实现一套集中的配置管理中心,应对不同的应用集群对于共享各自配置的需求,并且在配置变更时能够通知到集群中的每一个机器。Zookeeper很容易实现这种集中式的配置管理,比如将APP1的所有配置配置到/APP1 znode下,APP1所有机器一启动就对/APP1这个节点进行监控(zk.exist("/APP1",true)),并且实现回调方法Watcher,那么在zookeeper上/APP1 znode节点下数据发生变化的时候,每个机器都会收到通知,Watcher方法将会被执行,那么应用再取下数据即可(zk.getData("/APP1",false,null));以上这个例子只是简单的粗颗粒度配置监控,细颗粒度的数据可以进行分层级监控,这一切都是可以设计和控制的。
(2)集群管理 应用集群中,我们常常需要让每一个机器知道集群中(或依赖的其他某一个集群)哪些机器是活着的,并且在集群机器因为宕机,网络断链等原因能够不在人工介入的情况下迅速通知到每一个机器。Zookeeper同样很容易实现这个功能,比如我在zookeeper服务器端有一个znode叫/APP1SERVERS,那么集群中每一个机器启动的时候都去这个节点下创建一个EPHEMERAL类型的节点,比如server1创建/APP1SERVERS/SERVER1(可以使用ip,保证不重复),server2创建/APP1SERVERS/SERVER2,然后SERVER1和SERVER2都watch /APP1SERVERS这个父节点,那么也就是这个父节点下数据或者子节点变化都会通知对该节点进行watch的客户端。因为EPHEMERAL类型节点有一个很重要的特性,就是客户端和服务器端连接断掉或者session过期就会使节点消失,那么在某一个机器挂掉或者断链的时候,其对应的节点就会消失,然后集群中所有对/APP1SERVERS进行watch的客户端都会收到通知,然后取得最新列表即可。另外有一个应用场景就是集群选master,一旦master挂掉能够马上能从slave中选出一个master,实现步骤和前者一样,只是机器在启动的时候在APP1SERVERS创建的节点类型变为EPHEMERAL_SEQUENTIAL类型,这样每个节点会自动被编号我们默认规定编号最小的为master,所以当我们对/APP1SERVERS节点做监控的时候,得到服务器列表,只要所有集群机器逻辑认为最小编号节点为master,那么master就被选出,而这个master宕机的时候,相应的znode会消失,然后新的服务器列表就被推送到客户端,然后每个节点逻辑认为最小编号节点为master,这样就做到动态master选举。
Zookeeper 监视(Watches) 简介
Zookeeper C API 的声明和描述在 include/zookeeper.h 中可以找到,另外大部分的 Zookeeper C API 常量、结构体声明也在 zookeeper.h 中,如果如果你在使用 C API 是遇到不明白的地方,最好看看 zookeeper.h,或者自己使用 doxygen 生成 Zookeeper C API 的帮助文档。
Zookeeper 中最有特色且最不容易理解的是监视(Watches)。Zookeeper 所有的读操作——getData(), getChildren(), 和 exists() 都 可以设置监视(watch),监视事件可以理解为一次性的触发器, 官方定义如下: a watch event is one-time trigger, sent to the client that set the watch, which occurs when the data for which the watch was set changes。对此需要作出如下理解:
(一次性触发)One-time trigger
当设置监视的数据发生改变时,该监视事件会被发送到客户端,例如,如果客户端调用了 getData("/znode1", true) 并且稍后 /znode1 节点上的数据发生了改变或者被删除了,客户端将会获取到 /znode1 发生变化的监视事件,而如果 /znode1 再一次发生了变化,除非客户端再次对 /znode1 设置监视,否则客户端不会收到事件通知。
(发送至客户端)Sent to the client
Zookeeper 客户端和服务端是通过 socket 进行通信的,由于网络存在故障,所以监视事件很有可能不会成功地到达客户端,监视事件是异步发送至监视者的,Zookeeper 本身提供了保序性(ordering guarantee):即客户端只有首先看到了监视事件后,才会感知到它所设置监视的 znode 发生了变化(a client will never see a change for which it has set a watch until it first sees the watch event). 网络延迟或者其他因素可能导致不同的客户端在不同的时刻感知某一监视事件,但是不同的客户端所看到的一切具有一致的顺序。
(被设置 watch 的数据)The data for which the watch was set
这意味着 znode 节点本身具有不同的改变方式。你也可以想象 Zookeeper 维护了两条监视链表:数据监视和子节点监视(data watches and child watches) getData() and exists() 设置数据监视,getChildren() 设置子节点监视。 或者,你也可以想象 Zookeeper 设置的不同监视返回不同的数据,getData() 和 exists() 返回 znode 节点的相关信息,而 getChildren() 返回子节点列表。因此, setData() 会触发设置在某一节点上所设置的数据监视(假定数据设置成功),而一次成功的 create() 操作则会出发当前节点上所设置的数据监视以及父节点的子节点监视。一次成功的 delete() 操作将会触发当前节点的数据监视和子节点监视事件,同时也会触发该节点父节点的child watch。
Zookeeper 中的监视是轻量级的,因此容易设置、维护和分发。当客户端与 Zookeeper 服务器端失去联系时,客户端并不会收到监视事件的通知,只有当客户端重新连接后,若在必要的情况下,以前注册的监视会重新被注册并触发,对于开发人员来说 这通常是透明的。只有一种情况会导致监视事件的丢失,即:通过 exists() 设置了某个 znode 节点的监视,但是如果某个客户端在此 znode 节点被创建和删除的时间间隔内与 zookeeper 服务器失去了联系,该客户端即使稍后重新连接 zookeeper服务器后也得不到事件通知。
Zookeeper C API 常量与部分结构(struct)介绍
与 ACL 相关的结构与常量:
struct Id 结构为:
struct Id {
struct ACL 结构为:
struct ACL {
struct I };
struct ACL_vector 结构为:
struct ACL_vector {
struct ACL * };
与 znode 访问权限有关的常量
const int ZOO_PERM_READ; //允许客户端读取 znode 节点的值以及子节点列表。
const int ZOO_PERM_WRITE;// 允许客户端设置 znode 节点的值。
const int ZOO_PERM_CREATE; //允许客户端在该 znode 节点下创建子节点。
const int ZOO_PERM_DELETE;//允许客户端删除子节点。
const int ZOO_PERM_ADMIN; //允许客户端执行 set_acl()。
const int ZOO_PERM_ALL;//允许客户端执行所有操作,等价与上述所有标志的或(OR) 。
与 ACL IDs 相关的常量
struct Id ZOO_ANYONE_ID_UNSAFE; //(‘world’,’anyone’)
struct Id ZOO_AUTH_IDS;// (‘auth’,’’)
三种标准的 ACL
struct ACL_vector ZOO_OPEN_ACL_UNSAFE; //(ZOO_PERM_ALL,ZOO_ANYONE_ID_UNSAFE)
struct ACL_vector ZOO_READ_ACL_UNSAFE;// (ZOO_PERM_READ, ZOO_ANYONE_ID_UNSAFE)
struct ACL_vector ZOO_CREATOR_ALL_ACL; //(ZOO_PERM_ALL,ZOO_AUTH_IDS)
与 Interest 相关的常量:ZOOKEEPER_WRITE, ZOOKEEPER_READ
这 两个常量用于标识感兴趣的事件并通知 zookeeper 发生了哪些事件。Interest 常量可以进行组合或(OR)来标识多种兴趣(multiple interests: write, read),这两个常量一般用于 zookeeper_interest() 和 zookeeper_process()两个函数中。
与节点创建相关的常量:ZOO_EPHEMERAL, ZOO_SEQUENCE
zoo_create 函数标志,ZOO_EPHEMERAL 用来标识创建临时节点,ZOO_SEQUENCE 用来标识节点命名具有递增的后缀序号(一般是节点名称后填充 10 位字符的序号,如 /xyz, /xyz, /xyz, ...),同样地,ZOO_EPHEMERAL, ZOO_SEQUENCE 可以组合。
与连接状态 Stat 相关的常量
以下常量均与 Zookeeper 连接状态有关,他们通常用作监视器回调函数的参数。
ZOOAPI const int
ZOO_EXPIRED_SESSION_STATE
ZOOAPI const int
ZOO_AUTH_FAILED_STATE
ZOOAPI const int
ZOO_CONNECTING_STATE
ZOOAPI const int
ZOO_ASSOCIATING_STATE
ZOOAPI const int
ZOO_CONNECTED_STATE
与监视类型(Watch Types)相关的常量
以下常量标识监视事件的类型,他们通常用作监视器回调函数的第一个参数。
Zookeeper C API 错误码介绍
ZSYSTEMERROR
系统或服务器端错误(System and server-side errors),服务器不会抛出该错误,该错误也只是用来标识错误范围的,即大于该错误值,且小于 ZAPIERROR 都是系统错误。
ZRUNTIMEINCONSISTENCY
运行时非一致性错误。
ZDATAINCONSISTENCY
数据非一致性错误。
ZCONNECTIONLOSS
Zookeeper 客户端与服务器端失去连接
ZMARSHALLINGERROR
在 marshalling 和 unmarshalling 数据时出现错误(Error while marshalling or unmarshalling data)
ZUNIMPLEMENTED
该操作未实现(Operation is unimplemented)
ZOPERATIONTIMEOUT
该操作超时(Operation timeout)
ZBADARGUMENTS
非法参数错误(Invalid arguments)
ZINVALIDSTATE
非法句柄状态(Invliad zhandle state)
API 错误(API errors),服务器不会抛出该错误,该错误也只是用来标识错误范围的,错误值大于该值的标识 API 错误,而小于该值的标识 ZSYSTEMERROR。
节点不存在(Node does not exist)
没有经过授权(Not authenticated)
ZBADVERSION
版本冲突(Version conflict)
ZNOCHILDRENFOREPHEMERALS
临时节点不能拥有子节点(Ephemeral nodes may not have children)
ZNODEEXISTS
节点已经存在(The node already exists)
该节点具有自身的子节点(The node has children)
ZSESSIONEXPIRED
会话过期(The session has been expired by the server)
ZINVALIDCALLBACK
非法的回调函数(Invalid callback specified)
ZINVALIDACL
非法的ACL(Invalid ACL specified)
ZAUTHFAILED
客户端授权失败(Client authentication failed)
Zookeeper 连接关闭(ZooKeeper is closing)
并非错误,客户端不需要处理服务器的响应(not error, no server responses to process)
ZSESSIONMOVED
会话转移至其他服务器,所以操作被忽略(session moved to another server, so operation is ignored)
Watch事件类型:
ZOO_CREATED_EVENT:节点创建事件,需要watch一个不存在的节点,当节点被创建时触发,此watch通过zoo_exists()设置ZOO_DELETED_EVENT:节点删除事件,此watch通过zoo_exists()或zoo_get()设置ZOO_CHANGED_EVENT:节点数据改变事件,此watch通过zoo_exists()或zoo_get()设置ZOO_CHILD_EVENT:子节点列表改变事件,此watch通过zoo_get_children()或zoo_get_children2()设置ZOO_SESSION_EVENT:会话失效事件,客户端与服务端断开或重连时触发ZOO_NOTWATCHING_EVENT:watch移除事件,服务端出于某些原因不再为客户端watch节点时触发
浏览 374186
楼主只讲明了zookeeper的架构和大体的实现逻辑,但是缺少对paxos的说明,这个算法是zookeeper的核心,如果这个算法过程不说明,其实zookeeper就讲不清楚。兄台貌似更加理解zookeeper,能否出篇文章分享。
选主过程还是没有看懂看看paxos算法先,不然看这个zookeeper会非常难懂。其实原理简单来说,就是要选举leader,会生成一个zxid,然后分发给所有的server(所以这里一台server可以接受多台server给他发送要选举leader的请求),然后各个server根据发送给自己的zxid,选择一个值最大的,然后将这个选择返回给发送这个zxid的server,只要这个server收到的答复大于等于2/n+1个(也就是超过半数的同意票),则表明自己当选为leader,然后会向所有server广播自己已经成为leader。
对方提议的leader相关信息(id,zxid)请问是怎么提议的,收到那么多zxid,随机给一个么,那么选举线程为何不是随机自己选一个呢这个机制是通过fast paxos算法实现,具体如何提议,如何选择,建议先看看paxos这个算法https://zh.wikipedia.org/zh-cn/Paxos%E7%AE%97%E6%B3%95,维基百科讲的非常清楚。
[/img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][img][/url][/url][/url][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img][/img]
javafan_303
浏览: 590004 次
来自: 北京
好前沿的技术呀
&div class=&quote_title ...
楼主只讲明了zookeeper的架构和大体的实现逻辑,但是缺少 ...

我要回帖

更多关于 zookeeper 原理和实现 的文章

 

随机推荐