安装过程
-
解压tar zxf包
-
重命名zoo_sample为zoo
-
修改zoo.cfg的dataDir和logDir*没有就创建
-
开放端口2181
如果安装完成还是连接不上,可以尝试在下图的2个wmnet中禁用一个,因为可能是网络冲突导致
用于分布式项目统一的文件管理(配置文件)
用于服务的注册中心
1.Zokeeper操作
默认端口2182
基本节点操作
1.启动zkServer和引入zookeeper包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-config</artifactId>
</dependency>
2.开启连接
zooKeeper = new ZooKeeper("172.16.1.136:2181",50000,null);
3.创建节点
String result = zooKeeper.create("/javaNode/mynode", "java".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.err.println(result);
4.修改节点
Stat stat = zooKeeper.setData("/javaNode/mynode", "mysql".getBytes(), -1);
if(stat != null){
System.err.println(stat.getVersion());
}
5.修改节点
/*修改节点数据,版本默认-1,每次操作+1*/
Stat stat = zooKeeper.setData("/javaNode/mynode", "mysql".getBytes(), -1);
if(stat != null){
System.err.println(stat.getVersion());
}
6.删除节点
zooKeeper.delete("/javaNode/mynode",-1);
7.获取节点的描述信息
Stat exists = zooKeeper.exists("/javaNode/mynode", false);
if(exists != null){
System.err.println(exists.getAversion());
System.err.println(exists.getCtime());
System.err.println(exists.getDataLength());
System.err.println(exists.getNumChildren());
}
8.获取所有的子节点
List<String> children = zooKeeper.getChildren("/", null);
for (String child : children) {
System.out.println(child);
}
监控操作Watch
watch用于监控zookeeper节点的变化,比如当子节点删除时,用于通知其他的程序进行相应的操作
1.重写Watch方法
class Mywatch implements Watcher{
@Override
public void process(WatchedEvent watchedEvent) {
System.out.println("发生变化的路径:"+watchedEvent.getPath());
System.out.println("发生变化的状态:"+watchedEvent.getState());
System.out.println("发生变化的类型:"+watchedEvent.getType());
System.out.println("发生变化的warp:"+watchedEvent.getWrapper());
}
}
2.调用该watch类(exist方法是可以监听创建,而getData无法监听创建)
exist方法是可以监听创建,而getData无法监听创建
getChildren()方法是可以监听创建和删除,但是不能监听子节点的修改
@Test
public void watchTest() throws IOException, KeeperException, InterruptedException {
ZooKeeper zooKeeper = new ZooKeeper("172.16.1.136:2181",50000,null);
/*exist方法是可以监听创建,而getData无法监听创建*/
//byte[] data = zooKeeper.getData("/javaNode", new Mywatch(), null);
/*getChildren()方法是可以监听创建和删除,但是不能监听子节点的修改*/
//List<String> children = zooKeeper.getChildren("/javaNode", new Mywatch());
Stat exists = zooKeeper.exists("/javaNode", new Mywatch());
System.out.println("是否存在结果:"+exists);
while (true) {
}
}
3.当节点无变化时(此时已存在一个/javaNode的节点)
- 这时候,如果对该节点进行删除操作
delete /javaNode
结果:
- 创建节点
create /javaNode java1
结果:
控制台没有发生变化,因为这个监控器watch是一次触发,监听了一次结束就没了
2.应用场景
当分布式开发项目之中存在一个集群,zookeeper将他们的共有的配置文件集中管理,当其中配置文件发生改动时,可以通过监听,及时更新到各个所连接节点上的服务器上,确保配置文件的一致性
当其中一台集群中的服务器故障之后,通过监听可以反映到服务器集群中(临时节点断掉,父节点可以接受到节点断掉的变化),从而及时剔除该故障服务器(从配置文件之中删除故障服务器的配置),以免造成故障服务器还接受请求的情况
- 保持独占:通过写入数据成功,就添加一个特有的节点,这个节点就是锁,其他程序只能等待
- 控制时序:创建顺序节点,编号最小的那个节点可以先拿到锁
3.Zookeeper服务注册和发现
- 服务提供者开发结束就在zookeeper添加一个节点
- 服务消费者要使用服务的时候,先访问zookeeper查看特定服务节点,对发现的几个服务发送请求
- 当服务提供者新增或者删除服务,都会在zookeeper上进行注册,但是服务消费者并不关系服务的变化,能处理自己的请求就可以了,这样一来,达到一个解耦的效果.
zookeeper可以在长连接的时候可以代替一个反向代理的作用,通过特定的算法,将固定ip地址的连接,通过注册中心,发送给对应的服务
4.Zookeeper集群
通过选举一台leader的Zookeeper服务,把控整个集群节点的添加和删改
过半数存活原则
追随者再将结果写入客户端
过半数存活原则
:一半以上的节点(搭建奇数台服务)写入成功(投票成功),leader则判断该节点有效,则提交当前写入操作
脑裂
:一个完整的zookeeper集群的五台服务,其中两台和另三台断网,但是这两台互相同步,那么这两台组成一个集群,重选leader,但是由于过半数存活原则,导致该服务无法进行(永远达不到过半)的情况
3.
伪集群搭建
单台机器搭建n个Zookeeper服务
配置name | 解释 |
---|---|
tickTime | 心跳间隔时间 |
dataDir | 数据目录 |
clientPort | 客户端连接端口 |
initLimit | 初始化连接和leader连接的超时过期时间 |
syncLimit | 配置leader和follower之间发送消息,请求和应答最大时间长度(2则代表2倍tickTime) |
1.复制三份zookeeper解压的文件,分别命名
2.配置zoo.config
- 配置第1个zoo.cfg
dataDir=E:/zookeeper-3.4.11/data1
dataLogDir=E:/zookeeper-3.4.11/logs1
clientPort=2181
#serverid :是当前zookeeper服务器的id(data/myid的编号)
#2888成为leader之后的端口,用来监听follower的请求
#3888代表选举端口,每一个服务器开始选举的时候,发送投票的端口
server.1=172.16.1.136:2888:3888
server.2=172.16.1.136:2889:3889
server.3=172.16.1.136:2890:3890
- 配置第2个zoo.cfg
dataDir=E:/zookeeper-3.4.11/data2
dataLogDir=E:/zookeeper-3.4.11/logs2
clientPort=2182
server.1=172.16.1.136:2888:3888
server.2=172.16.1.136:2889:3889
server.3=172.16.1.136:2890:3890
- 配置第3个zoo.cfg
dataDir=E:/zookeeper-3.4.11/data3
dataLogDir=E:/zookeeper-3.4.11/logs3
clientPort=2183
server.1=172.16.1.136:2888:3888
server.2=172.16.1.136:2889:3889
server.3=172.16.1.136:2890:3890
修改三个zookeeper的myid
- 从配置的data文件夹进入,创建myid文件
- 分别配置1;2;3
按顺序启动第1;2;3个zkServer
启动第一个(无法选举leader),第二个会报错(和脑裂结果一样,无法半数原则),当启动第三个,前两个报错会解除
这时候启动zkCli,在2181上创建一个节点
create /zNode alpha
查看根节点下的所有节点
ls /
转而连接到2182
connect 127.0.0.1:2182
查看2182上的节点
ls /
可以看到从2181创建的zNode,集群搭建完成
ZAB协议
ZAB协议:(原子消息协议)在zookeeper的所有事务都由一个主服务器也就是leader来处理,其服务器为follower,leader将所有客户端的事务请求转换为事务proposal(提议,请求),并且将它分发给集群中的其他follower,然后leader等待follower反馈,当过半数>n/2+1,leader广播给所以follower发布commit信息,将之前的proposal提交