Zookeeper
文章目录
引言(重点必看):本篇简介进行Zookeeper的介绍,以帮助各位更快的入手Zookeeper
- 一、Zookeeper理解 可以放到后面来看
- 二、Zookeeper功能 这个先看,想学一门技术,最起码要知道人家是干什么的。在没有学习Zookeeper之前我也是很懵的,因为网上对zookeeper的功能介绍很多都过与笼统,这一块比较细致的介绍
- 三、搭建Zookeeper服务器 开始动手进行服务器搭建
- 四、Zookeeper内部的数据模型
- 五、 Zookeeper 客户端( zkCli )的使用 zk常见命令
1、什么是Zookeeper
- 他是一个分布式服务框架,是Appache Hadoop的一个子项目
- Zookeeper是一种分布式协调服务,用于管理大型主机。在分布式环境中协调和管理服务是一个复杂的过程。Zookeeper通过其简单的架构和API解决了这个问题,Zookeeper允许开发人员专注于核心应用程序逻辑,而不必担心应用程序的分布式特性。
2、Zookeeper干嘛的?
- 主要用来解决分布式应用中经常遇到的一些数据管理问题
- ZooKeeper主要服务于分布式系统,可以用ZooKeeper来做:统一配置管理、统一命名服务、分布式锁、集群管理。 也可以作为注册中心
- 简单来说 Zookeeper = 文件系统 + 监听通知机制。
3、怎么学习Zookeeper?
- ZooKeeper的数据结构,跟Unix文件系统非常类似,可以看做是一颗树,每个节点叫做ZNode。每一个节点可以通过路径来标识,结构图如下:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
一、Zookeeper理解
1.1 Znode数
那ZooKeeper这颗"树"有什么特点呢?ZooKeeper的节点我们称之为Znode,Znode分为两种类型
- 短暂/临时(Ephemeral):当客户端和服务端断开连接后,所创建的Znode(节点)会自动删除
- 持久(Persistent):当客户端和服务端断开连接后,所创建的Znode(节点)不会删除
- 顺序节点 :顺序节点可以是持久的或临时的。如果将具有路径 /myapp 的znode创建为顺序节点,则ZooKeeper会将路径更改为 /myapp0000000001 ,并将下一个序列号设置为0000000002。如果两个顺序节点是同时创建的,那么ZooKeeper不会对每个znode使用相同的数字。顺序节点在锁定和同步中起重要作用。
ZooKeeper和eureka、Redis一样,也是C/S结构(分成客户端和服务端)
1.2 Sessions(会话)
会话对于ZooKeeper的操作非常重要。会话中的请求按FIFO顺序执行。一旦客户端连接到服务器,将建立会话并向客户端分配会话ID 。
客户端以特定的时间间隔发送心跳以保持会话有效。如果ZooKeeper集合在超过服务器开启时指定的期间(会话超时)都没有从客户端接收到心跳,则它会判定客户端死机。
会话超时通常以毫秒为单位。当会话由于任何原因结束时,在该会话期间创建的临时节点也会被删除。
二、Zookeeper功能
2.1 监听器
在上面我们已经简单知道了ZooKeeper的数据结构了,ZooKeeper还配合了监听器才能够做那么多事的。常见的监听场景有以下两项:
- 监听Znode节点的数据变化
- 监听子节点的增减变化
没错,通过监听+Znode节点(持久/短暂[临时]),ZooKeeper就可以玩出这么多花样了。
2.2 统一配置管理
比如我们现在有三个系统A、B、C,他们有三份配置,分别是ASystem.yml、BSystem.yml、CSystem.yml
,然后,这三份配置又非常类似,很多的配置项几乎都一样。
- 此时,如果我们要改变其中一份配置项的信息,很可能其他两份都要改。并且,改变了配置项的信息很可能就要重启系统
于是,我们希望把ASystem.yml、BSystem.yml、CSystem.yml
相同的配置项抽取出来成一份公用的配置common.yml
,并且即便common.yml
改了,也不需要系统A、B、C重启。
做法:我们可以将common.yml
这份配置放在ZooKeeper的Znode节点中,系统A、B、C监听着这个Znode节点有无变更,如果变更了,及时响应。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
2.3 统一命名
统一命名服务的理解其实跟域名一样,是我们为这某一部分的资源给它取一个名字,别人通过这个名字就可以拿到对应的资源。
比如说,现在我有一个域名www.java3y.com
,但我这个域名下有多台机器:
- 192.168.1.1
- 192.168.1.2
- 192.168.1.3
- 192.168.1.4
别人访问www.java3y.com
即可访问到我的机器,而不是通过IP去访问。
2.4 分布式协调组件
就是在znode节点进行数据存储,其他几台需要协调的服务进行监听这个节点,一但节点发生改变,就会进行通知所有监听方改变自己的数据
在分布式系统中,需要有zookeeper作为分布式协调组件,协调分布式系统中的状态
2.5 分布式锁
点击了解 分布式锁 (非本人编写)
我们可以使用ZooKeeper来实现分布式锁,那是怎么做的呢??下面来看看:
系统A、B、C都去访问/locks
节点[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
访问的时候会创建带顺序号的临时/短暂(EPHEMERAL_SEQUENTIAL
)节点,比如,系统A创建了id_000000
节点,系统B创建了id_000002
节点,系统C创建了id_000001
节点。
接着,拿到/locks
节点下的所有子节点(id_000000,id_000001,id_000002),判断自己创建的是不是最小的那个节点
- 如果是,则拿到锁。
释放锁:执行完操作后,把创建的节点给删掉 - 如果不是,则监听比自己要小1的节点变化
举个例子:
- 系统A拿到
/locks
节点下的所有子节点,经过比较,发现自己(id_000000
),是所有子节点最小的。所以得到锁 - 系统B拿到
/locks
节点下的所有子节点,经过比较,发现自己(id_000002
),不是所有子节点最小的。所以监听比自己小1的节点id_000001
的状态 - 系统C拿到
/locks
节点下的所有子节点,经过比较,发现自己(id_000001
),不是所有子节点最小的。所以监听比自己小1的节点id_000000
的状态 - ……
- 等到系统A执行完操作以后,将自己创建的节点删除(
id_000000
)。通过监听,系统C发现id_000000
节点已经删除了,发现自己已经是最小的节点了,于是顺利拿到锁 - ….系统B如上
2.6 无状态化的实现
进行几个服务公共部分的数据信息进行存储到zookeeper上面,那几个服务需要数据的时候到zookeeper里面获取
如:用户进行登录后,登录(token)就可以直接放在zookeeper上面,这样就不需要分别在几个负载均衡的设备上面进行这个登录信息的存储,需要的时候直接去zookeeper上面进行获取。
2.7 服务注册中心
内部有临时文件,注册的服务进行定时向zookeeper发送心跳进行续约实现
类似与eureka
2.8 集群状态
经过上面几个例子,我相信大家也很容易想到ZooKeeper是怎么"感知"节点的动态新增或者删除的了。还是以我们三个系统A、B、C为例,在ZooKeeper中创建临时节点即可:
三、搭建Zookeeper服务器
http://zookeeper.apache.org/ zk官网进行Zookeeper下载
进行之后下载最新版本,windows和linux是同一个包。解压即可使用(需要有jdk环境 就是电脑装过jdk)
3.1 zoo.cfg 配置文件说明
#zookeeper 时间配置中的基本单位(毫秒)
tiekTime=2000
#允许 follower 初始化连接到1eader最大时长,它表示 tickTime 时间倍数即: initLimit*tickrime
initEimito=10
#允许 follower 与1eader数据同步最大时长,它表示 tickTime 时间信数
yncLimi =5
# zookeper 数据存储目录及日志保存目录(如果没有指明 dataLogDir ,则日志也保存在这个文件中)
dataDir=/tmp/zookeeper
#对客户端提供的端ロ号
clientPort=2181
#单个客户端与 zonkemper 量大并发连接数
maxC1ientCnxns=60
#保存的致据决照数量,之外的将会被清除
autopurge.snapRetainCount=3
#自动触发清除任务时间间隔,小时为单位。默认为 0,表示不自动清除。
autopurge.purgeInterval=1
3.2 Zookeeper服务器的操作命令
- 重命名 conf中的文件zoo_sample.cfg ->zoo.cfg
- 启动zk服务器
./bin/zkServer.sh start ./conf/zoo.cfg
- 查看zk服务器状态
./bin/zkServer.sh status ./conf/zoo.cfg
- 停止zk服务器
./bin/zkServer.sh stop ./conf/zoo.cfg
四、Zookeeper内部的数据模型
4.1 zk是如何保存数据的
zk中的数据是保存在节点上的,节点就是 znode ,多个 znode 之间构成一颗树的目录结构。 Zookeeper 的数据模型是什么样子呢?它很像数据结构当中的树,也很像文件系统的目录
树是由节点所组成, Zookeeper 的数据存储也同样是基于节点,这种节点叫做 Znode 但是,不同于树的节点, Znode 的引用方式是路径引用,类似于文件路径:
/动动/猫
/汽车/宝马
这样的层级结构,让毎一个 Znode 节点拥有唯一的路径,就像命名空间一样对不同信息作出清晰的隔离。
4.2 zk中的 znode 是什么样的结构
zk中的 znode ,包含了四个分:
-
data:保存数据
-
acl:权限,定义了什么样的用户能够操作这个节点,且能够进行怎样的操作
- c:create 创建权限。允许在该节点下创建子节点
- w:write 更新权限。允许更新该节点的数据
- r:read 读取权限。允许读取该节点的内容以及子节点的列表信息
- d : delete 删除权限。允许删除该节点的子节点
- admin 管理者权限,运行对该节点进行 acl 权限设置
-
stat:描述当前 znode 的元数据
-
child:当前节点的子节点
4.3 zk中节点 znode 的类型
-
特久节点:创建出的节点,在会话结束后依然存在。保存数据
-
持久序号节点:创建出的节点,根据先后顺序,会在节点之后带上一个数值,越后执行数值越大,适用于分布式锁的应用场景 - 单调递增
-
临时节点:临时节点在会话结束后,自动被删除,通过这个特性,zk可以实观服务注册与发现的效果。那么临时节点如何维持心跳的呢?
-
临时序号节点:跟持久序号节点相同,适用于临时的分布式锁。
-
Container 节点(3.5,3版本新增): Container 容器节点,当容器中没有子节点,该容器节点会被 zk 定期删(60s)
-
TTL 节点:可以指定节点的到期时间,到期后被 zk 定时删除。只能通过系统配置 zookeeper.extendedTypesEnabled = true 开启
4.4 zk的数据持久化
zk 的数据是运行在内存中, zk 提供了两种持久化机制
-
事务日志
zk把执行的命令以日志形式保存在 dataLogDir 指定的路径中的文件中(如果没有指定 dataLogDir,则按dataDir 指定的路径)。
-
数据快照
zk会在一定的时间间隔内做一次内存数据的快照。把该时刻的内存数据保存在快照文件中。
zk通过两种形式的持久化,在恢复时先恢复快照文件中的数据到到内存中,再用日志文件中的数据做增量恢复,这样的恢复速度更快。
五、 Zookeeper 客户端( zkCli )的使用
5.1 多节点类型创建
- 创建持久节点 create path data
- 创建持久序号节点 create -s path data
- 创建临时节点 create -e path data
- 创建临时序号节点 create -s -e path data
- 创建容器节点 create -c path data
5.2 查询节点
- 普通查询 get [-s] [-w] path [-s] :查看节点数据加元信息 [-w] : 查看节点并为节点添加一个监听
- 查询节点相关信息 stat [-w] path //查看节点元信息 [-w] :查看节点并为节点添加一个监听
- cZxid:创建节点的事务id
- mZxid:修改节点的事务id
- pZxid:添加和删除节点的事务id
- ctime:节点创建时间
- mtime:节点最近修改时间
- dataVersion:节点内数据的版本,每更新一次,版本会+1
- aciVersion:此节点的权限版本
- ephemeralOwner:如果当前节点是临时节点,该值是当前节点所有者的session id。如果节点不是临时节点,该值为零
- dataLength:节点内数据的长度
- numChildren:该节点的子节点个数
5.3 删除节点
- 普通删除 delete [-v] path [-v]:指定版本
- 乐观锁删除
5.4 权限设置
- 注册当前会话的账号和密码;
addauth digest lm:123456
- 创建节点并设置权限
#创建目录test-node 给账号lm密码123456的用户 c创建、d删除、w写入、r读取、a管理员 的权限
create /test-node abcd auth:lm:123456:cdwra
- 在另一个会话中必须使用账号密码,才能拥有操作该节点的权限
六、Curator客户端的使用
Curator介绍
Curator是Netflix公司开源的一套zookeeper客户端框架,Curator是对zookeeper支持最好的客户端框架。Curator封装了大部分Zookeeper的功能,比如Leader选举,分布式锁等,减少了技术人员在使用Zookeeper时的底层细节开发工作。
6.1 引入Curator
- 引入依赖 由于我整合了SpringCloud 以及SpringBoot 所有不需要写版本号了,没整合的话用最新的就好了(注意依赖冲突)
<!-- Curator -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>
<!--zookeeper-->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.3-beta</version>
<scope>test</scope>
</dependency>
6.2 写yml文件
server:
port: 2001
spring:
application:
name: curatorTest
#这个后来要注入到类里面去的
curator:
retryCount: 5
elapsedTimeMs: 5000
#由于我的服务直接是在本地,所以用localhost 这个本应该写zookeeper服务的机器ip
connectString: localhost:2181,localhost:2182,localhost:2183
sessionTimeoutMs: 6000
connectionTimeoutMs: 5000
6.3 配置类构建
@Data
@Component
//这个直接从上面的yml文件进行获取数据 随便放到一个包下就可以了
@ConfigurationProperties(prefix = "curator")
public class WrapperZK {
private int retryCount;
private int elapsedTimeMs;
private String connectString;
private int sessionTimeoutMs;
private int connectionTimeoutMs;
}
6.4 进Curator配置类构建
@Configuration
public class CuratorConfig {
@Autowired
WrapperZK wrapperZK;
@Bean(initMethod = "start")
public CuratorFramework curatorFramework() {
return CuratorFrameworkFactory.newClient(
wrapperZK.getConnectString(),
wrapperZK.getSessionTimeoutMs(),
wrapperZK.getConnectionTimeoutMs(),
new RetryNTimes(wrapperZK.getRetryCount(), wrapperZK.getElapsedTimeMs()));
}
}
6.5 就可以直接用测试单元测试了。
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest()
public class ColTest {
@Autowired
CuratorFramework curatorFramework;
@Test
public void createNode() throws Exception {
//添加持久节点
String path = curatorFramework.create().forPath("/curator-node");
// //添加临时序号节点
// String path = curatorFramework.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath("/curator-node","some-data".getBytes());
System.out.println(String.format("curator create node :%s successfully.",path));
//阻塞线程等待读取zookeeper方法 保持连接
// System.in.read();
}
@Test
public void testGetData() throws Exception {
//查询节点数据
byte[] bytes = curatorFramework.getData().forPath("/curator-node");
System.out.println(new String(bytes));
}
@Test
public void testSetData() throws Exception {
//设置zNode节点的数据
curatorFramework.setData().forPath("/curator-node","changed".getBytes());
byte[] bytes = curatorFramework.getData().forPath("/curator-node");
System.out.println(new String(bytes));
}
@Test
public void testCreateWithParent() throws Exception {
//建立节点 直到指定路径节点全部建完
String pathWithParent= "/node-parent/sub-node-1";
String path = curatorFramework.create().creatingParentsIfNeeded().forPath(pathWithParent);
System.out.println(String.format("curator create node :%s successfullyy",path));
}
@Test
public void testDelete() throws Exception {
//进行删除节点(包括子节点)
String pathWithParent = "/node-parent";
curatorFramework.delete().guaranteed().deletingChildrenIfNeeded().forPath(pathWithParent);
}
}
七、 zk 实现分布式锁
7.1 zk中锁的种类
- 读锁:大家都可以读,要想上读锁的前提:之前的锁没有写锁
- 写锁:只有得到写锁的才能写,要想上写锁的前提是,之前没有任何锁。
7.2 zk如何上读锁
- 创建一个临封序号节点,节点的数据是 read表示是读锁。
- 获取当前zk中序号比自己小的所有节点
- 判断最小节点是否是读锁
- 如果不是读的话,则上锁失败,为最小节点设置监听。阻塞等待,zk的 watch 机制会当最小节点发生变化时通知当前节点,于是再执行第二步的流程
- 如果是读锁的话,则上锁成功
7.3 zk如何上写锁
- 创建一个临时序号节点,节点的数据是 write ,表示是写锁
- 获取 zk 中所有的子节点
- 判新自己是否是最小的节点:
- 如果是,则上写锁成功
- 如果不是,说明前面还有锁,则上锁失败,监听最小的节点,如果最小节点有变化,则回到第二步。
7.4 羊群效应
如果用上述方法进行上锁,只要有节点发生变化,就会触发其他节点的监听事件,这样的话对zk的压力非常大,——羊群效应。可以调整成链式监听,解决这个问题。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t2tXVihC-1638500275475)(F:\真的文件夹\A_知识集\必须掌握图片\Zookeeper8.jpg)]
7.5 curator实现读写锁
1)获取读锁
@Test
public void testGetReadLock() throws Exception {
//读写锁 初始化参数 连接对象,需要加锁的路径
InterProcessReadWriteLock readWriteLock =
new InterProcessReadWriteLock(curatorFramework,"/curator-node");
//获取读锁对象
InterProcessLock interProcessLock = readWriteLock.readLock();
log.info("等待获取读锁对象!");
//获取锁 //没获取到锁之前会进入阻塞
interProcessLock.acquire();
//已经获取到读锁了,这下面制造堵塞(不释放锁 测试用)
for (int i = 0; i < 100; i++) {
Thread.sleep(3000);
log.info("{}",i);
}
//释放锁
interProcessLock.release();
log.info("============锁已经释放了");
}
2)获取写锁
@Test
public void testGetWriteLock() throws Exception {
//读写锁
InterProcessReadWriteLock readWriteLock =
new InterProcessReadWriteLock(curatorFramework,"/curator-node");
//获取写锁对象
InterProcessLock interProcessLock = readWriteLock.writeLock();
log.info("等待获取写锁中");
//获取锁
interProcessLock.acquire();
for (int i = 0; i < 100; i++) {
log.info("{}",i);
Thread.sleep(3000);
}
//释放锁
interProcessLock.release();
log.info("锁已经释放成功");
}
八、zk 的 watch 机制
8.1 Watch机制介绍
我们可以把 Watch 理解成是注册在特定 Znode 上的出发前。当这个 Znode 发生改变,也就是调用了 create,delete,setData, 方法的时候将会触发 Znode 上注册的对应事件。请求 Watch 的客户端会接收到异步通知。
具体交互过程知下
-
客户端调用 getData 方法, watah 参数是 true。服务端接收到请求,返回节点数据,并且在对应的哈希表里插入被 Watch 的 Znode 路径,以及 Watcher 列表。
-
当被 Watch 的 Znode 已删除。服务端会查找哈希表。找到该 Znode 对应的所有 Watcher,异步通知客户端。并且删除哈希表中对应的 Key - Value .
客户端使用NIO通信模式监听服务端的调用
8.2 zkCli客户端使用watch
create /test xxx
get -w /test #-次监听节点
ls -w /test #监听目录,创建和删除子目录会收到通知。子节点中新增节点不会收到通知
ls -R -w /test #对整个test目录监听。但内容变化不会收到通知
8.3 curator客户端使用watch
@Test
public void addNodeListener() throws Exception {
NodeCache nodeCache = new NodeCache(curatorFramework,"/curator-node");
nodeCache.getListenable().addListener(new NodeCacheListener() {
@Override
public void nodeChanged() throws Exception {
log.info("{} path nodeChanged:","/curator-node");
printNodeData();
}
});
nodeCache.start();
System.in.read();
}
public void printNodeData() throws Exception {
byte[] bytes = curatorFramework.getData().forPath("/curator-node");
log.info("data: {}",new String(bytes));
}
九、Zookeeper集群实战
9.1 Zookeeper集群角色
zookeeper集群有三种角色
- Leader:处理集群所有的事务请求,集群中只有一个Leader。
- Follower:只能处理读请求,参与Leader选举。
- Observer:只能处理读请求,提升集群的性能,但不能参与选举
9.2 集群搭建
搭建4个节点,其中一个节点为Observer
1)创建5个节点的myid,并设值
在/usr/local/zookeeper中创建一下四个文件
#zk1、zk2、zk3、zk4 这四个是目录 然后分别在它们里面建一个myid文件写入数据1、2、3、4
#目录不是固定的,我就建在 /lm/springcloud/Zookeeper/这个目录下
/user/local/zookeeper/zkdata/zk1]# echo 1 > myid
/user/local/zookeeper/zkdata/zk2]# echo 2 > myid
/user/local/zookeeper/zkdata/zk3]# echo 3 > myid
/user/local/zookeeper/zkdata/zk4]# echo 4 > myid
2)编写4个zoo.cfg
#zookeeper 时间配置中的基本单位(毫秒)
tiekTime=2000
#允许 follower 初始化连接到1eader最大时长,它表示 tickTime 时间倍数即: initLimit*tickrime
initEimito=10
#允许 follower 与1eader数据同步最大时长,它表示 tickTime 时间信数
yncLimi =5
#zookeper 数据存储目录及日志保存目录(如果没有指明 dataLogDir ,则日志也保存在这个文件中)
#修改为对应的zk1、zk2、zk3、zk4 这四个目录
dataDir=/uer/local/zookeeper/zkdata/zk1
#对客户端提供的端ロ号
#修改为对应的端口 2181、2182、2183、2184 如果是部署在不同的机器上就全部2181就行了
clientPort=2181
#2001为集群通信端口,3001位集群选举端口,observer表示不参与集群选举
#192.168.132.3是我机器的端口,部署在不同的机器的话 通信端口和选举端口可以写一致的
server.1=192.168.132.3:2001:3001
server.2=192.168.132.3:2002:3002
server.3=192.168.132.3:2003:3003
server.4=192.168.132.3:2004:3004:observer
3)启动4台Zookeeper
./bin/zkServer.sh start ./conf/zoo1.cfg
./bin/zkServer.sh start ./conf/zoo2.cfg
./bin/zkServer.sh start ./conf/zoo3.cfg
./bin/zkServer.sh start ./conf/zoo4.cfg
9.3 连接Zookeeper集群
./bin/zkCli.sh -server 192.168.132.3:2181,
192.168.132.3:2182,192.168.132.3:2183,192.168.132.3:2184
十、ZAB协议
10.1 什么是zab协议
zookeeper作为非常重要的分布式协调组件,需要进行集群部署,集群中会以一主多从的形式进行部署。zk为了保证数据的一致性,使用了ZAB(Zookeeper Atomlc Broadcast)协议,这个协议解决了Zookeeper的崩溃恢复和主从同步的问题。
10.2 ZAB协议定义的四种节点状态
- Looking:选举状态
- Following:Follower节点(从节点)所处的状态
- Leading:Leader节点(主节点)所处状态
- Observing:观察者节点所处的状态
10.3 集群上线时的Leader选举过程
假设有三台机器进行选举,实际只要有台机器获得了两票就会结束
优先根据zid(版本id)投票,其次myid(机器id)。
id大的获得选票,选票超过半数就会确定谁是Leader,后面没参与选票的进行顺从。
10.4 崩溃恢复时的Leader选举
Leader建立完后,Leader周期性低不断向Follower发送心跳(ping命令,没有内容的socket)。但Leader崩溃后,Follower发现socket通道已关闭,于是开始进入到Looking状态,重新回到上一节的Leader选举状态,此时集群不能对外提供服务。
10.5 主从服务器之间的数据同步
10.6 Zookeeper中的NIO与BIO的应用
- NIO
- 用于被客户连接2181端口,使用的是NIO模式与客户建立连接
- 客户端开启Watch时,也是使用NIO,等待Zookeeper的回调
- BIO
- 集群在选举时,多个节点之间的投票通信端口,使用BIO进行通信。
10.7 Zookeepper追求的一致性
Zookeeper在数据同步时,追求的并不是强一致性,而是顺序一致性(事务id和单调递增)
总结
- 学会搭建ZK服务器,熟练掌握zkCli命令
- 掌握Curator第三方工具的使用
- 搭建Zk集群,掌握集群的节点状态,客户端连接的操作
- 掌握zk选举流程和数据同步流程
本文参考:
【千锋最新Zookeeper集群教程-全网最全Zookeeper应用及原理分析课程-
哔哩哔哩】https://b23.tv/brRBIT
建议最近需要进行Zookeeper学习的小伙伴可以,去B站搜索学习