在本文中主要涉及三块内容: 第一,就是搭建虚拟机环境;第二,安装ZooKeeper、启动ZooKeeper以及使用内置命令操作ZooKeeper;第三,使用Java API完成操作,以便了解如何在实际的项目中使用。
闲话少说,言归正传,本次的目的是利用VMware搭建一个属于自己的ZooKeeper集群。本次我们选择的是VMware10,具体的安装步骤大家可以到网上搜索,资源很多。
第一步,确定目标:
ZooKeeperOne 192.168.224.100 CentOS
ZooKeeperTwo 192.168.224.201 CentOS
ZooKeeperThree 192.168.224.201 CentOS
我们安装的ZooKeeper是3.4.6版本,可以从这里 下载zookeeper-3.4.6 ; JDK安装的版本是1.7版本
第二步,安装CentOS环境、JDK1.7、配置网络:
此处大家可以参考网上的文章,或者参考我之前写的一篇文章 Hadoop4 利用VMware搭建自己的hadoop集群 ,该文章中的 第一步 到 第八步 涉及了安装基本环境的步骤哦和方法。我们只需要注意一下两点:
(1). 由于我们是在VMware中搭建三个服务器,所以我们可以先搭建一台,待配置都okay后,再利用VMware的克隆功能,直接克隆出另外两台,克隆出的两台只需要注意修改 /etc/sysconfig/network-scripts/ifcfg-eth0 中HWADDR属性、IPADDR 以及 /etc/sysconfig/network 的主机名称HOSTNAME
(2). JDK的安装注意使用JDK1.7,有些ZooKeeper版本在JDK1.6下是不支持的,所以简单一点,我们就直接使用JDK1.7。
第三步,安装配置ZooKeeper:
(1). 从这里 下载zookeeper-3.4.6 ,将文件解压缩,不用安装。以我的为例,我的ZooKeeper路径是: /myself_settings/zookeeper3.4.6/zookeeper-3.4.6,详细如下图:
(2). 需要执行 vi ~/.bash_profile,编辑一下ZooKeeper的环境变量,编辑完毕后执行 source ~/.bash_profile 使配置生效,详细如下图:
(3). 在(1)的zookeeper目录中,有一个conf文件夹,该文件夹中有一个 zoo_sample.cfg 的文件,我们使用命令 mv zoo_sample.cfg zoo.cfg 复制出一个zoo.cfg文件,这个文件就是ZooKeeper启动是时候默认要加载的配置文件,我们可以打开zoo.cfg查看都有哪些配置,并简单了解一下配置的含义,然后我们需要将配置改成如下图中的配置:
(4). 如(3)中的图中的配置,除了我在图中用红色框圈中的属性需要你添加或者修改,其余属性可以使用默认的。对于dataDir和dataLogDir这连个配置,顾名思义,分别是ZooKeeper的数据和日志目录,这个路径可以任意配置,我自己的目录就分别为/opt/zookeeper4.3.6/data 和 /opt/zookeeper4.3.6/log; 对于配置中的最后三行,每一行的格式都形如: server.id=host:port1:port2,其中host就是你的主机名称,port1代表着从(follower)机器连接到主(leader)机器的端口,port2代表着是用来进行leader选举的端口,注意这两个端口与 clientPort=2181 这个端口的含义区别。还有server.id中的id标识的是不同的服务器,在dataDir这个配置的路径下,建立一个名为myid的文件,在文件中只包含一行内容,即所指定的自身的id值,比如服务器"1"应该在myid文件中写入"1"。
(5). 其余两台服务器,注意修改(4)中的提到的这些需要变动的配置。
(6). 经过上边的配置,我们就可以准备启动ZooKeeper了,我么通过执行 zkServer.sh start 就可以将ZooKeeper启动了,其余服务器也直接使用相同命令启动即可。我们也可以使用 zkServer.sh start 指定路径的zoo.cfg文件 这个命令来启动ZooKeeper。启动成功截图详细如下:
第四步,使用客户端命令访问客户端:
(1). 我们可以在服务器上执行 zkCli.sh -server 192.168.224.170:2181 进入客户端,我们可以看到WelCome to ZooKeeper!等文字,详细如下图:
(2). 在客户端中我们了解以下几个命令,大家可以自行在客户端执行体验一下,对于get /zk这个命令执行返回的结果中,每个属性的含义值大家可以参考这片文章初步了解一下。
a. ls / 该命令用来查看当前ZooKeeper中所包含的内容
b. create /zk myData 该命令是创建了一个新的Znode节点zk,其内容是 myData
c. get /zk 该命令是获取已创建节点的信息
d. set /zk hahaha 该命令是对zk这个节点的内容进行设置
e. delete /zk 该命令是删除某个节点
第五步,使用Java API访问ZooKeeper:
其实Java API提供的功能基本也是基于上边的客户端命令来实现的,万变不离其宗,我将我整理的网上的例子贴到下面,大家可以在本地Java工程中执行一下,即可了解调用方法。这里有一点需要注意,我们需要在本地Java工程中引入 ZooKeeper安装包根目录下的zookeeper-3.4.6.jar 和 lib目录中的jar包。
1 import java.util.List; 2 3 import org.apache.zookeeper.CreateMode; 4 import org.apache.zookeeper.WatchedEvent; 5 import org.apache.zookeeper.Watcher; 6 import org.apache.zookeeper.ZooDefs.Ids; 7 import org.apache.zookeeper.ZooKeeper; 8 import org.apache.zookeeper.data.Stat; 9 10 11 /** 12 * @Title ZookeeperDemo0001.java 13 * @Package 14 * @author zhangyi03 15 * @description 基于zookeeper3.4.6,完成第一个zookeeper程序 16 * @date 2015-9-19 下午11:14:20 17 * @version v1.0 18 */ 19 public class ZookeeperDemo0001 { 20 // 会话超时时间,设置为系统默认时间一致 21 private static final int SESSION_TIMEOUT = 30000; 22 23 // 创建ZooKeeper实例 24 ZooKeeper zk; 25 26 // 创建Watcher实例 27 Watcher wh = new Watcher() { 28 public void process(WatchedEvent event) { 29 System.out.println(event.toString()); 30 } 31 }; 32 33 // 初始化ZooKeeper实例 34 private void createZKInstance() throws Exception { 35 zk = new ZooKeeper("192.168.224.170:2181", SESSION_TIMEOUT, wh); 36 } 37 38 private void ZKOperations() throws Exception { 39 System.out.println("/n1. 创建 ZooKeeper 节点 (znode: zoo2, 数据: myData2, " + 40 "权限: OPEN_ACL_UNSAFE, 节点类型: Persistent)"); 41 zk.create("/zoo2", "myData2".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); 42 43 System.out.println("/n2. 查看是否创建成功:"); 44 System.out.println(new String(zk.getData("/zoo2", false, null))); 45 46 System.out.println("/n3. 修改节点数据"); 47 Stat setDataStat = zk.setData("/zoo2", "zhangyi03201509192339".getBytes(), -1); 48 49 50 System.out.println("/n4. 查看是否修改成功:"); 51 System.out.println(new String(zk.getData("/zoo2", false, null))); 52 53 System.out.println("/n5. 添加子节点"); 54 for (int index = 0; index < 3; index++) { 55 zk.create("/zoo2/" + "child_" + (index+1), ("child_" + (index+1)).getBytes(), 56 Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); 57 } 58 59 System.out.println("/n6. 查看所有子节点:"); 60 List<String> childList = zk.getChildren("/zoo2", false); 61 for (String child : childList) { 62 System.out.println("/t/t/t 子节点:" + child); 63 } 64 65 System.out.println("/n7. 删除所有子节点"); 66 for (String child : childList) { 67 zk.delete("/zoo2" + "/" + child, -1); 68 } 69 70 System.out.println("/n8. 删除节点"); 71 zk.delete("/zoo2", -1); 72 73 System.out.println("/n9. 查看节点是否被删除:"); 74 System.out.println("节点状态: [" + zk.exists("/zoo2", false) + "]"); 75 } 76 77 private void ZKClose() throws Exception { 78 zk.close(); 79 } 80 81 /** 82 * @author zhangyi03 83 * @date 2015-9-19 下午11:14:01 84 * @description 85 * @param args 86 */ 87 public static void main(String[] args) throws Exception { 88 ZookeeperDemo0001 demo = new ZookeeperDemo0001(); 89 demo.createZKInstance(); 90 demo.ZKOperations(); 91 demo.ZKClose(); 92 } 93 }
经过上边的五步,我们基本上已经对如何安装ZooKeeper和使用ZooKeeper有了一定的了解,也就是ZooKeeper核心基本内容。这里需要大家再执行上班的Java代码中再主动的查询这样几个问题:
(1). ZooKeeper中的Znode、Watches的含义
(2). ZooKeeper中的永久节点和临时节点的含义和区别
(3). ZooKeeper中的ACL的含义,以及对应的Java代码中的Ids.OPEN_ACL_UNSAFE 等几个属性的含义
(4). ZooKeeper中的cZxid、mZxid等时间戳的含义;version、cversion、aversion等版本号的含义
(5). 我开头提到的如何利用ZooKeeper的节点数据版本号和Java API来实现数据锁
上述这5个问题,都是我在安装和执行测试代码过程中想过的,找到答案也很简单哦,加油!
同时,我在查看ZooKeeper安装目录下的zookeeper-3.4.6/recipes目录中的lock工程时,这是一个"写锁"的实现,基本的思想流程搞明白了,但是看的过程中对代码理解的还不是很深,大家也可以看一下。哎,今天实在是不想再看了,写完博客玩游戏去了,明天晚上再看看那个例子。
各位同仁,加油哈!!!