Zookeeper是一个开源的分布式(多台服务器干一件事)的,为分布式应用提供协调服务的Apache项目。
Zookeeper从设计模式角度来理解:是一个基于观察者模式(一个人干活,有人盯着他)设计的分布式服务管理框架。
-
它负责 存储 和 管理 大家都关心的数据
- 然后接受观察者的注册,一旦这些数据的发生变化
- Zookeeper就将负责通知已经注册的那些观察者做出相应的反应
- 从而实现集群中类似Master/Slave管理模式
Zookeeper = 文件系统 + 通知机制
分布式和集群的区别?
无论分布式和集群,都是很多人在做事情。
具体区别如下:
- 例如:我有一个饭店,越来越火爆,我得多招聘一些工作人员
- 分布式:招聘1个厨师,1个服务员,1个前台,三个人负责的工作不一样,但是最终目的都是为饭店工作
- 集群:招聘3个服务员,3个人的工作一样
集群概念
- 是一个leader和多个follower来组成的集群(狮群中,一头雄狮,N头母狮)
- 集群中只要有半数以上的节点存活,Zookeeper就能正常工作(5台服务器挂2台,没问题;4台服
务器挂2台,就停止) - 全局数据一致性,每台服务器都保存一份相同的数据副本,无论client连接哪台server,数据都是
一致的 - 数据更新原子性,一次数据要么成功,要么失败
- 实时性,在一定时间范围内,client能读取到最新数据
- 更新的请求按照顺序执行,会按照发送过来的顺序,逐一执行(发来123,执行123,而不是321
或者别的)
存储结构

- 每个节点默认可以存储1MB的数据,只能存储string类型数据
-
节点类型
- 持久型
- 持久化目录节点
- 持久化顺序编号目录节点:zk自动编号
- 临时型(连接断开后会消失)
- 临时目录节点
- 临时顺序目录节点
- 持久型
zookeeper应用场景
- 统一命名服务
- 统一配置管理
- 服务器节点上下线通知
- 软负载均衡
zookeeper内部原理
- 选举机制
- 集群中半数以上机器存活,集群可用。
- zk内部会自动产生一个leader,其余都是slaver
- 节点类型
- 监听器原理
- 在main方法中创建Zookeeper客户端的同时就会创建两个线程,一个负责网络连接通信,一个负责监听
- 监听事件就会通过网络通信发送给zookeeper
- zookeeper获得注册的监听事件后,立刻将监听事件添加到监听列表里
- zookeeper监听到 数据变化 或 路径变化,就会将这个消息发送给监听线程
- 监听线程就会在内部调用process方法(需要我们实现process方法内容)
-
写数据的过程
- Client 想向 ZooKeeper 的 Server1上写数据,必须的先发送一个写的请求
- 如果Server1不是Leader,那么Server1会把接收到的请求进一步转发给Leader
- 这个Leader会将写请求广播给各个Server,各个Server写成功后就会通知Leader
- 当Leader收到半数以上的 Server数据写成功了,那么就说明数据写成功
- 随后,Leader会告诉Server1数据写成功
- Server1会反馈通知 Client 数据写成功了,整个流程结束
分布式锁
zookeeper内部提供了一个分布式锁,但是调用很麻烦,我们通过Apache提供的封装方法来实现zk分布式锁。
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>
// 重试策略 (1000毫秒试1次,最多试3次)
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
//1.创建curator工具对象
CuratorFramework client = CuratorFrameworkFactory.newClient(zookeeperConnectionString, retryPolicy);
client.start();
//2.根据工具对象创建“内部互斥锁”
InterProcessMutex lock = new InterProcessMutex(client, lockPath);
try {
//3.加锁
lock.acquire();
productService.reduceStock(id);
}catch(Exception e){
if(e instanceof RuntimeException){
throw e;
}
}finally{
//4.释放锁
lock.release();
}
疑问
在CuratorFrameworkFactory.newClient()提供zookeeper的地址的时候如果是采用集群来搭建的ZK是需要提供多个ZK地址吗
