java基础之----zookeeper

概述

  zookeeper,拆开来就是zoo  keeper,翻译就是动物管理员,为什么这么命名呢?因为当时yahoo开发zookeeper的时候,已经开发很多其他的产品,都是以动物命名的,而zookeeper的作用就是要协调这些产品,所以最后就命名为了动物管理员。相信每个人都不陌生,无论是阿里的dubbo把zookeeper作为注册中心,无论是在使用kafka还有hbase的时候都离不开zookeeper,那zookeeper到底是什么,又可以干什么呢?

zookeeper是什么?

简单来说就是zookeeper是一个分布式协调服务。

zookeeper可以干什么?

可用于服务发现,分布式锁,配置管理等

zookeeper的架构

zookeeper是一个集群,集群中由3中角色。

  Leader: 维护和Follower,Observer的心跳,写请求必须通过leader,并且同步到Follower,Observer,集群中只有一个Leader

Follower: 处理读请求,将写请求转发给Leader,集群中一般由多个Follower

Observer: 功能和Follower类似,只是不参与投票。

由以上可知,zookeeper只有Leader负责写操作,如果有多个线程同时执行写操作,会导致Leader节点的负载太大,有崩溃的风险,而Leader如果崩溃,zookeeper就会触发重新选主过程,在这个过程中zookeeper是不能对外提供服务的,这个过程一般会持续几十秒,可想而知,这个后果有多严重,但是zookeeper有多个Follower和Oberver可以处理读请求,所以zookeeper适合那种读多写少的场景。 

zookeeper的选主过程

zookeeper触发选主过程有两种场景,一种是zookeeper集群刚刚启动时,第二种时运行期间主节点出现问题,出现什么问题呢?比如主节点崩溃,主节点网络出现问题等都会触发重新选主过程。zookeeper选主采用的是FastLeaderElection算法,下面就介绍一下该算法。

先介绍一下选票的数据结构

  • logicClock 每个服务器会维护一个自增的整数,名为logicClock,它表示这是该服务器发起的第多少轮投票
  • state 当前服务器的状态
  • self_id 当前服务器的myid
  • self_zxid 当前服务器上所保存的数据的最大zxid
  • vote_id 被推举的服务器的myid
  • vote_zxid 被推举的服务器上所保存的数据的最大zxid

这里解释一下myid,zxid

myid

安装过集群模式zookeeper都知道,我们需要自己创建一个名为myid的文件,里面会写上这个节点的编号,比如在文件里面写上1,就表示该节点的编号为1;

zxid

下面再说说zxid,这玩意其实是一个64位的字符,前面32位epoch是用来标识主节点的,因为每次选举出来一个主节点,都会生成一个不同的epoch,后面32位是一个递增计数,那记什么数呢,是这样的,zookeeper的每个节点发生改变都会对后32进行加1处理。那我的问题又来了,为什么节点改动就要进行加1操作呢?举个例子说明,现在有一个写操作,主节点这个zxid进行了加1操作,现在主节点要把这个写操作同步到Follower和Observer,那如果有些同步成功了,那成功的zxid就会加1,而同步失败就不会,这样又有什么用呢?这个的用处在下面介绍的选举过程就会体现出来。

投票流程

自增选举轮次

ZooKeeper规定所有有效的投票都必须在同一轮次中。每个服务器在开始新一轮投票时,会先对自己维护的logicClock进行自增操作。

初始化选票

每个服务器在广播自己的选票前,会将自己的投票箱清空。该投票箱记录了所收到的选票。例:服务器2投票给服务器3,服务器3投票给服务器1,则服务器1的投票箱为(2, 3), (3, 1), (1, 1)。票箱中只会记录每一投票者的最后一票,如投票者更新自己的选票,则其它服务器收到该新选票后会在自己票箱中更新该服务器的选票。

发送初始化选票

每个服务器最开始都是通过广播把票投给自己。

接收外部投票

服务器会尝试从其它服务器获取投票,并记入自己的投票箱内。如果无法获取任何外部投票,则会确认自己是否与集群中其它服务器保持着有效连接。如果是,则再次发送自己的投票;如果否,则马上与之建立连接。

判断选举轮次

收到外部投票后,首先会根据投票信息中所包含的logicClock来进行不同处理:

  • 外部投票的logicClock大于自己的logicClock。说明该服务器的选举轮次落后于其它服务器的选举轮次,立即清空自己的投票箱并将自己的logicClock更新为收到的logicClock,然后再对比自己之前的投票与收到的投票以确定是否需要变更自己的投票,最终再次将自己的投票广播出去。
  • 外部投票的logicClock小于自己的logicClock。当前服务器直接忽略该投票,继续处理下一个投票。
  • 外部投票的logickClock与自己的相等。当时进行选票PK。

选票PK

选票PK是基于(self_id, self_zxid)与(vote_id, vote_zxid)的对比:

  • 外部投票的logicClock大于自己的logicClock,则将自己的logicClock及自己的选票的logicClock变更为收到的logicClock
  • 若logicClock一致,则对比二者的vote_zxid,若外部投票的vote_zxid比较大,则将自己的票中的vote_zxid与vote_myid更新为收到的票中的vote_zxid与vote_myid并广播出去,另外将收到的票及自己更新后的票放入自己的票箱。如果票箱内已存在(self_myid, self_zxid)相同的选票,则直接覆盖
  • 若二者vote_zxid一致,则比较二者的vote_myid,若外部投票的vote_myid比较大,则将自己的票中的vote_myid更新为收到的票中的vote_myid并广播出去,另外将收到的票及自己更新后的票放入自己的票箱

这六步是重中之重,上面在介绍zxid的时候说这玩意会在选举过程用到,第五步就用到了,而且可以看出,当选票轮次相同时,时先根据zxid进行优先判断的,只有当zxid相等时才会根据myid判断,上面也介绍到触发选主的两种情况,第一种时集群刚刚启动时,这是其实说有节点的zxid都是一样的,所以这时都是根据myid判断的,但是如果是因为主节点崩溃触发的选主,那就要优先根据zxid进行判断了。

统计选票

如果已经确定有过半服务器认可了自己的投票(可能是更新后的投票),则终止投票。否则继续接收其它服务器的投票。

更新服务器状态

投票终止后,服务器开始更新自身状态。若过半的票投给了自己,则将自己的服务器状态更新为LEADING,否则将自己的状态更新为FOLLOWING。

zookeeper的应用

zookeeper作为分布式锁

之前看过一篇文章,写的非常好,在这里我就总结一下,然后把那篇文章引用进来,总结下来来说就是,zookeeper会维护一个临时顺序节点,当有进程或者线程申请加锁时,zookeeper会创建一个临时节点,当多线程竞争锁时,zookeeper会为每个线程或者进程创建一个临时节点,并别时有顺序的,然后,zookeeper会这样做,就是后一个节点会监听前一个节点,举个例子,第一个节点监听发现他前面没有节点了,就会直接获取锁,当锁释放时会删除这个临时节点,这时第二个节点发现他前面也没有节点了,那相应的第二个节点就获取到锁。

文章地址:https://www.itcodemonkey.com/article/11887.html

zookeeper作为注册中心

zookeeper作为注册中心,可以提供服务发现,具体是这样做的,zookeeper可以充当一个服务注册表(Service Registry),让多个服务提供者形成一个集群,让服务消费者通过服务注册表获取具体的服务访问地址(ip+端口)去访问具体的服务提供者。

在zookeeper中,进行服务注册,实际上就是在zookeeper中创建了一个znode节点,该节点存储了该服务的IP、端口、调用方式(协议、序列化方式)等。该节点承担着最重要的职责,它由服务提供者(发布服务时)创建,以供服务消费者获取节点中的信息,从而定位到服务提供者真正网络拓扑位置以及得知如何调用。RPC服务注册、发现过程简述如下:

服务提供者启动时,会将其服务名称,ip地址注册到配置中心。
服务消费者在第一次调用服务时,会通过注册中心找到相应的服务的IP地址列表,并缓存到本地,以供后续使用。当消费者调用服务时,不会再去请求注册中心,而是直接通过负载均衡算法从IP列表中取一个服务提供者的服务器调用服务。
当服务提供者的某台服务器宕机或下线时,相应的ip会从服务提供者IP列表中移除。同时,注册中心会将新的服务IP地址列表发送给服务消费者机器,缓存在消费者本机。
当某个服务的所有服务器都下线了,那么这个服务也就下线了。
同样,当服务提供者的某台服务器上线时,注册中心会将新的服务IP地址列表发送给服务消费者机器,缓存在消费者本机。
服务提供方可以根据服务消费者的数量来作为服务下线的依据。

感知服务的下线&上线

zookeeper提供了“心跳检测”功能,它会定时向各个服务提供者发送一个请求(实际上建立的是一个 socket 长连接),如果长期没有响应,服务中心就认为该服务提供者已经“挂了”,并将其剔除,比如100.19.20.02这台机器如果宕机了,那么zookeeper上的路径就会只剩/HelloWorldService/1.0.0/100.19.20.01:16888。

服务消费者会去监听相应路径(/HelloWorldService/1.0.0),一旦路径上的数据有任务变化(增加或减少),zookeeper都会通知服务消费方服务提供者地址列表已经发生改变,从而进行更新。

更为重要的是zookeeper 与生俱来的容错容灾能力(比如leader选举),可以确保服务注册表的高可用性。

使用 zookeeper 作为注册中心时,客户端订阅服务时会向 zookeeper 注册自身;主要是方便对调用方进行统计、管理。但订阅时是否注册 client 不是必要行为,和不同的注册中心实现有关,例如使用 consul 时便没有注册。

熟悉springcloud的应该知道,springcloud的注册中心默认使用的是Eureka,这篇文章就是将这两个注册中心的区别的:京东面试官让你谈谈 zookeeper 和 eureka 哪个更好使?

zookeeper配置管理

这个不在赘述,看网上的解决方案,很多使用zookeeper作为配置中心的,做个配置管理还是很简单的事。

参考文章:

https://dbaplus.cn/news-141-1875-1.html

 

原文地址:https://www.cnblogs.com/gunduzi/p/12382201.html

时间: 2024-10-12 19:35:10

java基础之----zookeeper的相关文章

有java基础,如何学习大数据,该怎么开始?

因为学大数据前期的基础课程就是java和linux.既然你有java基础就省去了学习者部分课程的基础,而且上手会容易很多! 再说说还需要学习哪些大数据技术,可以按我写的顺序学下去. 我还是要推荐下我自己创建的大数据资料分享群142973723,这是大数据学习交流的地方,不管你是小白还是大牛,小编都欢迎,不定期分享干货,包括我整理的一份适合零基础学习大数据资料和入门教程. Hadoop 这是现在流行的大数据处理平台几乎已经成为大数据的代名词,所以这个是必学的.Hadoop里面包括几个组件HDFS.

Java基础面试知识点总结

本文主要是我最近复习Java基础原理过程中写的Java基础学习总结.Java的知识点其实非常多,并且有些知识点比较难以理解,有时候我们自以为理解了某些内容,其实可能只是停留在表面上,没有理解其底层实现原理. 纸上得来终觉浅,绝知此事要躬行.笔者之前对每部分的内容 对做了比较深入的学习以及代码实现,基本上比较全面地讲述了每一个Java基础知识点,当然可能有些遗漏和错误,还请读者指正. Java基础学习总结 每部分内容会重点写一些常见知识点,方便复习和记忆,但是并不是全部内容,详细的内容请参见具体的

Java基础知识强化(用于自我巩固)以及审查

1. Java 和 JDK 的关系 JDK(Java Development Kit)Java 开发工具包,它包括:编译器.Java 运行环境(JRE,Java Runtime Environment).JVM(Java 虚拟机)监控和诊断工具等 Java 则表示一种开发语言. 2. Java 程序是怎么执行的? 日常工作中使用的开发工具(IntelliJ IDEA 或 Eclipse 等)可以很方便的调试程序,或者是通过打包工具把项目打包成 jar 包或者 war 包,放入 Tomcat 等

-Java基础-Java介绍

声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权:凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记. java的介绍 1.1java简介 Java是一种可以撰写跨平台应用程序的面向对象的程序设计语言. 它最初被命名为Oak,目标设定在家用电器等小型系统的编程语言,来解决诸如电视机.电话.闹钟.烤面包机等家用电器的控制和通讯问题.由于这些智能化家电的市场需求没有预期的高,Sun放弃了该项计划.就在Oak几近失败之时,随着互联网的发展,Sun看到了Oak在计算机

第3篇-JAVA基础

第3篇-JAVA基础 每篇一句 :目标是给梦想一个期限,行动与坚持就是实现梦想的过程 初学心得: 遇到困难或问题,它不是休止符,而是引向你如何解决问题的标识 (笔者:JEEP/711)[JAVA笔记 | 时间:2017-03-26| JAVA基础 Ⅱ] 上篇回顾 上篇文章中我们学习了JAVA底层的运行机制与深入剖析以及解释其中JAVA基础代码的含义 本篇文章将JAVA基础Ⅱ全面剖析解释,因为JAVA基础非常重要,务必要牢记知识点!!! 1.JAVA基础语法格式 JAVA采用unicode编码 1

Java基础学习第五天——方法与数组

文档版本 开发工具 测试平台 工程名字 日期 作者 备注 V1.0 2016.02.24 lutianfei none 第三章Java基础语法 方法 方法就是完成特定功能的代码块,即函数. 格式: 修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2-) { 函数体; return 返回值; } 详细解释: 修饰符,目前就用public static,后详解. 返回值类型:就是功能结果的数据类型. 方法名:符合命名规则即可,方便我们的调用. 参数: 实际参数:就是实际参与运算的.

2.35 Java基础总结①抽象②接口③设计抽象类和接口的原则④接口和抽象类的区别

java基础总结①抽象②接口③设计抽象类和接口的原则④接口和抽象类的区别 一.抽象 abstract作用:不能产生对象,充当父类,强制子类正确实现重写方法和类相比仅有的改变是不能产生对象,其他的都有,包括构造.属性等等任何一个类只要有一个抽象的方法就成了抽象类 抽象方法 public abstract A();①方法是抽象的,这个类也是抽象的:②子类必须重写抽象方法,除非子类也是抽象类 抽象类可以没有抽象方法,但一般不这么设计 二.接口 interface 接口也是Java的一种引用数据类型(J

java基础 计算今天距本月最后一天还剩多少天

Calendar  c = new GregorianCalendar();   //GregorianCalendar 是Calendar的一个具体子类,提供了世界上大多数国家/地区使用的标准日历系统. GredorianCalendar 是一种混合日历,可由调用者通过调用setGregorianChange()来更改起始日期. Calendar c = new  Calendar.getInstance(TimeZone.getTimeZone("GMT+08:OO"));  //

Java基础语法

Java的基础语法中包含字符集.标识符和关键字.变量和常量.语句.注释.运算符和表达式这些基本要素. 一.关键字 编程语言都有一些保留的单词,用于定义该语言,这些单词对于编译器有特殊含义,不能作为标识符使用: Java中的true.false.null这三个保留字,不能作为标识符使用,对于编译器有特殊含义: main是一个用于描述Java程序开始方法的特殊名称,它不是一个关键字: abstract 抽象 boolean 逻辑运算: 布尔 break 打破: 断开 byte 字节: case 例,