Zookeeper基础原理&应用场景详解
简单了解Zookeeper
Tips: 如果之前对Zookeeper不了解的话,这里大概留个印象就好了
Zookeeper是一个分布式协调服务,可以用于元数据管理、分布式锁、分布式协调、发布订阅、服务命名等等。
例如,Kafka中就是用Zookeeper来保存其集群中的相关元数据,例如Broker、Topic以及Partition等等。同时,基于Zookeeper的Watch监听机制,还可以用其实现发布、订阅的功能。
在平常的常规业务使用场景下,我们几乎只会使用到分布式锁这一个用途。
Zookeeper内部运行机制
Zookeeper的底层存储原理,有点类似于Linux中的文件系统。Zookeeper中的文件系统中的每个文件都是节点(Znode)。根据文件之间的层级关系,Zookeeper内部就会形成这个这样一个文件树。

在Linux中,文件(节点)其实是分类型的,例如分为文件、目录。在Zookeeper中同理,Znode同样的有类型。在Zookeeper中,所有的节点类型如下:
持久节点(Persistent) 持久顺序节点(Persistent Sequential) 临时节点(Ephemeral) 临时顺序节点(Ephemeral Sequential)
所谓持久节点,就和我们自己在电脑上新建一个文件一样,除非你主动删除,否则一直存在。
而持久顺序节点除了继承了持久节点的特性之外,还会为其下创建的子节点保证其先后顺序,并且会自动地为节点加上10位自增序列号作为节点名,以此来保证节点名的唯一性。这一点上图中的subfiles已经给出了示例。
而临时节点,其生命周期和client的连接是否活跃相关,如果client一旦断开连接,该节点(可以理解为文件)就都会被删除,并且临时节点无法创建子节点;
PS:这里的断开连接其实不是我们直觉上理解的断开连接,Zookeeper有其Session机制,当某个client的Session过期之后,会将对应的client创建的节点全部删除
Zookeeper的节点创建方式
接下来我们来分别看看几种节点的创建方式,给出几个简单的示例。
创建持久节点
create /node_name SH的全栈笔记

这里需要注意的是,命令中所有的节点名称必须要以/开头,否则会创建失败,因为在Zookeeper中是不能使用相对路径,必须要使用绝对路径。

创建持久顺序节点
create -s /node_name SH的全栈笔记

可以看到,Zookeeper为key自动的加上了10位的自增后缀。
创建临时节点
create -e /test SH的全栈笔记

创建临时顺序节点
create -e -s /node_name SH的全栈笔记

Zookeeper的用途
我们通过一些具体的例子,来了解Zookeeper的详细用途,它不仅仅只是被当作分布式锁使用。
元数据管理
我们都知道,Kafka在运行时会依赖一个Zookeeper的集群。Kafka通过Zookeeper来管理集群的相关元数据,并通过Zookeeper进行Leader选举。
Tips: 但是即将发布的Kafka 2.8版本中,Zookeeper已经不是一个必需的组件了。这块我暂时还没有时间去细看,不过我估计可能会跟RocketMQ中处理的方式差不多,将其集群的元数据放到Kafka本身来处理。
分布式锁
基于Zookeeper的分布式锁其实流程很简单。首先我们需要知道加分布式锁的本质是什么?
答案是创建临时顺序节点
当某个客户端加锁成功之后,实际上则是成功的在Zookeeper上创建了临时顺序节点。我们知道,分布式锁能够使同一时间只能有一个能够访问某种资源。那这就必然会涉及到分布式锁的竞争,那问题来了,当前这个客户端是如何感知抢到了锁呢?
其实在客户端侧会有一定的逻辑,假设加锁的key为/locks/modify_users。
首先,客户端会发起加锁请求,然后会在Zookeeper上创建持久节点locks,然后会在该节点下创建临时顺序节点。临时顺序节点的创建示例,如下图所示。

当客户端成功创建了节点之后,还会获取其同级的所有节点。也就是上图中的所有modify_users000000000x的节点。
此时客户端会根据10位的自增序号去判断,当前自己创建的节点是否是所有的节点中最小的那个,如果是最小的则自己获取到了分布式锁。
你可能会问,那如果我不是最小的怎么办呢?而且我的节点都已经创建了。如果不是最小的,说明当前客户端并没有抢到锁。按照我们的认知,如果没有竞争到分布式锁,则会等待。等待的底层都做了什么?我们用实际例子来捋一遍。
假设Zookeeper中已经有了如下的节点。

例如当前客户端是B创建的节点是modify_users0000000002,那么很明显B没有抢到锁,因为已经有比它还要小的由客户端A创建的节点modify_users0000000001。
此时客户端B会对节点modify_users0000000001注册一个监听器,对于该节点的任意更新都将触发对应的操作。
当其被删除之后,就会唤醒客户端B的线程,此时客户端B会再次进行判断自己是否是序号最小的一个节点,此时modify_users0000000002明显是最小的节点,故客户端B加锁成功。
为了让你更加直观的了解这个过程,我把流程浓缩成了下面这幅流程图。

分布式协调
我们都知道,在很多场景下要保证一致性都会采用经典的2PC(两阶段提交),例如MySQL中Redo Log和Binlog提交的数据一致性保障就是采用的2PC,详情可以看基于Redo Log和Undo Log的MySQL崩溃恢复流程。
在2PC中存在两种角色,分别是参与者(Participant)和协调者(Coordinator),协调者负责统一的调度所有分布式节点的执行逻辑。具体协调啥呢?举个例子。
例如在2PC的Commit阶段,两个参与者A、B,A的commit操作成功了,但不幸的是B失败了。此时协调者就需要向A发送Rollback操作。Zookeeper大概就是这样一个角色。
发布订阅
由于Zookeeper自带了监听器(Watch)的功能,所以发布订阅也顺理成章的成为了Zookeeper的应用之一。例如在某个配置节点上注册了监听器,那么该配置一旦发布变更,对应的服务就能实时的感知到配置更改,从而达到配置的动态更新的目的。
给个简单的Watch使用示例。

命名服务
用大白话来说,命名服务主要有两种。
单纯的利用Zookeeper的文件系统特性,存储结构化的文件 利用文件特性和顺序节点的特性,来生成全局的唯一标识
前者可以用于在系统之间共享某种业务上的特定资源,后者则可以用于实现分布式锁。
好了以上就是本篇博客的全部内容了,欢迎微信搜索关注【SH的全栈笔记】,回复【队列】获取MQ学习资料,包含基础概念解析和RocketMQ详细的源码解析,持续更新中。
如果你觉得这篇文章对你有帮助,还麻烦点个赞,关个注,分个享,留个言。

Zookeeper基础原理&应用场景详解的更多相关文章
- 基础 | batchnorm原理及代码详解
https://blog.csdn.net/qq_25737169/article/details/79048516 https://www.cnblogs.com/bonelee/p/8528722 ...
- Java基础-面向接口编程-JDBC详解
Java基础-面向接口编程-JDBC详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.JDBC概念和数据库驱动程序 JDBC(Java Data Base Connectiv ...
- Go语言备忘录:反射的原理与使用详解
目录: 预备知识 reflect.Typeof.reflect.ValueOf Value.Type 动态调用 通过反射可以修改原对象 实现类似“泛型”的功能 1.预备知识: Go的变量都是静态类 ...
- [五]基础数据类型之Short详解
Short 基本数据类型short 的包装类 Short 类型的对象包含一个 short 类型的字段 原文地址:[五]基础数据类型之Short详解 属性简介 值为 215-1 ...
- “全栈2019”Java第一百一十三章:什么是回调?回调应用场景详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- Go语言备忘录(2):反射的原理与使用详解
本文内容是本人对Go语言的反射原理与使用的备忘录,记录了关键的相关知识点,以供翻查. 文中如有错误的地方请大家指出,以免误导!转摘本文也请注明出处:Go语言备忘录(2):反射的原理与使用详解,多谢! ...
- zookeeper的安装(图文详解。。。来点击哦!)
zookeeper的安装(图文详解...来点击哦!) 一.服务器的配置 三台服务器: 192.168.83.133 sunshine 192.168.83.134 sunshineMin 19 ...
- Qt零基础教程(四) QWidget详解篇
在博客园里面转载我自己写的关于Qt的基础教程,没次写一篇我会在这里更新一下目录: Qt零基础教程(四) QWidget详解(1):创建一个窗口 Qt零基础教程(四) QWidget详解(2):QWid ...
- Qt零基础教程(四)QWidget详解(3):QWidget的几何结构
Qt零基础教程(四) QWidget详解(3):QWidget的几何结构 这篇文章里面分析了QWidget中常用的几种几何结构 下图是Qt提供的分析QWidget几何结构的一幅图,在帮助的 Wind ...
随机推荐
- Redis 对过期数据的处理
Redis 对过期数据的处理 在 redis 中,对于已经过期的数据,Redis 采用两种策略来处理这些数据,分别是惰性删除和定期删除 惰性删除 惰性删除不会去主动删除数据,而是在访问数据的时候,再检 ...
- 谈一下HashMap的底层原理是什么?
底层原理:Map + 无序 + 键唯一 + 哈希表 (数组+Entry)+ 存取值 1.HashMap是Map接口的实现类.实现HashMap对数据的操作,允许有一个null键,多个null值. Co ...
- 代码小知识之UUID
1.生成UUID(UUID保证对在同一时空中的所有机器都是唯一的,UUID的唯一缺陷在于生成的结果串会比较长.UUID 来作为数据库数据表主键是非常不错的选择,保证每次生成的UUID 是唯一的) UU ...
- 面试系列二:精选大数据面试真题JVM专项-附答案详细解析
公众号(五分钟学大数据)已推出大数据面试系列文章-五分钟小面试,此系列文章将会深入研究各大厂笔面试真题,并根据笔面试题扩展相关的知识点,助力大家都能够成功入职大厂! 大数据笔面试系列文章分为两种类型: ...
- go 报错 import cycle not allowed
运行时报错,import cycle not allowed : 查了goole大概知道了原因,还是导包类的问题,我检察了一下我的代码库,发现我昨天划分几个工具文件,里面的两个文件相互引用,就导致报i ...
- springboot整合jsp,完成公交车站路线图
转: springboot整合jsp,完成公交车站路线图 点赞再看,养成习惯 开发环境: jdk 8 intellij idea tomcat 8 mysql 5.7 maven 3.6 所用技术: ...
- c++中深层复制(浅层复制运行错误)成功运行-----sample
下面随笔给出c++中深层复制(浅层复制运行错误)成功运行------sample. 浅层复制与深层复制 浅层复制 实现对象间数据元素的一一对应复制. 深层复制 当被复制的对象数据成员是指针类型时,不是 ...
- mysql查询较长的执行进程及创建权限账号
A:对于死锁,进程的操作 1.查找当前活跃事务 SELECT * from information_schema.INNODB_TRX 根据trx_started等判断事务是否异常锁定 2.杀死线程 ...
- SpringDataJPA 入门
前言 1. 三者的区别与联系 JPA:本身是一种ORM规范,不是ORM框架.由各大ORM框架提供实现. Hibernate是一个完整的ORM框架,常规CRUD我们不需要写一句SQL;框架比较重,学习成 ...
- Spring 中的事务
前言: 之前总结了事务以及数据库中事务相关的知识点,Spring 对于事务做了相应的封装,便于业务开发中使用事务. 项目中使用Spring中的事务首先时基于Mysql数据库中InnoDB 引擎的,如果 ...