1、Zookeeper简介
zookepeer是一个分布式协调中间件,主要的作用:分布式锁、Leader选举、服务注册中心、配置中心等
2、Zookeeper的数据结构
Zookeeper的数据模型类似于文件系统,是树状结构,每个树节点(目录)对应一个Znode节点。
可以通过路径唯一确定到一个Znode,如/animal/cat
3、Znode的数据组成
Znode的数据组成主要包含4部分:
(1)data:保存数据
(2)stat:元数据信息,用于描述该节点的相关信息
(3)acl:权限,用于定义什么用户对该节点有怎样的权力
//注册当前会话的账号密码
addauth digest xiaowang:123456
//创建节点并设置权限
create /test-node abcd auth:xiaowang:123456:cdwra
//在另⼀个会话中必须先使⽤账号密码,才能拥有操作该节点的权限
(4)child:当前节点的子节点
4、Znode的分类
创建节点指令 [-s]表示节点是序号节点
[-e]表示节点是临时节点
[-c]表示节点是Container节点
(1)持久节点:创建的节点在会话结束后不会被删除
(2)持久序号节点:
对于普通的持久节点,两次创建相同节点会报错
对于持久序号节点,会在节点名之后自动加入序号,且按照创建的顺序序号是单调递增的
(3)临时节点:创建的节点在会话结束后(即断开连接后)会被删除
(4)临时序号节点:用于实现分布式锁及Leader选举
(5)Container节点:会被定时检测,当节点不存在子节点时会被删除
5、分布式锁的实现原理
(1)curator实现的分布式锁种类如下:
InterProcessMutex:分布式可重入排它锁 ;- 可重入排它锁比较常用,也叫公平锁(类似链表结构按照线程请求时间顺序依次获取锁)
InterProcessSemaphoreMutex:分布式排它锁;
InterProcessReadWriteLock:分布式读写锁;
InterProcessMultiLock:将多个锁作为单个实体管理的容器;
package cn.com.demo.zookeeper.test.testselection;
import cn.com.demo.zookeeper.constant.ZKParamConstant;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.framework.recipes.locks.InterProcessSemaphoreMutex;
import org.apache.curator.retry.RetryUntilElapsed;
public class InterProcessSemaphoreMutexTest {
public static void main(String[] args) throws Exception {
RetryUntilElapsed retryPolicy = new RetryUntilElapsed(10 * 1000, 2 * 1000);
CuratorFramework client = CuratorFrameworkFactory.builder()
.connectString("127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183")
.retryPolicy(retryPolicy)
// 会话超时
.sessionTimeoutMs(ZKParamConstant.SESSION_TIMEOUTMS * 1000)
// 连接超时
.connectionTimeoutMs(ZKParamConstant.CONNECTION_TIMEOUTMS * 1000)
.namespace("processor")
.build();
client.start();
//(1)可重入,第二次获取锁时不阻塞,即两次调用lock.acquire()只会创建一个临时节点
InterProcessMutex lock=new InterProcessMutex(client,"/myLockTest");
// //(2)不可重入,第二次获取锁时会阻塞,即两次调用lock.acquire()会创建两个临时节点
// InterProcessSemaphoreMutex lock=new InterProcessSemaphoreMutex(client,"/myLockTest");
lock.acquire();
lock.acquire();
System.out.println("lock acquire");
lock.release();
lock.release();
}
}
InterProcessMutex(互斥可重入锁运行结果),只生成一个临时节点,第二次获取锁不会阻塞
InterProcessMutex(互斥不可重入锁运行结果),生成两个临时节点,第二次获取锁阻塞
(2)zookeeper实现分布式锁的原理
以InterProcessMutex为例:
- 以"/processor/myLockTest" 为锁节点做抢锁,4个客户端按顺序调用acquire()方法获取锁,会在"/processor/myLockTest" 下创建4个临时序号节点。
- "/processor/myLockTest" 下最小临时序号节点的创建客户端持有锁
- 非最小临时序号节点的创建客户端会监听其前一个节点
- 为什么不是所有的客户端(除锁的持有者)监听最小的节点?惊群效应:当都监听最小节点时,如果最小节点被删除,那么大部分客户端都要将监听的节点改为此时最小的节点,效率低
- client0获取到锁,当client0调用release()方法或客户端断开连接后,临时序号节点0会被删除;临时序号节点1变为最小节点,此时client1接收到Server发送的节点变更通知,获取到锁继续运行后续代码
6、Leader选举
(1)curator中实现选举:
1、LeaderLatch(偏手动,latch单次使用)
(1)释放Leader权限需要手动调用LeaderLatch.close();
(2)如果客户端想要重新抢权限,需要重新创建LeaderLatch抢权限
2、LeaderSelector(偏自动自动,可以循环使用)
(1)LeaderSelector在运行完takeLeadership后会自动释放权限
(2)通过调用LeaderSelector.autoRequeue()可以重新开始抢夺权限
//LeaderSelector构造方法
public LeaderSelector(CuratorFramework client, String leaderPath, LeaderSelectorListener listener) {
this(client, leaderPath, new CloseableExecutorService(Executors.newSingleThreadExecutor(defaultThreadFactory), true), listener);
}
//LeaderSelectorListener
public interface LeaderSelectorListener extends ConnectionStateListener {
void takeLeadership(CuratorFramework var1) throws Exception;
}
(2)实例参考:
Curator应用场景(三)-Master选举LeaderLatch,LeaderSelector使用及原理分析_hosaos的博客-CSDN博客_leaderlatch
(3)原理:LeaderSelector基于InterProcessMutex实现,本质上与LeaderLatch及分布式锁一样都是基于watch机制和临时序号节点实现的。
7、Zookeeper数据持久化
(1)事务日志:将执行的命令以日志的形式保存
(2)数据快照:每过一定的时间将内存中的数据以快照的形式保存
数据的恢复:先读取快照到内存中,然后读取日志做数据的恢复。提高效率的同时减小日志文件的大小