zookeeper
介绍
zookeeper是一个为分布式应用提供一致性服务的软件,它是开源的
Hadoop项目中的一个子项目,并且根据
google发表的
<The Chubby lock service for loosely-coupled distributed systems>论文来实现的,接下来我们首先来安装使用下这个软件,然后再来探索下其中比较重要一致性算法。
zookeeper安装和使用
zookeeper的安装基本上可以按照
http://hadoop.apache.org/zookeeper/docs/current/ zookeeperStarted.html 这个页面上的步骤完成安装,这里主要介绍下部署一个集群的步骤,因为这个官方页面似乎讲得并不是非常详细
(Running Replicated Zookeeper)。
由于手头机器不足,所以在一台机器上部署了
3个
server,如果你手头也比较紧,也可以这么做。那么我建了
3个文件夹,如下
server1 server2 server3
然后每个文件夹里面解压一个
zookeeper的下载包,并且还建了几个文件夹,总体结构如下
,最后那个是下载过来压缩包的解压文件
data dataLog logs zookeeper-3.3.2
那么首先进入
data目录,创建一个
myid的文件,里面写入一个数字,比如我这个是
server1,那么就写一个
1,
server2对应
myid文件就写入
2,
server3对应myid文件就写个
3
然后进入
zookeeper-3.3.2/conf
目录,那么如果是刚下过来,会有
3个文件,
configuration.xml, log4j.properties,zoo_sample.cfg
,这
3个文件我们首先要做的就是在这个目录创建一个
zoo.cfg的配置文件,当然你可以把
zoo_sample.cfg文件改成
zoo.cfg,配置的内容如下所示:
tickTime=2000
initLimit=5
syncLimit=2
dataDir=xxxx/zookeeper/server1/data
dataLogDir=xxx/zookeeper/server1/dataLog
clientPort=2181
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890
标红的几个配置应该官网讲得很清楚了,只是需要注意的是
clientPort这个端口如果你是在
1台机器上部署多个
server,那么每台机器都要不同的
clientPort,比如我
server1是
2181,server2是
2182,
server3是
2183,
dataDir和
dataLogDir也需要区分下。
最后几行唯一需要注意的地方就是
server.X 这个数字就是对应
data/myid中的数字。你在
3个
server的
myid文件中分别写入了
1,
2,
3,那么每个
server中的
zoo.cfg都配
server.1,server.2,server.3就
OK了。因为在同一台机器上,后面连着的
2个端口
3个
server都不要一样,否则端口冲突,其中第一个端口用来集群成员的信息交换,第二个端口是在
leader挂掉时专门用来进行选举
leader所用。
进入
zookeeper-3.3.2/bin 目录中,./
zkServer.sh start
启动一个
server,这时会报大量错误?其实没什么关系,因为现在集群只起了
1台
server,
zookeeper服务器端起来会根据
zoo.cfg的服务器列表发起选举
leader的请求,因为连不上其他机器而报错,那么当我们起第二个
zookeeper实例后,
leader将会被选出,从而一致性服务开始可以使用,这是因为
3台机器只要有
2台可用就可以选出
leader并且对外提供服务
(2n+1台机器,可以容
n台机器挂掉
)。
接下来就可以使用了,我们可以先通过
zookeeper自带的客户端交互程序来简单感受下
zookeeper到底做一些什么事情。进入
zookeeper-3.3.2/bin(
3个
server中任意一个)下,
./zkCli.sh –server 127.0.0.1:2182
,我连的是开着
2182端口的机器。
那么,首先我们随便打个命令,因为
zookeeper不认识,他会给出命令的
help,如下图
ls(查看当前节点数据
),
ls2(查看当前节点数据并能看到更新次数等数据
) ,
create(创建一个节点
) ,
get(得到一个节点,包含数据和更新次数等数据
),
set(修改节点
)
delete(删除一个节点
)
通过上述命令实践,我们可以发现,
zookeeper使用了一个类似文件系统的树结构,数据可以挂在某个节点上,可以对这个节点进行删改。另外我们还发现,当改动一个节点的时候,集群中活着的机器都会更新到一致的数据。
zookeeper
的数据模型
在简单使用了
zookeeper之后,我们发现其数据模型有些像操作系统的文件结构,结构如下图所示
(1)
每个节点在
zookeeper中叫做
znode,并且其有一个唯一的路径标识,如
/SERVER2节点的标识就为
/APP3/SERVER2
(2)
Znode可以有子
znode,并且
znode里可以存数据,但是
EPHEMERAL类型的节点不能有子节点
(3)
Znode中的数据可以有多个版本,比如某一个路径下存有多个数据版本,那么查询这个路径下的数据就需要带上版本。
(4)
znode 可以是临时节点,一旦创建这个
znode 的客户端与服务器失去联系,这个
znode 也将自动删除,
Zookeeper 的客户端和服务器通信采用长连接方式,每个客户端和 服务器通过心跳来保持连接,这个连接状态称为
session,如果
znode 是临时节点,这个
session 失效,
znode 也就删除了
(5)
znode 的目录名可以自动编号,如
App1 已经存在,再创建的话,将会自动命名为
App2
(6)
znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是
zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的集中管理,集群管理,分布式锁等等。
通过
java代码使用
zookeeper
Zookeeper
的使用主要是通过创建其
jar
包下的
Zookeeper
实例,并且调用其接口方法进行的,主要的操作就是对
znode
的增删改操作,监听
znode
的变化以及处理。
以下为主要的
API
使用和解释
//
创建一个Zookeeper实例,第一个参数为目标服务器地址和端口,第二个参数为Session超时时间,第三个为节点变化时的回调方法
ZooKeeper zk
=
new
ZooKeeper(
"
127.0.0.1:2181
"
,
500000
,
new
Watcher()
{
//
监控所有被触发的事件
public
void
process(WatchedEvent event)
{
//
dosomething
}
}
);
//
创建一个节点root,数据是mydata,不进行ACL权限控制,节点为永久性的(即客户端shutdown了也不会消失)
zk.create(
"
/root
"
,
"
mydata
"
.getBytes(),Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
//
在root下面创建一个childone znode,数据为childone,不进行ACL权限控制,节点为永久性的
zk.create(
"
/root/childone
"
,
"
childone
"
.getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
//
取得/root节点下的子节点名称,返回List<String>
zk.getChildren(
"
/root
"
,
true
);
//
取得/root/childone节点下的数据,返回byte[]
zk.getData(
"
/root/childone
"
,
true
,
null
);
//
修改节点/root/childone下的数据,第三个参数为版本,如果是-1,那会无视被修改的数据版本,直接改掉
zk.setData(
"
/root/childone
"
,
"
childonemodify
"
.getBytes(),
-
1
);
//
删除/root/childone这个节点,第二个参数为版本,-1的话直接删除,无视版本
zk.delete(
"
/root/childone
"
,
-
1
);
//
关闭session
zk.close();
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
类型,这样每个节点会自动被编号,例如
zk.create(
"
/testRootPath/testChildPath1
"
,
"
1
"
.getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
zk.create(
"
/testRootPath/testChildPath2
"
,
"
2
"
.getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
zk.create(
"
/testRootPath/testChildPath3
"
,
"
3
"
.getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
//
创建一个子目录节点
zk.create(
"
/testRootPath/testChildPath4
"
,
"
4
"
.getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println(zk.getChildren(
"
/testRootPath
"
,
false
));
打印结果:
[testChildPath10000000000, testChildPath20000000001, testChildPath40000000003, testChildPath30000000002]
zk.create(
"
/testRootPath
"
,
"
testRootData
"
.getBytes(),Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
//
创建一个子目录节点
zk.create(
"
/testRootPath/testChildPath1
"
,
"
1
"
.getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);
zk.create(
"
/testRootPath/testChildPath2
"
,
"
2
"
.getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);
zk.create(
"
/testRootPath/testChildPath3
"
,
"
3
"
.getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);
//
创建一个子目录节点
zk.create(
"
/testRootPath/testChildPath4
"
,
"
4
"
.getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);
System.out.println(zk.getChildren(
"
/testRootPath
"
,
false
));
打印结果:
[testChildPath2, testChildPath1, testChildPath4, testChildPath3]
我们默认规定编号最小的为
master,
所以当我们对
/APP1SERVERS
节点做监控的时候,得到服务器列表,只要所有集群机器逻辑认为最小编号节点为
master
,那么
master
就被选出,而这个
master
宕机的时候,相应的
znode
会消失,然后新的服务器列表就被推送到客户端,然后每个节点逻辑认为最小编号节点为
master
,这样就做到动态
master
选举。
总结
我们初步使用了一下
zookeeper并且尝试着描述了几种应用场景的具体实现思路,接下来的文章,我们会尝试着去探究一下
zookeeper的高可用性与
leaderElection算法。
分享到:
相关推荐
dubbo概述,简要描述了一下dubbo以及zookeeper的使用和原理
Zookeeper的搭建、底层原理以及Java客户端的操作,如:zkclient,curator等
Zookeeper入门及其原理介绍以及一些简单的应用
深入分析zookeeper实现原理
从Paxos到Zookeeper分布式一致性原理与实践.pdf从Paxos到Zookeeper分布式一致性原理与实践.pdf从Paxos到Zookeeper分布式一致性原理与实践.pdf从Paxos到Zookeeper分布式一致性原理与实践.pdf从Paxos到Zookeeper分布式...
zookeeper的通俗原理解释,能让初学者通过比较通俗的解释了解原理
1)Zookeeper概述、原理及应用汇总 2)Zookeeper分布式服务框架内容总结:包括四字命令、命令行工具操作、目标、概念、 Zookeeper结构等说明 3)4大应用场景(配置中心、集群管理、等) 4)Linux Evi集群(三台PC)部署
从PAXOS到ZOOKEEPER分布式一致性原理与实践从PAXOS到ZOOKEEPER分布式一致性原理与实践从PAXOS到ZOOKEEPER分布式一致性原理与实践
ZooKeeper 原理及其在 Hadoop 和 HBase 中的应用,详细讲解ZooKeeper的原来和使用方法。
Zookeeper部署及原理说明,内涵zookeeper的发布步骤。
zookeeper的理论原理 xmind文件
从Paxos到Zookeeper 分布式一致性原理与实践
该文件详细的介绍了zookeeper的设计原理,主要对选举和事务进行说明。还列举了一些应用场景,值得一看
同时,本书深入介绍了分布式一致性问题的工业解决方案——ZooKeeper,并着重向读者展示这一分布式协调框架的使用方法、内部实现及运维技巧,旨在帮助读者全面了解ZooKeeper,并更好地使用和运维ZooKeeper。...
ZooKeeper 是一个开源的分布式协调服务,ZooKeeper 框架最初是在“Yahoo!"上构建的,用于以简单而稳健的方式访问他们的应用程序。
ZooKeeper是一个高可用的分布式数据管理与系统协调框架。基于对Paxos 算法的实现,使该框架保证了分布式环境中数据的强一致性,也正是基于这样的特性,使得zookeeper 能够应用于很多场景。网上对zk的使用场景也有...
从Paxos到Zookeeper分布式一致性原理与实践 + ZooKeeper-分布式过程协同技术详解
从Paxos到Zookeeper 分布式一致性原理与实践 PDF电子书下载 带目录书签 完整版.pdf
从Paxos到Zookeeper分布式一致性原理与实践包括源码推荐给需要学习的童鞋