Zookeeper笔记
为什么要使用Zookeeper
dubbo需要一个注册中心,而Zookeeper是我们在使用Dubbo是官方推荐的注册中心


Zookeeper介绍

Zookeeper的集群机制
Zookeeper是为了其他分布式程序提供服务的,所以不能随便就挂了。Zookeeper的集群机制采取的是半数存活机制。也就是整个集群节点中有半数以上的节点存活,那么整个集群环境可用。这也是为什么说zk的集群最好是奇数个节点。
zk的作用
| 序号 | 功能 |
|---|---|
| 1 | 为别的分布式程序服务的 |
| 2 | 本身就是一个分布式程序 |
| 3 | 主从协调 服务器节点动态上下线 统一配置管理 分布式共享锁 统一名称服务 |
| 4 | 管理(存储,读取)用户程序提交的数据 并为用户程序提供数据节点监听服务 |
Zookeeper集群节点的角色
Leader
Leader是Zookeeper集群工作的核心,其主要工作是:
- 事务请求的唯一调度和处理者,保证集群事务处理的顺序性。
- 集群内部各服务器的调度者
Follower
Follower是zookeeper集群的跟随者,主要工作是:
- 处理客户端非事务性请求(读取数据),转发事务请求给Leader服务器
- 参与事务请求Proposal的投票
- 参与Leader选举投票
Observer
Observer充当观察者的角色,观察Zookeeper集群的最小状态变化并将这些状态同步过来,其对于非事务请求可以独立处理,对于事务请求,会转给Leader节点进行处理。Observer不会参与投票,包括事务请求Proposal的投票和Leader选举投票
集群环境准备
节点的映射关系
每个节点设置相应的ip和主机名的映射关系,方便集群环境的部署
修改hosts配置文件中的信息

配置免密登录
生成公钥和私钥
ssh-keygen
输入命令后根据提示,四次回车即可

发送公钥给需要免密登录的节点
ssh-copy-id zk01
ssh-copy-id zk02
ssh-copy-id zk03

节点和节点发送文件通过scp命令实现
scp -r b.txt bobo01:/root/

关闭防火墙
查看防火墙状态
firewall-cmd --state
停止防火墙
systemctl stop firewall.service
禁止开机启动
systemctl disable firewall.service
Zookeeper的选举机制
Leader主要作用是保证分布式数据一致性,即每个节点的存储的数据同步。
服务器初始化时Leader选举
Zookeeper由于自身的性质,一般建议选取奇数个节点进行搭建分布式服务器集群。以3个节点组成的服务器集群为例,说明服务器初始化时的选举过程。启动第一台安装Zookeeper的节点时,无法单独进行选举,启动第二台时,两节点之间进行通信,开始选举Leader。
- 每个Server投出一票。第一次他们都投给自己作为Leader,投票内容未(SID,ZXID)。
SID为Server的id,即启动ZK时配置文件中的myid;
ZXID为事务id,为节点的更新程序,ZXID越大,代表Server对ZK节点的操作越新。由于服务器初始化,
每个Sever上的Znode为0,所以Server1投的票为(1,0),Server2为(2,0)。两Server将各自投票发给集群中其他机器。 - 每个Server接收来自其他Server的投票。集群中的每个Server先判断投票的有效性,如检查是不是本轮的投票,是不是来Looking状态的服务器投的票。
- 对投票结果进行处理。处理规则为:
- 首先对比ZXID。ZXID大的服务器优先作为Leader
- 若ZXID系统,如初始化时,每个Server的ZXID都是0
- 就会比较sid即myid,myid大的选出来做Leader。
首次选举对于Server而言,他接受到的投票为(2,0),因为自身的票为(1,0),所以此时它会选举Server2为Leader,
将自己的更新为(2,0)。而Server2收到的投票为Server1的(1,0)由于比他自己小,
Server2的投票不变。Server1和Server2再次将票投出,投出的票都为(2,0)
- 统计投票。每次投票后,服务器都会统计投票信息,如果判定某个Server有过半的票数,俺么该Server就是Leader。首次投票对于Server1和Server2而言,统计出已经有两台机器接收了(2,0)的投票信息,此时认为选出了Leader。
- 改变服务器的状态。当确定了Leader之后,每个Server更新自己的状态,
Leader将状态更新为Leading,Follower将状态更新为Following。

服务器运行期间的Leader选举
ZK运行期间,如果有新的Server加入,或非Leader节点挂了,那么LEader会同步数据给新的Server或寻找其他备用Server替代宕机的Server。若Leader宕机,此时集群暂停对外服务,开始在内部选举新的Leader。假设当前集群中有Server1、Server2、Server3三台服务器,Server2为当前集群的Leader,由于意外情况,Server2宕机了,便开始进入选举状态。过程如下
1 变更状态。其他非Observer服务器将自己的状态改变成Looking,开始进入Leader选举。
2. 每个Server投出1张票(myid,ZXID),由于集群运行过,所以每个Server的ZXID可能不同。
假设Server1的ZXID为145,Server3的为122,第一轮投票中,Server1和Server3都投自己,
票分别为(1,145)、(3,122),将自己的票发送给集群中所有机器。
3. 每个Server接收接收来自其他Server的投票,接下来的步骤与初始化时相同。
Zookeeper客户端使用
配置Zookeeper的环境变量
为了简化我们每次操作Zookeeper而不用进入到Zookeeper的安装目录,我们可以将Zookeeper的安装信息配置到系统的环境变量中
vim /etc/profile
添加的内容
export ZOOKEPPER_HOME=/opt/zookeeper
export PATH=$PATH:$ZOOKEEPER_HOME/bin
执行source命令
source /etc/profile
我们就可以在节点的任意位置操作Zookeeper了,通过scp命令将profile文件发送到其他几个节点上
scp /etc/profile zk02:/etc/
客户端连接
通过bin目录下的zkCli.sh 命令连接即可
zkCli.sh

zkCli.sh默认连接的是当前节点的Zookeeper节点,如果我们要连接其他节点执行如下命令即可
zkCli.sh -timeout 5000 -server zk02:2181
数据操作
Zookeeper的数据结构
- 层次化的目录结构,命名符合常规文件系统规范
- 每个节点在Zookeeper中叫做znode,并且有一个唯一的路径标识
- 节点znode可以包含数据和子节点(但是EPHEMERAL类型的节点不能有子节点)
- 客户端应用可以在节点上设置监听器

节点类型
1).znode有两种类型:
短暂性(ephemeral)(断开连接自己删除)
持久性(persistent)(断开连接不删除)
2).znode有四种形式的目录节点(默认是persistent)如下
| 序号 | 节点类型 | 描述 |
|---|---|---|
| 1 | PERSISTENT | 持久节点 |
| 2 | PERSISTENT_SEQUENTIAL | 持久有序节点(顺序节点) |
| 3 | EPHEMERAL | 短暂节点 (临时节点) |
| 4 | EPHEMERAL_SEQUENTIAL | 短暂有序节点 (临时顺序节点) |
创建znode时设置顺序标识,znode名称后会附加一个值,顺序号是一个单调递增的计数器,有父节点维护在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序
常用命令
Zookeeper作为Dubbo的注册中心用来保存我们各个服务的节点信息,显示Zookeeper是可以实现输出的存储操作的,我们来看下Zookeeper中存储操作的基本命令
ls
ls用来查看某个节点下的子节点信息

增强的命令,查看节点下的子节点及当前节点的属性信息 ls2或者 ls -s 命令

create
创建节点信息

get
get命令用来查看节点的数据

如果要查看节点的属性信息那么我们可以通过get -s 来实现
delete
delete只能删除没有子节点的节点要删除非空节点可以通过 rmr 或者 deleteall 命令实现

set
set命令可以用来修改节点的内容。

事件监听
监听某个节点的数据内容变化,通过get命令 带 -w 参数即可,在3.4版本的Zookeeper中是通过 get path watch 来说实现监控的

然后我们在其他节点上修改app1节点的数据,会触监听事件
Zookeeper Java API使用
pom
<dependencies><dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.5.9</version></dependency><dependency><groupId>com.github.sgroschupf</groupId><artifactId>zkclient</artifactId><version>0.1</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency></dependencies>
连接ZK服务
private String connectString = "192.168.100.121:2181,192.168.122:2181,192.168.100.122:2181";private int sessionTimeOut = 5000;/*** 连接Zookeeper服务端*/@Testpublic void test1() throws IOException {ZooKeeper zooKeeper = new ZooKeeper(connectString, sessionTimeOut, new Watcher() {/*** 触发监听事件的回调方法* @param watchedEvent*/@Overridepublic void process(WatchedEvent watchedEvent) {System.out.println("触发了.....");}});System.out.println("--->" + zooKeeper);}

/*** 创建节点*/@Testpublic void createNode() throws Exception{String path = zooKeeper.create("/apptest" // 节点路径,"HelloZookeeper".getBytes() // 节点的数据, ZooDefs.Ids.OPEN_ACL_UNSAFE // 权限, CreateMode.PERSISTENT // 节点类型);System.out.println(path);}/*** 判断节点是否存在*/@Testpublic void exist() throws Exception{// true表示的是使用Zookeeper中的watchStat stat = zooKeeper.exists("/apptest", true);if(stat != null){System.out.println("节点存在"+ stat.getNumChildren());}else{System.out.println("节点不存在 ....");}}/*** 获取某个节点下面的所有的子节点*/@Testpublic void getChildrens() throws Exception{List<String> childrens = zooKeeper.getChildren("/app1", true);for (String children : childrens) {// System.out.println(children);// 获取子节点中的数据byte[] data = zooKeeper.getData("/app1/" + children, false, null);System.out.println(children+":" + new String(data));}}/*** 修改节点的内容*/@Testpublic void setData() throws Exception{// -1 不指定版本 自动维护Stat stat = zooKeeper.setData("/app1/a1", "666666".getBytes(), -1);System.out.println(stat);}/*** 删除节点*/@Testpublic void deleteNode() throws Exception{zooKeeper.delete("/app1",-1);}
事件监听处理
/*** 监听Node节点下的子节点的变化*/@Testpublic void nodeChildrenChange() throws Exception{List<String> list = zooKeeper.getChildren("/app1", new Watcher() {/*** None(-1),* NodeCreated(1),* NodeDeleted(2),* NodeDataChanged(3),* NodeChildrenChanged(4),* DataWatchRemoved(5),* ChildWatchRemoved(6);* @param watchedEvent*/@Overridepublic void process(WatchedEvent watchedEvent) {System.out.println("--->"+ watchedEvent.getType());}});for (String s : list) {System.out.println(s);}Thread.sleep(Integer.MAX_VALUE);}/*** 监听节点内容变更*/@Testpublic void nodeDataChanged() throws Exception{byte[] data = zooKeeper.getData("/app1/a1", new Watcher() {@Overridepublic void process(WatchedEvent watchedEvent) {System.out.println("--->" + watchedEvent.getType());}}, null);System.out.println("--->" + new String(data));Thread.sleep(Integer.MAX_VALUE);}
相关文章:
Zookeeper笔记
为什么要使用Zookeeper dubbo需要一个注册中心,而Zookeeper是我们在使用Dubbo是官方推荐的注册中心 Zookeeper介绍 Zookeeper的集群机制 Zookeeper是为了其他分布式程序提供服务的,所以不能随便就挂了。Zookeeper的集群机制采取的是半数存活机制。也…...
【视觉SLAM入门】5.1. 特征提取和匹配--FAST,ORB(关键点描述子),2D-2D对极几何,本质矩阵,单应矩阵,三角测量,三角化矛盾
"不言而善应" 0. 基础知识1. 特征提取和匹配1.1 FAST关键点1.2 ORB的关键点--改进FAST1.3 ORB的描述子--BRIEF1.4 总结 2. 对极几何,对极约束2.1 本质矩阵(对极约束)2.1.1 求解本质矩阵2.1.2 恢复相机运动 R , t R,t R,…...
【能量管理系统( EMS )】基于粒子群算法对光伏、蓄电池等分布式能源DG进行规模优化调度研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
绘制Circos基因圈图
写在前面 昨天在绘制Circos圈图,已经隔了2年左右没有做这类的图了。这时间过得真是快,但是文章和成果依旧是没有很明显的成效。只能安慰自己,后面的时间继续加油吧!关于Cirocs图的制作,我从刚开始到现在都是是使用TBt…...
openGauss学习笔记-26 openGauss 高级数据管理-约束
文章目录 openGauss学习笔记-26 openGauss 高级数据管理-约束26.1 NOT NULL约束26.2 UNIQUE约束26.3 PRIMARY KEY26.4 FOREIGN KEY26.5 CHECK约束 openGauss学习笔记-26 openGauss 高级数据管理-约束 约束子句用于声明约束,新行或者更新的行必须满足这些约束才能成…...
学习React(四)
学习React(四) componentWillMount(被放弃使用)rendercomponentDidMountshouldComponentUpdate(nextProps,nextState)componentWillUpdate(被放弃使用)componentDidUpdatecomponentWillReceiveProps&#x…...
如何将单体项目拆分成微服务
1、如何将单体项目拆分成微服务 如何拆分微服务?其实对不同的业务项目场景,对应有不同的拆分方案。需要项目人员详细的分析项目需求、团队现状、业务边界、业务逻辑等方方面面,拆分的粒度既不能过细,也不能过粗,需要把…...
【Vue框架】Vuex状态管理
前言 在上一篇 【Vue框架】Vue路由配置 结尾时说到store.js,在代码里new Vuex.Store()传入了getters对象;本篇专门针对getters的内容进行整理。 1、getters.js 1.1 代码 // 用于存储获取状态的方法 const getters {// 这里的state参数,是…...
Linked List
文章目录 链表定义专业术语代码链表分类常见算法链表创建和常用算法 链表总结 链表 补充知识 typedef 给类型换名字,比如 typedef struct Student {int sid;char name[100];char sex; }ST;//ST就代表了struct Student //即这上方一大坨都可以用ST表示 //原先结构体…...
javascript数组基础
文章和代码已经归档至【Github仓库:https://github.com/timerring/front-end-tutorial 】或者公众号【AIShareLab】回复 javascript 也可获取。 文章目录 数组的基本使用定义数组和数组单元访问数组和数组索引数据单元值类型数组长度属性操作数组 数组:(…...
【模型预测控制MPC】使用离散、连续、线性或非线性模型对预测控制进行建模(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
Golang之路---01 Golang VS Code创建项目
Golang VS Code创建项目 代码组织 Golang使用包和模块来组织代码,包对应到文件系统就是文件夹,模块就是xxx.go的go源文件。一个包中会有多个模块,或者多个子包。 早期使用的是gopath来管理项目,不方便,比较麻烦&…...
vue 表单form-item模板(编辑,查看,新建)
目录 formatFormData 后端数据格式编辑 JSON解析和生成 加载(请求前,await后) formComp formatFormData 后端数据格式 为空的,可以直接不提交/提交null/undefined JSON解析和生成 var str {"name": "…...
【IC设计】DC工具的target、link、synthetic、symbol库
Specifying Libraries You use dc_shell variables to specify the libraries used by Design Compiler. Table 4-1 lists the variables for each library type as well as the typical file extension for the library. 你使用dc_shell变量去指定dc要使用的库。下表列出了每种…...
redisson常用APi-Example
中文文档目录 redisson中文文档目录 分布式对象 package com.example.redissondemo.test;import com.example.redissondemo.RedissonDemoApplication; import com.example.redissondemo.test.domain.Order; import lombok.Data; import lombok.extern.slf4j.Slf4j; import o…...
小程序学习(四):WXML模板语法
WXML模板语法-数据绑定 1.数据绑定的基本原则 ①在data中定义数据 ②在WXML中使用数据 2.动态绑定属性 WXML模板语法-事件绑定 3.什么是事件 4.小程序中常用的事件 5.事件对象的属性列表 6.target和currentTarget的区别 7.bindtap的语法格式 8.在事件处理函数中为data中的数据…...
IDEA好用的插件总结
IdeaVim 这个看个人喜好,我比较喜欢用vim,并且支持自定义修改按键绑定alibaba java code guidelines alibaba的java编程规范plantUML 绘制UML,支持语言显示plantUML integration 能够直接将代码转化为UML图,非常方便rainbow brack…...
如何在Linux系统中安装ActiveMQ
1、环境 ActiveMQ是一个纯Java程序,这里安装5.18.2版ActiveMQ,该版MQ运行在JDK 11环境内,为此需要先搭建JDK 11环境,这里安装JDK 15。 1.1、卸载 卸载开源JDK软件包,如下所示: [rootlocalhost ~]# rpm -…...
【Latex】常用公式编辑与符号:公式换行,标号居中、常用符号等
【Latex】常用公式编辑与符号 文章目录 【Latex】常用公式编辑与符号1. 公式换行,且标号居中2. 常用符号3. 常用的希腊字母 1. 公式换行,且标号居中 \begin{equation}\label{eq14} \begin{aligned}a & b/c, \\d & e/f \end{aligned} \end{equ…...
【ArcGIS Pro二次开发】(55):给多个要素或表批量添加字段
在工作中可能会遇到这样的场景:有多个GDB要素、表格,或者是SHP文件,需要给这个要素或表添加相同的多个字段。 在这种情况下,手动添加就变得很繁琐,于是就做了这个工具。 需求具体如下图: 左图是待处理数据…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
