Zookeeper 源码分析流程
文章目录
- 前言
- Zookeeper启动
- 加载磁盘数据
- 与客户端的通信交互
- Leader选举准备
- 节点状态处理
- 总结
前言
Zookeeper 作为分布式协调服务为分布式系统提供了一些基础服务,如:命名服务、配置管理、同步等,使得开发者可以更加轻松地处理分布式问题。
在分布式系统中,协调是一项关键任务。例如,如何让一组独立的进程或机器知道它们应该执行哪些任务,如何将它们的状态同步到其他进程或机器上,以及如何处理故障或异常等。这些问题都是 Zookeeper 所解决的问题。
本文将带你深入了解 Zookeeper 的内部实现,从其各个组件和接口开始,分析其工作原理和设计思想。希望你在阅读这个源码分析的过程中,能够深入理解 Zookeeper 的工作原理和设计思想,从而更好地利用它来解决你的分布式问题。
Zookeeper启动
无论看什么代码,我们都应该从程序的入口点入手,这样可以更好地理解整体的结构和运行流程。

通过 zkServer.sh 脚本可以看到启动类为QuorumPeerMain。

可以看到Zookeeper启动是通过main方法开始的,最终调用了runFromConfig方法设置并启动一个ZooKeeper的集群节点。

上面的代码设置了QuorumPeer的事务日志和快照目录路径、选举算法选择、指定服务器ID、定义时钟周期和数据保存实例等配置。此外,还创建了服务器和客户端连接的工厂类(NIO/Netty)。最后,调用start方法启动服务。

在start中,主要完成了以下四个任务:
- 将磁盘中的数据加载到内存中,为后续的处理和响应提供必要的数据储备。
- 建立Socket来处理客户端的请求,实现与客户端的通信交互。
- 进行了Leader的选举准备工作,确定选举算法。。
- 进行Leader选举并对节点状态进行监听并相应处理,及时发现和处理节点故障或异常状态,确保整个系统的可靠性和稳定性。
加载磁盘数据
ZooKeeper 操作事内存级别的,为了保障可靠性,会将数据以事务日志形式持久化到文件中,所以在启动时先加载数据到内存。

这段代码的主要目的是从磁盘加载Zookeeper数据库到内存,并检查并处理相关的epoch信息。getDataTree().lastProcessedZxid 这行代码获取在ZooKeeper服务器上已处理的最新的事务的zxid,ZxidUtils.getEpochFromZxid(lastProcessedZxid)这行代码从zxid中获取epoch,readLongFromFile(CURRENT_EPOCH_FILENAME): 这行代码从文件中读取当前的epoch信息。如果zxid所属的epoch小于当前的epoch,会抛出IOException异常。
与客户端的通信交互
cnxnFactory 是建立了Socket 服务端,用来接收客户端的请求并处理,下图中的代码是NIOServerCnxnFactory,还有一个NettyServerCnxnFactory。选用NIO还是Netty可以在配置文件中设置。对NIO和Netty不熟悉的可以看下网络编程专栏

最核心的就是对客户端请求的处理,有如下几个处理器:

CommitProcessor是事务提交处理器,它会等待集群内针对Proposal的投票直到该Proposal可以被提交。SyncRequestProcessor负责把事务请求(写request)持久化到本地磁盘。AckRequestProcessor是Leader特有的处理器,其主要职责是在SyncRequestProcessor处理器完成事务日志记录后,向Proposal的投票收集器发送ACK反馈,以通知投票收集器当前服务器已经完成了对该Proposal的事务日志记录。FollowerRequestProcessor这个处理器可能会负责处理来自客户端的读请求和写请求,并将其转发给其他处理器进行处理,比如写请求转发给Leader节点。SendAckRequestProcessor负责向领导者(Leader)节点发送确认收到的消息(ACK),通知领导者节点该请求已经得到处理。
Leader选举准备
startLeaderElection 中主要调用了createElectionAlgorithm 创建了集群间网络连接的管理器 QuorumCnxManager,并选择了一个选举算法,这个通过配置文件配置,默认为FastLeaderElection。

节点状态处理
super.start()执行 QuorumPeer.java 类中的 run()方法,主要是对节点状态的监听及处理。

当 Zookeeper 启动后,首先都是 Looking 状态,通过选举,让其中一台服务器成为 Leader,其他的服务器成为 Follower。如果代码比较难理解可以看一下ZAB协议。

总结
通过深入解析源代码,我注意到其简洁性以及对功能实现的巧妙设计。尽管代码所处理的功能相当复杂,但组织结构和代码风格的简洁性使得阅读和理解变得相当容易。特别注意到网络编程的大量应用,对连接安全和优化的细致处理。还有其ZAB协议如何巧妙地解决了分布式一致性问题,这些细腻的设计理念无疑为分布式系统的开发提供了宝贵的借鉴,期待能在未来的工作中将这些思想融入到的代码中。
相关文章:
Zookeeper 源码分析流程
文章目录 前言Zookeeper启动加载磁盘数据与客户端的通信交互Leader选举准备节点状态处理总结 前言 Zookeeper 作为分布式协调服务为分布式系统提供了一些基础服务,如:命名服务、配置管理、同步等,使得开发者可以更加轻松地处理分布式问题。 …...
计数排序与基数排序
计数排序与基数排序 计数排序 计数排序:使用一个数组记录序列中每一个数字出现的次数,将该数组的下标作为实际数据,元素的值作为数据出现的次数。例如对于序列[3,0,1,1,3,3,0,2],统计的结果为: 0出现的次数…...
Mysql—表操作
目录 1、linux中数据库表名区分大小写,windows不区分2、创建数据库表3、外键4、查看数据表结构5、修改表5.1、修改表名5.2、添加字段5.3、指定位置添加字段5.4、修改字段名称5.5、修改字段类型5.6、修改字段位置5.7、删除字段5.8、修改表存储引擎5.9、删除外键 1、l…...
SpringCloud——微服务
微服务技术栈 在之前的开发过程中,我们将所有的服务都部署在一台服务器中,当我们的服务开始越来越多,业务越来越复杂,当一台服务器不能承担我们的业务的时候,就需要将不同的业务分开部署在不同的服务器上,…...
深入理解Java单例模式和优化多线程任务处理
目录 饿汉模式懒汉模式单线程版多线程版双重检查锁定 阻塞队列 单例模式能保证某个类在程序中只存在唯一一份实例, 而不会创建出多个实例,并提供一个全局访问点。 饿汉模式 类加载的同时,创建实例。 class Singleton {private static final Singlet…...
已解决 Kotlin Error: Type mismatch: inferred type is String but Int was expected
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页: 🐅🐾猫头虎的博客🎐《面试题大全专栏》 🦕 文章图文并茂🦖…...
Web应用系统的小安全漏洞及相应的攻击方式
写作目的 本文讲述一个简单的利用WebAPI来进行一次基本没有破坏力的“黑客”行为。 主要目的如下: 了解什么叫安全漏洞 知道什么是api 了解一些获取api的工具 通过对API的认识了解白盒接口测试基本概念和技术 免责声明: 本文主要是以学习交流为目的&a…...
git工具下载和安装
(1)从git官网下载安装包 然后安装 https://git-scm.com/downloads (2)git 学习参考官方的资料 https://git-scm.com/book/en/v2...
腾讯mini项目-【指标监控服务重构】2023-08-04
今日已办 关于 span-references 的调研 https://github.com/DataDog/dd-trace-js/issues/1761 https://github.com/open-telemetry/opentelemetry-specification/blob/874a451e7f6ac7fc54423ee3f03e5394197be35b/specification/compatibility/opentracing.md#span-references h…...
怎么推广自己抖店的商品?最适合0经验新手操作的办法,来看看
我是王路飞。 抖店开通后,想要把自己店铺的商品卖出去,就需要进行推广了。 但是怎么推广呢? 要么利用抖音的搜索和推荐流量,获取曝光,实现点击和转化。 不过这种玩法有个弊端,就是需要你有一定的电商经…...
线性代数的本质(三)——线性方程组
文章目录 线性方程组高斯消元法初等行变换线性方程组的解向量方程齐次线性方程组的解非齐次线性方程组的解 线性方程组 高斯消元法 客观世界最简单的数量关系是均匀变化的关系。在均匀变化问题中,列出的方程组是一次方程组,我们称之为线性方程组(Linea…...
轻量级性能测试工具 wrk 如何使用?
项目设计之初或者是项目快要结束的时候,大佬就会问我们,这个服务性能测试的结果是什么,QPS 可以达到多少,RPS 又能达到多少?接口性能可以满足未来生产环境的实际情况吗?有没有自己测试过自己接口的吞吐量&a…...
WebGL 视图矩阵、模型视图矩阵
目录 立方体由三角形构成 视点和视线 视点、观察目标点和上方向 视点: 观察目标点: 上方向: 在WebGL中,观察者的默认状态应该是这样的: 视图矩阵程序(LookAtTriangles.js) 实际上&…...
Python 3 – 文件 readline() 方法
Python 3 – 文件 readline() 方法|极客笔记 # 打开文件 file open("example.txt", "r")# 读取文件中的一行数据 line file.readline() while line:# 移除行尾的换行符print(line.strip())# 读取文件中的下一行数据line file.readline()# 关闭文件 file…...
如何在微软Edge浏览器上一键观看高清视频?
编者按:视频是当下最流行的媒体形式之一。但由于视频压缩、网络不稳定等原因,我们常常可以看到互联网上的很多视频其画面质量并不理想,尤其是在浏览器端,这极大地影响了观看体验。不过,近期微软 Edge 浏览器推出了一项…...
Telegram BoT的主流项目盘点
目录 DeFi 类 数据分析类 空投埋伏交易 其他 Telegram Bot赛道的发展趋势预测 Telegram BoT赛道发展较快,具体来看可以分为DeFi 类、数据分析类、空投埋伏交易类以及其他。 DeFi 类 Unibot(交易)、Banana Gun、WagieBot(交…...
PTA 甲级 1044 Shopping in Mars
题目链接 思路:前缀和滑动窗口 #include<bits/stdc.h> #define MAXN 100010 using namespace std; int a[MAXN];int main(){int n,m;cin>>n>>m;//n数量 m金额for(int i1;i<n;i){int t;cin>>t;a[i]a[i-1]t;//前缀和}vector<pair<in…...
Linux学习之MyCat实现分库分表
环境准备 先准备一套MySQL主从服务器,可参考MySQL主从配置配置MyCat服务 资源下载 网盘链接: https://pan.baidu.com/s/1cLTMH_e1-6loc_gF9ZNHTg?pwda63n 提取码: a63n MyCat配置 # 1)安装mycat软件 //安装jdk [rootmycat58 upload]# yum -y insta…...
DirectX12(d3d12)初始化
一、前置要求 Windows 10及以上(安装有DirectX12)VisualStudio 2022 二、DirectX12入门 1.引用头文件 #include<Windows.h> #include<d3d12.h> #include<dxgi1_4.h>2.注册窗口类并初始化窗口 这里我们调用Windows API 通过应用程序的句柄来注册一个唯一…...
算法通关村-----回溯模板如何解决排列组合问题
组合总和 问题描述 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。candidates 中的 同一个 数字可以 无限…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
