ZooKeeper
1、下载
这里从一个镜像地址下载,版本为3.5.8的
wget http://mirrors.hust.edu.cn/apache/zookeeper/zookeeper-3.5.8/apache-zookeeper-3.5.8-bin.tar.gz
加压下载后的文件
tar -zxvf apache-zookeeper-3.5.8-bin.tar.gz
2、配置集群信息(这里已三台集群为例)
三台Centos7的ip分别为:
192.168.40.128
192.168.40.129
192.168.40.130
首先在第一台机器(192.168.40.128)上进行配置
2.1 进入解压后的目录
cd apache-zookeeper-3.5.8
2.2 创建zookeeper的数据存放目录
mkdir data
2.3 修改配置文件,由于zookeeper的默认加载配置文件的为zoo.cfg,修改原有的zoo_sample.cfg文件名
cd conf/
mv zoo_sample.cfg ./zoo.cfg
2.4 修改zoo.cfg
vi zoo.cfg
2.5 修改机器的id(进入刚才创建的data目录)
cd /usr/app/apache-zookeeper-3.5.8/data
touch myid
2.6 修改每个机器的id
在myid文件中输入一个数字即可,zoo.cfg中对应的server后面的数字,注意不要有其他的字符
vi myid
2.7 复制文件到其他集群机器(复制过后记得修改data目录下的myid文件中的id号为对应的id)
远程复制命令(复制改好的文件到其他的集群机器root为其他机器登陆的用户名,会提示输入密码,PWD表示要复制到其他机器的目录为当前目录一致)
scp -r apache-zookeeper-3.5.8/ root@192.168.40.128:$PWD
3、启动zookeeper
3.1 关闭防火墙
systemctl status firewalld.service//查看防火墙状态
systemctl stop firewalld.service//关闭防火墙
systemctl disable firewalld.service//关闭防火墙的开机自启动
3.2 安装必要插件
机器必须安装jdk,并且环境变量名称必须为JAVA_HOME
yum -y install gcc automake autoconf libtool make
sudo yum install glibc.i686 www.cit.cn
3.3 启动(进入bin目录)
cd /root/app/apache-zookeeper-3.5.8-bin/bin
./zkServer.sh start
3.4 依次启动三台zookeeper的服务
3.5 查看zookeeper的状态
./zkServer.sh status
机器1:
机器2:
机器3:
如果出现两个follower和一个leader则说明配置成功
4、应用
4.1 选举机制
集群创建成功后,所有节点会进行投票选举(采用paxos算法来进行选举),选出主节点leader,选举的原则是1/2原则,主节点选举成功后,主从之间进行心跳检测,主节点会开辟线程和从节点进行数据同步,主节点负责数据写入,从节点只负责读。
4.2 paxos算法
假设现在有三台机器,分别为:机器1、机器2、机器3
1、三台机器分别开始进行投票,并将投票结果发给其他两人
机器1投票给自己想让自己当leader,并将这个结果发给机器2和机器3
机器2投票给自己想让自己当leader,并将这个结果发给机器1和机器3
2、此时已经达到了1/2原则,由于机器1和机器2的票数是相等的,此时会选出编号大的为leader
所以此时leader已经诞生:为机器2
但是机器3投票给自己想让自己当leader,并将这个结果发给机器1和机器2
这个投票已经无法影响选举结果了,选举结果已经诞生。
3、由于网速或者其他原因的影响,会导致每个机器的选举结果再发送给其他机器时的延时不同,延时高的机器在还没有发送选票时就已经被其他延时低的机器选出了leader。
4、当某一台机器挂掉之后(基于心跳检测判断机器是否存活,心跳时间间隔可以在zoo.cfg中进行修改),其他剩余机器会再次进行选举,重新选出leader
5、当整个集群挂掉1/2以上的机器时,集群不可用,leader选择自杀
4.3 分布式cap定律
c(一致性 )
a(可用性 )
p(分区容错性)
zookeeper实现了cp定律,并不高可用,因为当整个集群挂掉1/2以上时候,集群会导致不可用
mysql集群实现了ap定律
通常在生产环境中zookeeper用奇数台机器
5、常问面试题
zookeeper的选举算法 paxos算法 1/2以上
使用几台zookeeper机器?
问什么使用zookeeper?
6、数据存储结构
树状存储结构,节点是树状结构,每个节点可以设置一个value值
节点有四种类型:
临时节点(存在内存中,一旦集群关闭,节点消失)、
临时有序节点、
永久节点、(持久化到硬盘中的)
永久有序节点
create -e(临时)【-s(有序)】 path value
get path(获取节点的value值)
set path(修改节点的value值)
delete path(删除当前没有子节点的节点)
rmr path(递归删除当前节点以及节点下的所有子节点)
state path(查看当前节点的状态信息)
ls path(遍历当前节点下的所有子节点)
ls2 path(遍历当前节点下的所有子节点以及当前节点的状态信息)
get path watch(监听指定节点的数据变化)
7、客户端操作
6.1 shell命令操作
./zkCli.sh -timeout 5000 -server 192.168.40.128:2181
6.2 java连接
6.2.1 导入依赖
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
6.2.2 实例化ZkClient对象,然后进行操作
ZkClient zkClient=new ZkClient("192.168.40.128:2181");
zkClient.createPersistent("/hebei","shaomeng");
8、zookeper的watch机制(分布式锁的实现)
zookeeper提供了节点的监听机制,当节点变更的时候,zookeeper会通知监听者节点变更(修改或者删除)
ZkClient zkClient=new ZkClient("192.168.40.128:2181,192.168.40.129:2181");
zkClient.subscribeDataChanges("/baidu", new IZkDataListener() {
//节点的值变化
public void handleDataChange(String s, Object o) throws Exception {
System.out.println("节点:"+s+",新值:"+o);
}
//节点数据删除
public void handleDataDeleted(String s) throws Exception {
System.out.println(s+"节点删除");
}
});
9、分布式锁的场景
传统的锁:是指在同一个java进行内,使用synchronized lock锁来保证多线程并发时的数据安全问题。
分布式锁:是指多个进程中的线程,对同s一资源进行修改的时候,会产生数据安全问题,所以必须使用分布式锁来解决并发问题。
//当不同进程的线程想要操作同一资源时候,先通过zooleeper过去分布式锁,之后再更新资源,更新成功后,删除分布式锁。当别的线程监听到了锁的变更,那么就意味着可以放弃本次更新动作,如果监听不到,当达到了等待时长可以默认执行进程的线程出现了意外,可以重新去创建锁之后再去更新资源
public static void main(String[] args) {
ZkClient zkClient=new ZkClient("192.168.40.128:2181,192.168.40.129:2181");
if(zkClient.exists("/lock")){
//如果有人占据了锁,那么去监听锁的标记
zkClient.subscribeDataChanges("/lock", new IZkDataListener() {
public void handleDataChange(String s, Object o) throws Exception {
}
public void handleDataDeleted(String s) throws Exception {
//假如监听到了锁的标记删除了,意味着刚才占据锁的进程操作了mysql数据库
//操作完成mysql数据库后,删除了锁
//那么就可以直接不操作mysql直接退出
}
});
}else {
//如果不存在锁,则去创建锁
//设置锁的时候,一定要给锁设置一个失效时间,因为有可能占据这把锁的进程在运行过程中,由于异常导致代码执行失败没能清空锁
zkClient.create("/lock","1", CreateMode.PERSISTENT);
//获取到了锁,并将值置为1
//然后来操作数据库
//操作数据库。。。。
//并删除锁
zkClient.delete("/lock");
}
}
10、可以充当别的框架的注册中心
为有可能占据这把锁的进程在运行过程中,由于异常导致代码执行失败没能清空锁
zkClient.create("/lock",“1”, CreateMode.PERSISTENT);
//获取到了锁,并将值置为1
//然后来操作数据库
//操作数据库。。。。
//并删除锁
zkClient.delete("/lock");
}
}
## 10、可以充当别的框架的注册中心
zookeeper dubbo官方推荐的注册中心