Unit4:大数据技术进阶(Zookeeper)
本章节学习目标:
1. 了解zookeeper的概述和架构
2. 掌握集群中各个角色的作用
3. 熟悉zookeeper集群的搭建
4. 掌握内部原理
5. 企业面试真题
一、大数据概念
1 概论:
zookeeper是什么?
1, Zookeeper是一个分布式协调服务的开源概架,主要用来解决分布式集群中应用系统的一致性问题。
2 ,ZooKeeper本质上是一个分布式的小文件存储系统,提供基于类似于文件系统的目录树方式的数据存储,并且可以对树中的节点进行有效管理,从而用来维护和监控你存储的数据的状态变化,通过监控这些数据状态的变化,从而可以达到基于数据的集群管理,诸如:统一命名服务、分布式配置管理、负载均衡、分布式锁、分布式协调等功能。
( 详见官网:https://zookeeper.apache.org/)
2 特点 :
zookeeper的几大特性分别是什么?
-
Zookeeper:是由一个领导者(Leader),多个跟随者(Follower)组成的集群。
-
集群中只要有半数以上的节点存活下来,Zookeeper集群就能正常服务。
-
全局数据一致:每个Server保存一份相同的数据副本,Client无论连接那个Server,数据都是一致的。
-
可靠性:如果消息被其中的一台服务器接收,那么就被所有的服务器接收。
-
顺序性:更新请求顺序进行,来自同一个Client的更新请求按照发送顺序依次执行。
-
数据更新原子性:一次数据更新要么成功,要么失败,不存在其他状态。
-
实时性:Zookeeper保证客户端在一定事件间隔范围内获取服务器的更新(或失效)的信息。
-
集群中半数以上机器存活,集群可用。所以Zookeeper适合安装奇数台服务器。
3 集群中角色的作用
各个角色代表着什么?
1. Leader:
Zookeeper 集群工作的核心
事务请求 (写操作) 的唯一调度和处理者,保证集群事务处理的顺序性
集群内部各个服务器的调度者。
对于 create, setData, delete 等有写操作的请求,则需要统一转发给leader 处理.leader 需要决定编号、执行操作,这个过程称为一个事务。
1. Follower:
处理客户端非事务(读操作)请求,转发事务请求给 Leader
参与集群Leader 选举投票。
3. Observer:(对于访问量比较大的集群,可以新增观察者角色)
观察者角色,观察Zookeeper集群的最新状态变化并将这些状态同步过来,对于非事务请求可以进行独立处理,对于事务请求,则会转发给 Leader服务器进行处理。
不会参与任何形式的投票只提供非事务服务,通常用于在不影响集群事务处理能力的前提下提升集群的非事务处理能力。
4 数据结构
Zookeeper数据模型的结构与Unix文件系统相似,呈树状图分布,每个节点称为一个ZNode,每个与ZNode默认只能存储1M的数据,每个ZNode都可以通过路径使标识唯一。
- 每个ZNode有三部分组成:
- stat:状态信息,显示ZNode版本,权限等信息。
- data:与ZNode关联的数据。
- children:本ZNode下的子节点。
二、API应用
Eclipse
- 创建maven工程
- 添加pom文件
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.10</version>
</dependency>
</dependencies>
- 创建log4j.properties文件并添加如下内容
log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
- 创建客户端
private static String connectString =
"hadoop102:2181,hadoop103:2181,hadoop104:2181";
private static int sessionTimeout = 2000;
private ZooKeeper zkClient = null;
@Before
public void init() throws Exception {
zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent event) {
// 收到事件通知后的回调函数(用户的业务逻辑)
System.out.println(event.getType() + "--" + event.getPath());
// 再次启动监听
try {
zkClient.getChildren("/", true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
- 创建子节点
// 创建子节点
@Test
public void create() throws Exception {
// 参数1:要创建的节点的路径; 参数2:节点数据 ; 参数3:节点权限 ;参数4:节点的类型
String nodeCreated = zkClient.create("/jinghang", "jinlian".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
- 获取子节点并监听节点变化
// 获取子节点
@Test
public void getChildren() throws Exception {
List<String> children = zkClient.getChildren("/", true);
for (String child : children) {
System.out.println(child);
}
// 延时阻塞
Thread.sleep(Long.MAX_VALUE);
- 判断ZNode是否存在
// 判断znode是否存在
@Test
public void exist() throws Exception {
Stat stat = zkClient.exists("/eclipse", false);
System.out.println(stat == null ? "not exist" : "exist");
}
三、内部原理(重点)
1 节点类型
- 类型分为两大类
持久节点:客户端与服务器断开连接之后,创建的节点始终存在。
临时节点:客户端与服务器断开连接之后,节点自动删除。
- 持久化目录节点:客户端与Zookeeper断连之后,创建的节点依旧存在。
- 持久化顺序编号目录节点:同持久化目录节点,只是Zookeeper给该节点名称进行顺序编号。
- 临时目录节点:客户端与Zookeeper断连之后,创建的节点被删除。
- 临时顺序编号目录节点:同临时目录节点,只是Zookeeper给该节点名称进行顺序编号。
3 stat结构体
Stat 结构体相关参数,须知:
- czxid-创建节点的事务zxid
- ctime - znode被创建的毫秒数(从1970年开始)
- mzxid - znode最后更新的事务zxid
- mtime - znode最后修改的毫秒数(从1970年开始)
- pZxid-znode最后更新的子节点zxid
- cversion - znode子节点变化号,znode子节点修改次数 (须知)
- dataversion - znode数据变化号(修改一次会加一) (须知)
- ephemeralOwner- 如果是临时节点,这个是znode拥有者的session id。如果不是临时节点则是0x0。 (须知)
- dataLength- znode的数据长度 (须知)
- numChildren - 子节点数量 (须知)
4 Leader选举机制
1) 旧集群选举:
数据ID、服务器ID和逻辑时钟含义说明:
数据ID:数据新的version就大,数据每次更新都会更新version。
服务器ID:就是我们配置的myid中的值,每个机器一个。
逻辑时钟:这个值从0开始递增,每次选举对应一个值。 如果在同一次选举中,这个值是一致的。
选举的标准为:
- 逻辑时钟小的选举结果被忽略,重新投票;
- 统一逻辑时钟后,数据id大的胜出,当选leader;
- 数据id相同的情况下,服务器id大的胜出,当选leader;
2) 全新集群选举:
- 采用投票机制,每台服务器自带一票默认投给自己,一旦遇到服务器id比自己大的就会将自身宝贵的一票贡献出来,直到有一台服务器的票数大于所有服务器总数的一半时,Leader诞生。所有Follower改变状态,不在参与选举。
5 监听器原理
- 首先要有一个main()线程
- 在main线程中创建Zookeeper客户端,这时就会创建两个线程,一个负责网络连接通信(connet),一个负责监听(listener)
- 通过connect线程将注册的监听事件发送给Zookeeper
- 在Zookeeper的注册监听器列表中将注册的监听事件添加到列表中
- Zookeeper监听到有数据或路径变化,就会将这个消息发送给listener线程
- listener线程内部调用process()方法
6 写数据流程
- Client向ZooKeeper的Server1 写数据,发送一个写请求
- 如果Server1不是Leader,那么Server1会把接受到的这个事务请求进一步转发给Leader。
Leader会将写请求广播给各个Server,各个Server写成功后,会向Leader发送成功信息 - 当Leader收到半数以上(大多数) Server数据写成功的信息,说明该数据写成功了。Leader会告诉server1数据写成功了.
- Server1会进一步通知 Client 数据写成功了,就认为整个写操作成功
7 监听服务器节点动态上下线案例(扩展)
参考:https://blog.csdn.net/m0_51113511/article/details/112412308
四、面试官拷问:
- 请简述ZooKeeper的选举机制?
- ZooKeeper的监听原理是什么?
- ZooKeeper的部署方式有哪几种?集群中的角色有哪些?集群最少需要几台机器?
- ZooKeeper的常用命令?
- Zookeeper 下 Server工作状态都有什么?
- 数据是怎样进行同步的?