原文地址: http://blog.csdn.net/nsrainbow/article/details/42836479 最新课程请关注原作者博客,获得更好的显示体验

声明

  • 本文基于Centos 6.x + CDH 5.x

zookeeper有什么用

    看了之前的教程,会发现多处出现zookeeper,比如hadoop的 auto failover 得用 zookeeper ,Hbase 的 RegionServer 也得用zookeeper。其实不止hadoop,包括现在小有名气的 Storm 用的也是zookeeper。那么zookeeper 究竟是做什么用的?
  • ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务。
  • ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户
  • ZooKeeper包含一个简单的原语集,提供Java和C的接口。
    在Zookeeper中,znode是一个跟Unix文件系统路径相似的节点,可以往这个节点存储或获取数据。如果在创建znode时Flag设置为EPHEMERAL,那么当创建这个znode的节点和Zookeeper失去连接后,这个znode将不再存在在Zookeeper里,Zookeeper使用Watcher察觉事件信息。当客户端接收到事件信息,比如连接超时、节点数据改变、子节点改变,可以调用相应的行为来处理数据。Zookeeper的Wiki页面展示了如何使用Zookeeper来处理事件通知,队列,优先队列,锁,共享锁,可撤销的共享锁,两阶段提交。

简单的说: 通过在zookeeper里面注册znode节点,可以做两件事情
  • 对于分布式服务来说,通过zookeeper可以作为管理节点的一个桥梁,就拿Hbase来说,当你增加一个regionserver的时候根本不需要去master那里去增加一些配置,你只需要在regionserver上配置好zookeeper的地址,master隔几秒会去zookeeper上看下,是否有多了regionserver,如果有就自动使用了,master,regionserver都在zookeeper上注册着,所以jdbc连接也只要去zookeeper上查就可以知道该连哪个master
  • 我们可以自动监控这些节点是否活着,而不用手动去实现这些事情,所以zookeeper解决了用户想知道节点“是否活着?”的问题

快速开始

安装

服务端,在每一台需要监控的机器上安装

yum install zookeeper-server

客户端
yum install zookeeper-client

配置

编辑 /etc/zookeeper/conf/zoo.cfg ,所有机器上的 zoo.cfg 这个文件都是一样的
maxClientCnxns=50
# 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.
dataDir=/var/lib/zookeeper
# the port at which the clients will connect
clientPort=2181
server.1=host1:2888:3888
server.2=host2:2888:3888

  • tickTime 单位是毫秒,被用作计算会话超时时间和心跳时间的最小单位,这两个时间会被表示成 tickTime 的倍数,而不是直接写上毫秒数,不懂这样设计的好处在哪里,不过至少用户简单了一点,只需要写上倍数就行了
  • dataDir 存储内存数据的快照或者关于事务的更新日志
  • clientPort 给客户端使用的端口

使用

在所有机器上启动zookeeper
service zookeeper-server start


使用 zookeeper-client 进入客户端
[zk: localhost:2181(CONNECTED) 0] 

使用help命令看看有什么可以用的命令
[zk: localhost:2181(CONNECTED) 0] help
ZooKeeper -server host:port cmd args
	connect host:port
	get path [watch]
	ls path [watch]
	set path data [version]
	rmr path
	delquota [-n|-b] path
	quit 
	printwatches on|off
	create [-s] [-e] path data acl
	stat path [watch]
	close 
	ls2 path [watch]
	history 
	listquota path
	setAcl path acl
	getAcl path
	sync path
	redo cmdno
	addauth scheme auth
	delete path [version]
	setquota -n|-b val path

我们来试试看最简单的 ls 命令
[zk: localhost:2181(CONNECTED) 1] ls /
[hadoop-ha, hbase, zookeeper]
[zk: localhost:2181(CONNECTED) 2] ls /hadoop-ha
[mycluster]


可以看到下面有三个节点,hadoop-ha 下面还有一个节点。这都是因为我之前的教程已经安装了hadoop和hbase所以会有这些节点。做到这里,我们明白了,zookeeper维持了一个类似文件夹结构的空间,在这个空间内存储的东西就是znode,znode可以有自己的子节点

创建节点


接下来,我们试试创建一个新的节点
[zk: localhost:2181(CONNECTED) 3] create /zk_test my_data
Created /zk_test
[zk: localhost:2181(CONNECTED) 4] ls /
[hadoop-ha, hbase, zookeeper, zk_test]

这个zk_test 是我们要建立的节点名字,my_data 是节点的数据。
我们可以用get命令看下节点的数据

节点数据


[zk: localhost:2181(CONNECTED) 5] get /zk_test
my_data
cZxid = 0x2200000019
ctime = Sun Jan 18 02:30:56 PST 2015
mZxid = 0x2200000019
mtime = Sun Jan 18 02:30:56 PST 2015
pZxid = 0x2200000019
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 7
numChildren = 0

在讲解这些参数之前先介绍一下一个概念:
ZooKeeper以多种方式跟踪时间
  • zxid:每次修改ZooKeeper状态都会收到一个zxid形式的时间戳,也就是ZooKeeper事务ID。事务ID是ZooKeeper中所有修改总的次序。每个修改都有唯一的zxid,如果zxid1小于zxid2,那么zxid1在zxid2之前发生。
  • 版本号:对节点的每次修改将使得节点的版本号增加一。版本号有三种:version(znode数据修改的次数)、cversion(znode子节点修改的次数),以及aversion(znode的ACL修改次数)。
  • tick:多服务器ZooKeeper中,服务器使用tick来定义状态上传、会话超时、节点间连接超时等事件的时序。tick仅被最小会话超时(2倍的tick时间)间接使用:如果客户端要求小于最小会话超时的时间,服务器将告知客户端,实际使用的是最小会话超时。
  • 真实时间:除了在创建和修改znode时将时间戳放入stat结构体中之外,ZooKeeper不使用真实时间,或者说时钟时间。
get获得的参数的意思是:
  • czxid:创建节点的事务的zxid
  • mzxid:对znode最近修改的zxid
  • ctime:以距离时间原点(epoch)的毫秒数表示的znode创建时间
  • mtime:以距离时间原点(epoch)的毫秒数表示的znode最近修改时间
  • pzxid:子节点的最后版本
  • cversion:znode子节点修改次数
  • dataVersion:数据的版本
  • aclVersion:znode的ACL修改次数
  • ephemeralOwner:如果znode是临时节点,则指示节点所有者的会话ID;如果不是临时节点,则为零。
  • dataLength:znode数据长度。
  • numChildren:znode子节点个数。

修改节点


不需要完全看懂以上这些参数,我们可以试着修改一下数据再看
[zk: localhost:2181(CONNECTED) 6] set /zk_test junk
cZxid = 0x2200000019
ctime = Sun Jan 18 02:30:56 PST 2015
mZxid = 0x220000001a
mtime = Sun Jan 18 02:55:35 PST 2015
pZxid = 0x2200000019
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
[zk: localhost:2181(CONNECTED) 7] get /zk_test
junk
cZxid = 0x2200000019
ctime = Sun Jan 18 02:30:56 PST 2015
mZxid = 0x220000001a
mtime = Sun Jan 18 02:55:35 PST 2015
pZxid = 0x2200000019
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0

再对比一下之前的参数,会发现以下参数改变了
  • mZxid :变为另一个数据,表示最后修改的版本
  • mtime:最后修改时间变了
  • dataVersion:从0变成1,表示数据的版本增加了1
  • dataLength:数据长度变化了

什么是ACL

    ZooKeeper使用ACL控制对节点的访问。ACL的实现同Unix文件访问权限非常相似:采用权限位来定义允许/禁止的各种节点操作,以及位应用的范围。与标准Unix权限不同的是,ZooKeeper节点不由用户(文件所有者)、组和其他这三个标准范围来限制。ZooKeeper没有节点所有者的概念。取而代之的是,ACL指定一个ID集合,以及与这些ID相关联的权限。
    还要注意的是,ACL仅仅用于某特定节点。特别是,ACL不会应用到子节点。比如说,/app只能被ip:172.16.16.1读取,/app/status可以被所有用户读取。ACL不是递归的。ZooKeeper支持可插入式鉴权模式。使用scheme:id的形式指定ID,其中scheme是id对应的鉴权模式。比如说,ip:172.16.16.1是地址为172.16.16.1的主机的ID。
    客户端连接到ZooKeeper,验证自身的时候,ZooKeeper将所有对应客户端的ID都关联到客户端连接上。客户端试图存取节点的时候,ZooKeeper会在节点的ACL中校验这些ID。ACL由(scheme:expression,perms)对组成。expression的格式是特定于scheme的。比如说,(ip:19.22.0.0/16,READ)给予任何IP地址以19.22开头的客户端以READ权限。

只需要知道概念就行了,具体的使用等需要的时候再学习。

删除节点


[zk: localhost:2181(CONNECTED) 8] delete /zk_test
[zk: localhost:2181(CONNECTED) 9] ls /
[hadoop-ha, hbase, zookeeper]

可以看到节点被删除了

总结

     其实这个教程只是让你知道了zookeeper是如何管理节点的,但是没有说明zookeeper是如何监听节点和标记节点的,因为那些有点复杂并且对我们普通开发者其实作用不太大,这些一般是 hadoop或者storm 的开发者需要考虑的问题。我们作为最终用户只需要对zookeeper是个怎样的东西,究竟是长什么样子有一个感性的认识就可以了。

参考资料

  • http://zookeeper.apache.org/doc/trunk/zookeeperStarted.html
  • http://zookeeper.apache.org/doc/trunk/zookeeperProgrammers.html#sc_zkDataModel_znodes
  • http://blog.163.com/wm_at163/blog/static/132173490201232423051163/


Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐