【Zookeeper专题】Zookeeper选举Leader源码解析

news2024/11/19 18:43:24

目录

  • 前言
  • 阅读建议
  • 课程内容
    • 一、ZK Leader选举流程回顾
    • 二、源码流程图
    • 三、Leader选举模型图
  • 学习总结

前言

为什么要看源码?说实在博主之前看Spring源码之前没想过这个问题。因为我在看之前就曾听闻大佬们说过【JavaCoder三板斧:Java,Mysql,Spring】,所以我抱着积极的学习心态去看的。另外,我也发现了一个很有意思的现象:就是我们一群人在学习,但是每个人学习的【偏好】似乎是不一样的,或者说关注的重点不一样。所以,其实我也不知道自己关注的重点到底对不对,但总归是有收获的。
现在回过头来再看ZK源码,有必要学习吗?一开始我是觉得没必要的,因为不少人说ZK源码写的很抽象、不规范,但还是有人坚持说学习一下比较好。现在稍微学习了一小段之后,我突然间有点感悟:ZK源码还是值得学习阅读的,甚至所有市面上以Java编写的分布式中间件都值得学习。为什么呢?
首先,ZK服务端是以Java编写出来的程序,所以,我们在阅读ZK源码的时候,何尝不是一种进步呢?(咱可是直接在看行业大拿的源码啊)
其次,也可能是最重要的,如果我们想成为一个优秀的JavaCoder,甚至是架构师,这确实是一条必经之路,毕竟这些成熟、优秀的产品架构,肯定能让你学到很多东西(修炼内功);
还有啊,这些成熟、优秀的源码,难道不值得学习吗?这或许是世界上,Java里面最牛逼的源码之一了!
以上是我的一些思考。

同样,这个问题,我的老师也给出了他们的答案,在这里分享给大家:

Q1:为什么要学习源码?
答:

  1. 提升技术功底:学习源码里的优秀设计思想,比如一些疑难问题的解决思路,还有一些优秀的设计模式,整体提升自己的技术功底
  2. 深度掌握技术框架:源码看多了,对于一个新技术或框架的掌握速度会有大幅提升,看下框架demo大致就能知道底层的实现,技术框架更新再快也不怕
  3. 快速定位线上问题:遇到线上问题,特别是框架源码里的问题(比如bug),能够快速定位,这就是相比其他没看过源码的人的优势
  4. 对面试大有裨益:面试一线互联网公司对于框架技术一般都会问到源码级别的实现
  5. 知其然知其所以然:对技术有追求的人必做之事,使用了一个好的框架,很想知道底层是如何实现的
  6. 拥抱开源社区:参与到开源项目的研发,结识更多大牛,积累更多优质人脉

阅读建议

看源码方法:

  1. 先使用:先看官方文档快速掌握框架的基本使用
  2. 抓主线:找一个demo入手,顺藤摸瓜快速静态看一遍框架的主线源码,画出源码主流程图,切勿一开始就陷入源码的细枝末节,否则会把自己绕晕。实在看不懂的凭经验猜
  3. 画图做笔记:总结框架的一些核心功能点,从这些功能点入手深入到源码的细节,边看源码边画源码走向图,并对关键源码的理解做笔记,把源码里的闪光点都记录下来,后续借鉴到工作项目中,理解能力强的可以直接看静态源码,也可以边看源码边debug源码执行过程,观察一些关键变量的值
  4. 整合总结:所有功能点的源码都分析完后,回到主流程图再梳理一遍,争取把自己画的所有图都在脑袋里做一个整合

课程内容

我跟着老师看了一下源码,说实在,思考了很久实在不知道怎么给大家伙记下来分享给大家,有点无从下手的感觉,因为相关性太大了。所以,这里算是自结吧,主要是为了加深个人理解,以及方便后续回头看。

一、ZK Leader选举流程回顾

在这里插入图片描述
我在之前的笔记当中有写过选举原理,但是有点囫囵吞枣,后来才知道原来这个挺重要的,算是ZK比较重点的内容之一。现在这里重新讲解一番。

什么是Leader选举
ZooKeeper的Leader选举过程是基于投票和对比规则的,确保集群中选出一个具有最高优先级的服务器作为Leader来处理客户端请求,以及同步数据给集群中的其他节点。

选举规则
选举投票对比规则如下:

  • 首先比较epoch,选取具有最大epoch的服务器。epoch用于区分不同的选举轮次,每次重新选举时都会增加epoch。
  • 如果epoch相同,则比较zxid(事务ID),选取事务ID最大的服务器。zxid表示最后一次提交的事务ID。
  • 如果zxid也相同,则比较myid(服务器ID),选取服务器ID最大的服务器。

epoch:表示ZooKeeper服务器的逻辑时期(logical epoch),它是一个相对时间的概念,用于区分不同的Leader选举周期。
zxid:是一个64位的整数,由高32位的epoch和低32位的counter组成。
counter:是一个在每个时期(epoch)内递增的计数器,用于标识事务的顺序。

选举流程
首先得说明的是,ZK的Leader选举是分两步的,所以又叫:两阶段选举。为什么需要两个阶段?接下来我们看一下流程,这个流程是我们网上能搜索到的,大家都清楚的流程:(流程按照上面的模型图。即:假设集群中有3个节点,并且只启动了2个节点,第3个节点没启动)

  1. ZK集群刚启动的时候,由于他们仍未经历过选举,所以每一台ZK机器中,上面投票规则提到的epoch肯定是一样的,包括zxid,毕竟还没有接受过客户端的读写,所以唯一的差异就在myId上了
  2. 开始第一阶段选举:由于彼此还不知道谁的epochzxidmyId,所以会优先将票投给自己,并且广播出去;当然也能接收到别的服务器【投票自己的广播】。所以,myid=1的机器按照投票规则,投票vote=(1, 0),并且收到myid=2的投票vote=(2, 0);同时myid=2的机器按照投票规则,投票vote=(2, 0),并且收到myid=1的投票vote=(1, 0)。显然,目前投票情况是服务1跟服务2各收到一张选票,所以Leader没办法选举出来
  3. 第二阶段选举:每个节点服务器收到投票广播后,按照投票选举规则,各自更新自己最新的投票。比如:myid=1的服务器经过比较之后,发现myid=2比自己更适合当Leader,于是在第二轮投票的时候投票vote=(2,0);而myid=2的服务也经过比较之后,觉得还是自己适合做Leader,于是在第二轮投票的时候投票vote=(2,0)。就这样,myid=2的服务收到了2张选票,2 > (3/2),符合【过半机制】,于是成为了Leader
  4. 接着myid=3的节点上线,发现已经有Leader了,那不用投票了,直接把自己置为Follower(也许有人问,为什么不重新选举?因为没必要啊,对于ZK集群来说,尽快对外服务才是重点,重新选举不是浪费时间嘛)

OK,流程回顾就到这里。相信大伙通过这个业务流程去理解代码,将会事半功倍。

二、源码流程图

说明:我估计很多人源码入口都找不到,给大家一个方法,也是很多源码阅读的办法。那就是从启动脚本找,比如ZK,我们知道它的启动脚本为zkServer.sh,那就在里面找好了。

ZK源码入口类:org.apache.zookeeper.server.quorum.QuorumPeerMain
下面是是一个自结的源码流程图,不是很好看。感兴趣的大伙,可以跟着我的流程图看一遍源码
在这里插入图片描述
看完选举源码之后的一些总结与思考:

  1. 【总结】比较清晰的了解,为什么是二阶段选举,因为ZK在设计投票与选举的时候,是使用两个独立的业务领域类(独立的线程)来完成的(投票决策领域类 + 投票发送/接受领域类),也就是说,他们的数据并非是直接耦合在一起的(我描述的比较抽象,咱也不知道该怎么解释了)。
  2. 【总结】在投票、选举中,ZK新建了好几个业务线程,往往是,一个业务领域类本身就是一个线程子类,然后在run方法中实现各自领域的逻辑。每个线程通常各自维护了一条阻塞队列,线程之间交换数据是将消息发送至对应的阻塞队列中。也许,这就是JVM级别,不基于中间件的线程通信的可靠手段之一吧
  3. 【思考】Leader节点与Follower节点,节点之间投票都分别监听了独立的端口,使用独立的scoket进行通信交互。其实前者Leader节点与Follower节点数据同步采用socket长连接保持通信我是能理解的,但是选举方面,我发现这个需求本来就不是特别大,为什么也要用socket通信呢?为什么不是http?别笑我哈,我一直以为socket比起http是一种比较重度的通信手段。现在看来可能跟我想象的不一样。sockert是传输层协议,http是应用层协议,且两者安全性方面前者更高。下面是来自gpt的回答:
    在这里插入图片描述
    在这里插入图片描述
  4. 【总结】BIO网络连接在简单的应用通信之间,还是很可靠的,人家ZK都这么玩

三、Leader选举模型图

接下来再给大家画一下,选举的相关模型图。
整个zookeeper选举底层可以分为【选举逻辑层】和【选举消息传输层】,【逻辑层】有自己的队列统一接收和发送选票,【传输层】也设计了自己的队列,但是按发送的机器分了队列,避免给每台机器发送消息时相互影响,比如某台机器如果出问题发送不成功则不会影响对正常机器的消息发送。
在这里插入图片描述

学习总结

  1. 学习了ZK底层选举源码,学习像JUC,阻塞队列、网络通信在这种优秀应用中的使用思路
  2. 学习了ZK源码设计思想。其实我看着很像是DDD的领域设计

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1081634.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式_责任链

责任链模式 介绍 设计模式定义案例责任链模式问题 传给 多个可处理人 这多个处理人做成一个链表学生请假条审核 上课老师(3天权限) 班主任 (5天权限) 校长 (30天权限) 问题堆积在哪里解决办法进一步优…

目标检测新思路:DETR

Transformer是一种基于自注意力机制的神经网络架构,它能够从序列中提取重要信息,已被广泛应用于自然语言处理和语音识别等领域。随着Transformer的提出和发展,目标检测领域也开始使用Transformer来提高性能。 DETR是第一篇将Transformer应用于…

点击弹窗页面右侧缩小问题

主页面是由header和下面的tabel&#xff0c;2个组件构成&#xff0c;需要在css里使用flex布局&#xff0c; 就解决了弹窗导致的页面右侧缩小问题。 display: flex; flex-direction: column; <template><div class"main"><div class"header"…

局域网远程控制

被控制端电脑设置 1开启服务 Romate Desktop Services 2设置允许远程控制&#xff0c;并且添加被控制的用户 3检查用户组管理用户名是否一致 我的电脑>管理>本地用户和组>用户 4在控制电脑端WinR 输入 mstsc出现如下界面 输入被控制电脑IP和用户名 然后输入被控制端…

第十届蓝桥杯省赛C++C/研究生组,第十届蓝桥杯省赛JAVAC/研究生组——扫地机器人题解(二分)

题目描述 小明公司的办公区有一条长长的走廊&#xff0c;由 N个方格区域组成&#xff0c;如下图所示。 走廊内部署了 K台扫地机器人&#xff0c;其中第 i台在第 A i A_i Ai​ 个方格区域中。 已知扫地机器人每分钟可以移动到左右相邻的方格中&#xff0c;并将该区域清扫干净…

Android组件通信(二十四)

1. Activity生命周期 1.1 知识点 &#xff08;1&#xff09;掌握Activity的生命周期及操作方法&#xff1b; 1.2 具体内容 范例&#xff1a; 第一个配置文件 <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http…

C语言常见题目(1)交换两个变量的值,数的逆序输出,猜数游戏,两个数比较大小等

我的个人主页&#xff1a;☆光之梦☆的博客_CSDN博客-C语言基础语法&#xff08;超详细&#xff09;领域博主 欢迎各位 &#x1f44d;点赞 ⭐收藏 &#x1f4dd;评论 特别标注&#xff1a;本博主将会长期更新c语言的语法知识&#xff0c;初学c语言的朋友们&#xff0c;可以收藏…

面试经典 150 题 3 —(双指针)— 167. 两数之和 II - 输入有序数组

167. 两数之和 II - 输入有序数组 方法一 class Solution { public:vector<int> twoSum(vector<int>& numbers, int target) {unordered_map<int,int> hashtable;for(int i 1; i < numbers.size(); i){auto item hashtable.find(target - numbers[…

Allegro基本规则设置指导书之Spacing规则设置

进入规则设置界面 1.设置Line 到其他的之间规则: 2.设置Pins 到其他的之间规则: 3.设置Vias 到其他的之间规则:

微软开源 windows-drivers-rs,用 Rust 开发 Windows 驱动程序

Microsoft Azure 首席技术官兼著名 Windows 软件开发人员 Mark Russinovich 在社交平台上宣布&#xff0c;启动了一个名为 windows-drivers-rs 的新开源项目。 该项目可帮助开发人员使用 Rust 开发 Windows 驱动程序&#xff0c;旨在支持 WDM (Windows Driver Model) 和 WDF (…

Pandas将两个Excel表格找出不同之处-对比两个文件-merge合并查询

Demo示例&#xff1a; 现有两个Excel表格&#xff0c;SKU不同&#xff0c;需要找出不同之处 代码结果演示&#xff1a; 代码&#xff1a; import pandastest1_path rC:\Users\Administrator\Desktop\新建文件夹 (2)\test1.xlsx test2_path rC:\Users\Administrator\Deskto…

pyqt 划线标注工具

效果图: 代码: import osfrom PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout, QPushButton, QLabel from PyQt5.QtGui import QPainter, QPen, QColor, QImage, QPixmap from PyQt5.QtCore import Qt, QPoint import sys import jsonclass ImageLabel(QLabel)…

接口自动化测试 —— 协议、请求流程

一、架构 CRM客户关系管理系统 SAAS Software As A Service 软件即服务 PAAS Platform AS A Service 平台即服务 快速交付→ 快&#xff1a;自己去干、有结果、事事有回音、持续改进 单体架构——》垂直架构——》面向服务架构——》微服务架构&#xff08;分布式&#xf…

(学习笔记)U-net++代码解读

U-net 声明&#xff1a;本文只提供代码部分。声明&#xff1a;内容为题主学习时的疑问&#xff0c;仅供初学者参考。python&#xff1a; 3.10 U-net结构图遇到的问题1. albumentations包安装的问题2. AttributeError: module albumentations.augmentations.transforms has no a…

0.在Linux Centos7下安装MySQL及其配置

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 目录 1.检查是否已有MySQL 2. 检查系统安装包 3. 卸载这些默认安装包 4. 获取mysql官⽅yum源 5.安装mysql的yum源&#xff0c;对⽐前后yum源 6.看看能不能正常⼯作 7. 安装mysql服务 8.查看配置⽂件和数据存储位置 …

【编程必备知识】文件操作

文章目录 前言1. 认识文件1.1 树型结构组织和目录1.2 文件路径1.2.1 绝对路径1.2.2 相对路径 1.3 文件类型 2. Java 中操作文件2.1 File 概述2.1.1 构造方法2.1.2 成员方法 2. 2 代码示例示例1: 观察 get 系列的特点和差异示例2: 普通文件的创建示例3: 普通文件的删除示例4: 观…

手写Spring系列【一】IOC的简单实现笔记

前言&#xff1a; &#x1f44f;作者简介&#xff1a;我是笑霸final&#xff0c;一名热爱技术的在校学生。 &#x1f4dd;个人主页&#xff1a;个人主页1 || 笑霸final的主页2 &#x1f4d5;系列专栏&#xff1a;项目专栏 &#x1f4e7;如果文章知识点有错误的地方&#xff0c;…

uni-app:文本超出部分用省略号表示

效果 前 后 核心代码 white-space: nowrap; /* 强制不换行 */ text-overflow: ellipsis; /* 超过部分省略号代替 */ overflow: hidden; /* 必须同时设置overflow:hidden才能生效 */ 完整代码 <template><view><view class"all_style"><view c…

「才得吹嘘身渐稳」,也来谈谈大模型

要问2023年的科技领域什么消息最博人眼球&#xff0c;那么22年底发布、23年迅速跻身顶流的ChatGPT一定占有一席之地。随着ChatGPT的“爆火出圈”&#xff0c;国内外大厂纷纷布局「生成式语言模型」研发赛道&#xff0c;各类应用也如雨后春笋般层出不穷&#xff0c;让人眼花缭乱…

SpringBoot的配置文件——.yml和.properties

目录 1. Spring Boot 配置文件的使用场景 2. 配置文件的两种格式 2.0 特殊说明&#xff1a; 2.1 .properties 2.1.1 格式 2.2.2 缺陷 2.2.3 解决中文乱码的问题 2.2 .yml 2.2.3 格式 配置数据库连接 注意转义字符 ​编辑 ​编辑 配置null 配置对象 从.yml读取文件举例 Stud…