赞
踩
主要包括两部分:文件系统、通知机制
ZooKeeper维护一个类似Linux文件系统的数据结构,用于存储数据
ZooKeeper是一个基于观察者模式设计的分布式服务管理框架
简单来说,客户端注册监听它关心的目录节点,当目录节点发生变化时,ZooKeeper会通知客户端
ZooKeeper是一个订阅中心(注册中心)
A distributed system is de ned as a software system that is composed of independent computing entities linked together by a computer network whose components communicate and coordinate with each other to achieve a common goal.
分布式系统是由独立的计算机通过网络连接在一起,
并且通过一些组件来相互交流和协作来完成一个共同的目标。
想要更好的判断是否为好的分布式系统,可以看这些特性:
有了ZooKeeper,开发者可以很轻松的实现:
可以想象,假如一台计算机的出错概率为0.1%,那么1000台服务器的出错概率呢?一旦计算机的数量增多,出错的概率就大大的增加。
当然了…ZooKeeper被设计出来的目的就是解决这种类型的问题.
ZooKeeper本身是不提供负载均衡策略的,需要自己实现,所以准确的说,是在负载均衡中使用ZooKeeper来做集群的协调(也称为软负载均衡)。
实现思路:
ZooKeeper一般都运行在Linux平台
ZooKeeper安装包下载地址:http://zookeeper.apache.org/releases.html
tar zxf zookeeper3.4.13.tar.gz
# 创建存放数据文件的目录
cd zookeeper3.4.13/
mkdir data
# 创建配置文件
cd conf
cp zoo_sample.cfg zoo.cfg # 默认使用的是zoo.cfg,名称固定
# 修改配置文件
vi zoo.cfg
dataDir=../data # 指定数据存放目录
cd bin
./zkServer.sh start | stop | status | restart # 启动|停止|查看状态|重启
./zkCli.sh # 启动客户端,默认连接本机的2181端口
或
./zkCli.sh server 服务器地址:端口 # 连接指定主机、指定端口的zookeeper
例如,
./zkCli.sh -server localhost:2181
quit # 退出客户端
[root@ali-master01 bin]# jps # 使用jps查看java进程的信息
1233 activemq.jar
30242 Jps
27517 QuorumPeerMain #这个是zookeeper的进程
399 activemq.jar
windows下的安装zookeeper的操作步骤和Linux的比较相似,有需要的小伙伴网上百度下自行学习下吧。
下面对zookeeper的配置文件zookeeper-3.4.13/conf/zoo.cfg进行下讲解,
配置项 | 描述 | 备注说明 |
---|---|---|
tickTime=2000 | 心跳时间 | 维持心跳的时间间隔,单位是毫秒在zookeeper中所有的时间都是以这个时间为基础单元,进行整数倍配置 |
initLimit=10 | 初始通信时限 | 用于zookeeper集群,此时有多台zookeeper服务器,其中一个 |
为Leader,其他都为Follower | ||
syncLimit=5 | 同步通信时限 | 在运行时Leader通过心跳检测与Follower进行通信,如果超过syncLimit*tickTime时间还未收到响应,则认为该Follower已经宕机 |
dataDir=…/data | 存储数据的目录 | 数据文件也称为snapshot快照文件 |
clientPort=2181 | 端口号 | 默认为2181 |
maxClientCnxns=60 | 单个客户端的最大连接数限制 | 默认为60,可以设置为0,表示没有限制 |
autopurge.snapRetainCount=3 | 保留文件的数量 | 默认3个 |
autopurge.purgeInterval=1 | 自动清理快照文件和事务日志的频率 | 默认为0,表示不开启自动清理,单位是小时 |
dataLogDir= | 存储日志的目录 | 未指定时日志文件也存放在dataDir中,为了性能最大化,一般建议把dataDir和dataLogDir分别放到不同的磁盘上 |
查看指定节点的详细信息: ls2 /
# 子节点名称数组 [zookeeper] # 节点的状态信息,也称为stat结构体 # 创建该znode的事务的zxid(ZooKeeper Transaction ID) # 事务ID是ZooKeeper为每次更新操作/事务操作分配一个全局唯一的id,表示zxid,值越小,表示越先执行 cZxid = 0x0 # 0x0表示十六进制数0 # 创建时间 ctime = Thu Jan 01 08:00:00 CST 1970 # 最后一次更新的zxid mZxid = 0x0 # 最后一次更新的时间 mtime = Thu Jan 01 08:00:00 CST 1970 # 最后更新的子节点的zxid pZxid = 0x0 # 子节点的变化号,表示子节点被修改的次数,1表示从未被修改过 cversion = 1 # 当前节点的变化号,0表示从未被修改过 dataVersion = 0 # 访问控制列表的变化号 access control list aclVersion = 0 # 如果临时节点,表示当前节点的拥有者的sessionId # 如果不是临时节点,则值为0 ephemeralOwner = 0x0 # 数据长度 dataLength = 0 # 子节点数据 numChildren = 1
(create -s /app5 app5)顺序编号节点:
server.20=192.168.4.20:2888:3888
server.21=192.168.4.21:2888:3888
server.22=192.168.4.22:2888:3888
格式: server.A=B:C:D
A表示这台服务器的编号ID,是一个数字
B表示服务器的IP地址或域名
C表示这台服务器与集群中的Leader交换信息时使用的端口
D表示执行选举Leader服务器时互相通信的端口
cd data
echo A的值 > myid
ZooKeeper启动时会读取这个文件,将里面的数字与zoo.cfg中配置的server.A进行比较,从而判断这台服务器是哪个。
选举流程:
总结:
# 在集群的A服务器,监听某个节点值的变化
get /yyy watch
# 在集群的B服务器,修改对应节点的值
set /yyy myyyy
# 此时A服务器会收到事件NodeDataChanged
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/yyy
监听Watch事件是一个一次性的触发器,当数据改变时只会触发一次,如果以后这个数据再发生改变,则不会再次触发。
# 在集群的A服务器,监听某个节点的子节点的变化
ls /yyy watch
# 在集群的B服务器,创建/修改/删除对应节点的子节点
create /yyy/hello hello
# 此时A服务器会收到事件NodeChildrenChanged
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/yyy
<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.13</version>
<type>pom</type>
</dependency>
package com.nick; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.ZooKeeper; import java.io.IOException; import java.util.List; /** * @author wangteng * @version 1.0.0 * @ClassName ZookeeperDemo.java * @Description TODO * @createTime 2019年08月23日 22:26:00 */ public class ZookeeperDemo { /** *@Description: *@Author: wangteng *@date: 2019/8/23 */ public static void main(String[] args) throws IOException, KeeperException, InterruptedException { //1、获取zookeeper的连接 创建zookeeper的客户端 String zkserver_url = "39.96.194.34:2181"; //超时时间,单位:ms毫秒 int sessionTimeout = 13000;//此参数值不能设置太小了,否则会导致会话还没有连接上就报错退出了 ZookeeperWatcher zookeeperWatcher = new ZookeeperWatcher(); ZooKeeper zkclient = new ZooKeeper(zkserver_url, sessionTimeout, zookeeperWatcher); Thread.sleep(3000); System.out.println("客户端的状态信息="+zkclient.getState()); //2、类似客户端的相关的命令 这里调用对应的api接口 List<String> child = zkclient.getChildren("/", false); System.out.println(child); //查看指定节点下的内容 // List<String> children = zkClient.getChildren("/", true);//第二个参数表示是否监视该节点 // System.out.println(children); //创建节点,OPEN_ACL_UNSAFE表示acl权限列表为完全开放,PERSISTENT表示节点类型为持久化节点 // zkClient.create("/world", "世界".getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); //获取节点的数据(节点的值和节点状态Stat) // byte[] data = zkClient.getData("/world", true, null); // System.out.println(new String(data)); // Stat stat = new Stat(); // byte[] data = zkClient.getData("/hello", true, stat); // byte[] data = zkClient.getData("/hello", new DataWatcher(), stat); // System.out.println(new String(data)); // // System.out.println(stat); // System.out.println(stat.getCtime()); // System.out.println(stat.getVersion()); // System.out.println(stat.getDataLength()); //修改节点的数据 // zkClient.setData("/hello","aaa".getBytes(),stat.getVersion()); //第三个参数表示当前节点的数据版本,一般先获取数据stat,然后指定数据版本 // zkClient.setData("/hello", "bbb".getBytes(), 1); //也可以设置为1,表示不检测版本 //删除节点 // zkClient.delete("/hello", 1); //判断节点是否存在 System.out.println(zkclient.exists("/hello",false)); //存在时返回节点状态,不存在则返回null //休眠 // Thread.sleep(1000000); //关闭连接 zkclient.close(); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。