Zookeeper
Zookeeper 分布式服务框架是 Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。
实验环境
3台虚拟机,rhel server:
123 | 172.19.238.62172.19.238.63172.19.238.64 |
集群的安装和配置
Zookeeper 的安装非常简单。
下载
最新的版本可以通过官网下载,当前版本为zookeeper-3.4.9。
安装
解压并复制到/usr/local/zookeeper-3.4.9目录
12 | # 在当前目录创建data目录zookeeper-3.4.9 ># mkdir dataDir |
配置
配置文件在conf目录,需要将默认的zoo_sample.cfg重命名为zoo.cfg,然后编辑:
123456789101112131415161718192021222324 | # 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:3888server.2=172.19.238.63:2888:3888server.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中任意一个)下
12345678910111213141516171819202122232425262728 | 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] helpZooKeeper -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 |
123456 | 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,编写代码测试:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960 | 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) { } }); //创建一个节点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); zk.create("/root/childtwo", "childtwo".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); //取得/root节点下的子节点名称,返回List<String> List<String> nodes = zk.getChildren("/root",true); for(String str : nodes){ System.out.println("znode in root : " + str); } //取得/root/childone节点下的数据,返回byte[] byte[] data = zk.getData("/root/childone", true, null); System.out.println("/root/childone data : " + new String(data)); //修改节点/root/childone下的数据,第三个参数为版本,如果是-1,那会无视被修改的数据版本,直接改掉 zk.setData("/root/childone", "childmodify".getBytes(), -1); //删除/root/childone这个节点,第二个参数为版本,-1的话直接删除,无视版本 zk.delete("/root/childone", -1); zk.delete("/root/childtwo", -1); zk.close(); }} |
执行结果:
123 | znode in root : childoneznode in root : childtwo/root/childone data : childone |
也可以查看集群中每台机器的数据,验证一致性。
zookeeper应用场景
zookeeper从设计模式角度来看,是一个基于观察者模式设计的分布式服务管理框架,负责存储和管理大家都关心的数据,
然后接受观察者的注册,一旦这些数据发生变化,zookeeper就将负责通知已经在zookeeper上注册的那些观察者做出相应
的反应,从而实现集群中类似Master/Slave管理模式。