Zookeeper 分布式服务框架是 Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。
实验环境
3台虚拟机,rhel server:
1 2 3
| 172.19.238.62 172.19.238.63 172.19.238.64
|
集群的安装和配置
Zookeeper 的安装非常简单。
下载
最新的版本可以通过官网下载,当前版本为zookeeper-3.4.9。
安装
解压并复制到/usr/local/zookeeper-3.4.9目录
1 2
| # 在当前目录创建data目录 zookeeper-3.4.9 ># mkdir dataDir
|
配置
配置文件在conf目录,需要将默认的zoo_sample.cfg重命名为zoo.cfg,然后编辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| # Zookeeper服务器之间或客户端与服务器之间维持心跳的时间间隔 tickTime=2000 # Zookeeper接受客户端初始化连接时最长能忍受多少个心跳时间间隔数 initLimit=10 # 标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度 syncLimit=5 # Zookeeper保存数据的目录 dataDir=/usr/local/zookeeper-3.4.9/dataDir # 客户端连接端口 clientPort=2181 # server.A=B:C:D # A 是一个数字,表示这个是第几号服务器,也是dataDir中myid文件要写的数字; # B 是这个服务器的 ip 地址; # C 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口; # D 表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口。 # 如果是伪集群的配置方式,由于 B 都是一样,所以不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同的端口号。 server.1=172.19.238.62:2888:3888 server.2=172.19.238.63:2888:3888 server.3=172.19.238.64:2888:3888
|
除了修改zoo.cfg配置文件,集群模式下还要配置一个文件myid,这个文件在dataDir目录下,这个文件里面就有一个数据就是A的值,Zookeeper启动时会读取这个文件,拿到里面的数据与zoo.cfg里面的配置信息比较从而判断到底是哪个server。
3台机器做同样的配置。
启动集群
进入zookeeper-3.4.9/bin目录中,执行
1
| bin ># ./zkServer.sh start
|
当前执行命令所在的目录会生成日志文件:zookeeper.out,打开日志会发现报大量错误,这是因为现在集群只起了1台server,zookeeper服务器端起来会根据zoo.cfg的服务器列表发起选举leader的请求,因为连不上其他机器而报错,那么当我们起第2个zookeeper实例后,leader将会被选出,从而一致性服务开始可以使用,这是因为3台机器只要有2台可用就可以选出leader并且对外提供服务(2n+1台机器,可以容n台机器挂掉)。
启动完集群就可以使用了。
客户端连接
可以先通过zookeeper自带的客户端交互程序来简单感受下zookeeper到底做一些什么事情。
进入zookeeper-3.4.9/bin(3个server中任意一个)下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| bin ># ./zkCli.sh -server 127.0.0.1:2181 ... Welcome to ZooKeeper! ... [zk: 127.0.0.1:2181(CONNECTED) 0] [zk: 127.0.0.1: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
|
大专栏 Zookeeper1 2 3 4 5 6
| ls (查看当前节点数据) ls2 (查看当前节点数据并能看到更新次数等数据) create (创建一个节点) get (得到一个节点,包含数据和更新次数等数据) set (修改节点) delete (删除一个节点)
|
zookeeper使用了一个类似文件系统的树结构,数据可以挂在某个节点上,可以对这个节点进行删改。当改动一个节点的时候,集群中活着的机器都会更新到一致的数据。
java代码使用zookeeper
Zookeeper的使用主要是通过创建其jar包下的Zookeeper实例,并且调用其接口方法进行的,主要的操作就是对znode的增删改操作,监听znode的变化以及处理。
引入zookeeper-3.4.9目录中zookeeper-3.4.9.jar和zookeeper-3.4.9/lib目录中slf4j-api-1.6.1.jar,编写代码测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| package zookeeper01; import java.io.IOException; import java.util.List; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.ZooKeeper; public class { public static void main(String[] args) { try { test(); } catch (IOException | KeeperException | InterruptedException e) { e.printStackTrace(); } } public static void test() throws IOException, KeeperException, InterruptedException{ ZooKeeper zk = new ZooKeeper("172.19.238.62", 500000, new Watcher() { public void process(WatchedEvent event) { } }); zk.create("/root", "mydata".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zk.create("/root/childone", "childone".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); zk.create("/root/childtwo", "childtwo".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); List<String> nodes = zk.getChildren("/root",true); for(String str : nodes){ System.out.println("znode in root : " + str); } byte[] data = zk.getData("/root/childone", true, null); System.out.println("/root/childone data : " + new String(data)); zk.setData("/root/childone", "childmodify".getBytes(), -1); zk.delete("/root/childone", -1); zk.delete("/root/childtwo", -1); zk.close(); } }
|
执行结果:
1 2 3
| znode in root : childone znode in root : childtwo /root/childone data : childone
|
也可以查看集群中每台机器的数据,验证一致性。
zookeeper应用场景
zookeeper从设计模式角度来看,是一个基于观察者模式设计的分布式服务管理框架,负责存储和管理大家都关心的数据,
然后接受观察者的注册,一旦这些数据发生变化,zookeeper就将负责通知已经在zookeeper上注册的那些观察者做出相应
的反应,从而实现集群中类似Master/Slave管理模式。
查看