如果你还不知道Apache Zookeeper?你凭什么拿大厂Offer!!
很多同学或多或少都用到了Zookeeper,并知道它能实现两个功能
- 配置中心,实现表分片规则的统一配置管理
- 注册中心,实现sharding-proxy节点的服务地址注册
那么Zookeeper到底是什么?以及为什么能实现这样的功能?接下来我们就来了解一下Zookeeper。
Zookeeper的前世今生
Apache ZooKeeper是一个高可靠的分布式协调中间件。它是Google Chubby的一个开源实现,那么它主要是解决什么问题的呢?那就得先了解Google Chubby
Google Chubby是谷歌的一个用来解决分布式一致性问题的组件,同时,也是粗粒度的分布式锁服务。
分布式一致性问题
什么是分布式一致性问题呢?简单来说,就是在一个分布式系统中,有多个节点,每个节点都会提出一个请求,但是在所有节点中只能确定一个请求被通过。而这个通过是需要所有节点达成一致的结果,所以所谓的一致性就是在提出的所有请求中能够选出最终一个确定请求。并且这个请求选出来以后,所有的节点都要知道。
这个就是典型的拜占庭将军问题
拜占庭将军问题说的是:拜占庭帝国军队的将军们必须通过投票达成一致来决定是否对某一个国家发起进攻。但是这些将军在地里位置上是分开的,并且在将军中存在叛徒。叛徒可以通过任意行动来达到自己的目标:
欺骗某些将军采取进攻行动
促使一个不是所有将军都统一的决定,比如将军们本意是不希望进攻,但是叛徒可以促成进攻行动
迷惑将军使得他们无法做出决定
如果叛徒达到了任意一个目标,那么这次行动必然失败。只有完全达成一致那么这次进攻才可能胜利
拜占庭问题的本质是,由于网络通信存在不可靠的问题,也就是可能存在消息丢失,或者网络延迟。如何在这样的背景下对某一个请求达成一致。
为了解决这个问题,很多人提出了各种协议,比如大名鼎鼎的Paxos; 也就是说在不可信的网络环境中,按照paxos这个协议就能够针对某个提议达成一致。
所以:分布式一致性的本质,就是在分布式系统中,多个节点就某一个提议如何达成一致
这个和Google Chubby有什么关系呢
在Google有一个GFS(google file system),他们有一个需求就是要从多个gfs server中选出一个master server。这个就是典型的一致性问题,5个分布在不同节点的server,需要确定一个master server,而他们要达成的一致性目标是:确定某一个节点为master,并且所有节点要同意。
而GFS就是使用chubby来解决这个问题的。
实现原理是:所有的server通过Chubby提供的通信协议到Chubby server上创建同一个文件,当然,最终只有一个server能够获准创建这个文件,这个server就成为了master,它会在这个文件中写入自己 的地址,这样其它的server通过读取这个文件就能知道被选出的master的地址。
图9-3
分布式锁服务
从另外一个层面来看,Chubby提供了一种粗粒度的分布式锁服务,chubby是通过创建文件的形式来提供锁的功能,server向chubby中创建文件其实就表示加锁操作,创建文件成功表示抢占到了锁。
由于Chubby没有开源,所以雅虎公司基于chubby的思想,开发了一个类似的分布式协调组件Zookeeper,后来捐赠给了Apache。
所以,大家一定要了解,zookeeper并不是作为注册中心而设计,他是作为分布式锁的一种设计,而注册中心只是他能够实现的一种功能而已。
Zookeeper的安装和部署
安装
zookeeper有两种运行模式:集群模式和单击模式。
下载zookeeper安装包:https://mirrors.bfsu.edu.cn/apache/zookeeper/zookeeper-3.6.3/apache-zookeeper-3.6.3-bin.tar.gz
下载完成,通过tar -zxvf解压
常用命令
- 启动ZK服务:
bin/zkServer.sh start
- 查看ZK服务状态:
bin/zkServer.sh status
- 停止ZK服务:
bin/zkServer.sh stop
- 重启ZK服务:
bin/zkServer.sh restart
- 连接服务器
zkCli.sh -timeout 0 -r -server ip:port
单机环境安装
一般情况下,在开发测试环境,没有这么多资源的情况下,而且也不需要特别好的稳定性的前提下,我们可以使用单机部署;
初次使用zookeeper,需要将conf目录下的zoo_sample.cfg文件copy一份重命名为zoo.cfg
修改dataDir目录,dataDir表示日志文件存放的路径(关于zoo.cfg的其他配置信息后面会讲)
集群环境安装(后续再讲)
在zookeeper集群中,各个节点总共有三种角色,分别是:leader,follower,observer
集群模式我们采用模拟3台机器来搭建zookeeper集群。分别复制安装包到三台机器上并解压,同时copy一份zoo.cfg。
修改配置文件
- 修改端口
- server.1=IP1:2888:3888 【2888:访问zookeeper的端口;3888:重新选举leader的端口】
- server.2=IP2.2888:3888
- server.3=IP3.2888:2888
server.A=B:C:D:其 中
- A 是一个数字,表示这个是第几号服务器;
- B 是这个服务器的 ip地址;
- C 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;
- D 表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口。如果是伪集群的配置方式,由于 B 都是一样,所以不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同的端口号。
- 在集群模式下,集群中每台机器都需要感知到整个集群是由哪几台机器组成的,在配置文件中,按照格式server.id=host:port:port,每一行代表一个机器配置。id: 指的是server ID,用来标识该机器在集群中的机器序号
新建datadir目录,设置myid
在每台zookeeper机器上,我们都需要在数据目录(dataDir)下创建一个myid文件,该文件只有一行内容,对应每台机器的Server ID数字;比如server.1的myid文件内容就是1。【必须确保每个服务器的myid文件中的数字不同,并且和自己所在机器的zoo.cfg中server.id的id值一致,id的范围是1~255】
启动zookeeper
Zookeeper的数据模型
如果我们把zookeeper当成是一个内存数据库的话,那么crud就是对zookeeper内存数据库进行一个数据的增删改查操作,那zookeeper的数据结构是什么样的呢?如图9-4所示,zookeeper的视图结构和标准的文件系统非常类似,每一个节点称之为ZNode, 是zookeeper的最小单元。每个znode上都可以保存数据以及挂载子节点,构成一个层次化的树形结构
图9-4
节点类型
Zookeeper中包含4种类型的节点,分别说明如下。
持久化节点
持久化节点可以细分为两种节点,分别是:
PERSISTENT:持久化,不会随客户端的断开而自动删除,默认类型,如图9-5所示
图9-5
PERSISTENT_SEQUENTIAL:带序号的持久化,znode的名字将被附加一个单调递增的数字,如图9-6所示
图9-5
临时节点
EPHEMERAL:临时节点,当客户端断开时自动删除,如图9-6所示,如果该Client创建了/Server1和/Server2这两个节点,当Client的session断开后,这两个节点会被Zookeeper自动删除。
图9-6
EPHEMERAL_SEQUENTIAL:带序号的临时节点,znode的名字将被附加一个单调递增的数字,如图9-7所示
注意,临时节点不能存在子节点
图9-7
Container节点
CONTAINER:container节点是一个特殊用途的节点,它是为Leader、Lock等操作而设计的节点类型,它的作用是: 当容器节点的最后一个子节点被删除后,容器节点将会被标注并且在一段时间后删除。
由于容器节点存在这个特性,所以当我们在容器节点下创建一个子节点时,需要捕获KeeperException.NoNodeException异常,如果捕获到这个异常,就需要重新创建容器节点。
TTL节点
如果某个节点设置为TTL节点类型,那么这个节点在指定TTL时间(单位为毫秒)段内没有修改并且没有子节点时,该节点会在一段时间后被删除。
- PERSISTENT_WITH_TTL:zookeeper的扩展类型,如果znode在给定的TTL内没有被修改,它将在没有子节点时被删除。要想使用该类型,必须在zookeeper的bin/zkService.sh中的启动zookeeper的java环境中设置环境变量zookeeper.extendedTypesEnabled=true(具体做法在下边),否则KeeperErrorCode = Unimplemented for /**。
设置zookeeper.extendedTypesEnabled=true
打开zookeeper bin/zkServer.sh(win是zkService.cmd),修改启动zookeeper的命令,加上-Dzookeeper.extendedTypesEnabled=true,也就是设置java的一个环境变量。
nohup "$JAVA" $ZOO_DATADIR_AUTOCREATE "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" \
"-Dzookeeper.log.file=${ZOO_LOG_FILE}" "-Dzookeeper.extendedTypesEnabled=true" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
-XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError='kill -9 %p' \
-cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &
- PERSISTENT_SEQUENTIAL_WITH_TTL:同上,是不过是带序号的
Zookeeper的操作命令
创建节点
create [-s] [-e] [-c] [-t ttl] path [data] [acl]
[-s]:sequential 序列化的,即可以重复创建,在路径后面加上序列号
[-e]:ephemeral 临时的,断开连接后自动失效
[-c] :表示container node(容器节点),
[-t ttl]:表示TTL Nodes(带超时时间的节点)
[acl]:是针对这个节点创建一个权限的,如果创建权限了,则拥有权限的才可以访问
删除节点
删除节点,-v表示版本号,实现乐观锁机制
delete [-v version] path
更新节点
给节点赋值 -s返回节点状态
set [-s] [-v version] path data
查询节点信息
获取指定节点的值
get [-s] [-w] path
节点状态信息stat
节点除了存储数据内容以外,还存储了数据节点本身的一些状态信息,通过get命令可以获得状态信息的详细内容,如图9-8所示。
图9-8
版本-保证分布式数据原子性
zookeeper为数据节点引入了版本的概念,每个数据节点都有三类版本信息,对数据节点任何更新操作都会引起版本号的变化
图9-9
版本有点和我们经常使用的乐观锁类似。这里有两个概念说一下,一个是乐观锁,一个是悲观锁
悲观锁:是数据库中一种非常典型且非常严格的并发控制策略。假如一个事务A正在对数据进行处理,那么在整个处理过程中,都会将数据处于锁定状态,在这期间其他事务无法对数据进行更新操作。
乐观锁:乐观锁和悲观锁正好想法,它假定多个事务在处理过程中不会彼此影响,因此在事务处理过程中不需要进行加锁处理,如果多个事务对同一数据做更改,那么在更新请求提交之前,每个事务都会首先检查当前事务读取数据后,是否有其他事务对数据进行了修改。如果有修改,则回滚事务
再回到zookeeper,version属性就是用来实现乐观锁机制的“写入校验”
Watcher监听节点事件变化
zookeeper提供了分布式数据的发布/订阅功能,zookeeper允许客户端向服务端注册一个watcher监听,当服务端的一些指定事件触发了watcher,那么服务端就会向客户端发送一个事件通知。zookeeper提供以下几种命令来对指定节点设置监听。
- get [-s] [-w] path:监听指定path节点的修改和删除事件。同样该事件也是一次性触发。
get -w /node
# 在其他窗口执行下面命令,会触发相关事件
set /node 123
delete /node
- ls [-s] [-w] [-R] path : 监控指定path的子节点的添加和删除事件。
ls -w /node
# 在其他窗口执行下面命令,会触发相关事件
create /node/node1
delete /node/node1
注意: 当前命令设置的监听是一次性的,就是说一旦触发了一次事件监听,后续的事件都不会响应。当然我们可以通过重复订阅来解决
stat [-w] path:作用和get完全相同。
addWatch [-m mode] path # optional mode is one of [PERSISTENT, PERSISTENT_RECURSIVE] - default is PERSISTENT_RECURSIVE
addWatch的作用是针对指定节点添加事件监听,支持两种模式
- PERSISTENT,持久化订阅,针对当前节点的修改和删除事件,以及当前节点的子节点的删除和新增事件。
- PERSISTENT_RECURSIVE,持久化递归订阅,在PERSISTENT的基础上,增加了子节点修改的事件触发,以及子节点的子节点的数据变化都会触发相关事件(满足递归订阅特性)
Session会话机制
如图9-10所示,表示Zookeeper的session会话状态机制。
- 首先,客户端向Zookeeper Server发起连接请求,此时状态为CONNECTING
- 当连接建立好之后,Session状态转化为CONNECTED,此时可以进行数据的IO操作。
- 如果Client和Server的连接出现丢失,则Client又会变成CONNECTING状态
- 如果会话过期或者主动关闭连接时,此时连接状态为CLOSE
- 如果是身份验证失败,直接结束
图9-10
Zookeeper的应用场景
配置中心
程序总是需要配置的,如果程序分散部署在多台机器上,要逐个改变配置就变得困难。好吧,现在把这些配置全部放到zookeeper上去,保存在 Zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中就好。
图9-11
服务注册中心
如图9-12所示,Zookeeper可以用来实现服务注册中心,简单来说就是管理目标服务端的地址,客户端调用目标服务端之前,从zookeeper上获得地址进行访问。
图9-12
分布式锁
利用临时有序节点实现分布式锁,如图9-13所示,每个App节点要抢占分布式锁,可以先去Zookeeper上创建一个临时有序节点,节点最小的表示该客户端获得了锁,其他没获得锁的客户端先等待,直到获得锁的客户端删除了该节点或者断开会话连接。
图9-13
关注[跟着Mic学架构]公众号,获取更多精品原创
如果你还不知道Apache Zookeeper?你凭什么拿大厂Offer!!的更多相关文章
- 如果你还不知道如何控制springboot中bean的加载顺序,那你一定要看此篇
1.为什么需要控制加载顺序 springboot遵从约定大于配置的原则,极大程度的解决了配置繁琐的问题.在此基础上,又提供了spi机制,用spring.factories可以完成一个小组件的自动装配功 ...
- 2.动手实操Apache ZooKeeper
Tips 做一个终身学习的人! 日拱一卒,功不唐捐. 在本节中,我们将讲解如何下载并安装Apache ZooKeeper,以便我们可以直接开始使用ZooKeeper. 本部分旨在通过提供详细的安装和使 ...
- org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss for /eclipse20171118
1:如果有一天,你有幸看到了这个错误,也许你像我一样low,因为此时,你已经准备开发Zookeeper程序了,却还没有把Zookeeper的服务启动起来. org.apache.zookeeper.K ...
- 【Apache ZooKeeper】命令行zkCli.sh使用指南
ZooKeeper命令行 原文 http://blog.csdn.net/ganglia/article/details/11606807 ZooKeeper客户端 ...
- 3.Apache ZooKeeper数据模型
1. ZooKeeper自下向上的服务视图 Apache ZooKeeper是分布式应用程序的协调服务. 它旨在解决分布式应用程序中与组件协调相关的棘手问题. 它通过暴露一个简单而强大的接口来实现这一 ...
- Apache ZooKeeper 服务启动源码解释
转载:https://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper-code/ 本文首先讲解了 Apache ZooKeeper 服 ...
- 在 Linux 多节点安装配置 Apache Zookeeper 分布式集群
规划: 三台物理服务器就形成了(法定人数).对于高可用性集群,您可以使用高于3的任何奇数.例如,如果设置5台服务器,则集群可以处理两个故障节点等. 物理服务器需要开启的端口 2888 , 3888 和 ...
- Apache ZooKeeper在Kafka中的角色 - 监控和配置
1.目标 今天,我们将看到Zookeeper在Kafka中的角色.本文包含Kafka中需要ZooKeeper的原因.我们可以说,ZooKeeper是Apache Kafka不可分割的一部分.在了解Zo ...
- JDK15就要来了,你却还不知道JDK8的新特性!
微信搜「烟雨星空」,白嫖更多好文. 现在 Oracle 官方每隔半年就会出一个 JDK 新版本.按时间来算的话,这个月就要出 JDK15 了.然而,大部分公司还是在使用 JDK7 和 8 . 之前去我 ...
随机推荐
- idea配置tomcat及中文乱码解决
放在前面:不要使用tomcat10,访问自己的页面会报404错误,目前无解,在这个坑爬了一下午,最终换了tomcat 9才解决.所以我选择了tomcat 9 + idea 2021.2版本 配置步骤: ...
- Tars | 第5篇 基于TarsGo Subset路由规则的Java JDK实现方式(上)
目录 前言 1. 修改.tars协议文件 1.1 Go语言修改部分 1.2 修改地方的逻辑 1.3 通过协议文件自动生成代码 2. [核心]增添Subset核心功能 2.1 Go语言修改部分 2.2 ...
- 从零开始学习SQL SERVER(1)--- 了解SQL
SQL是什么 SQL (发音为 sequal [' sikwəl ' ]) SQL指 Structured Query Language 结构化查询语言,是用于访问和处理数据库的标准的计算机语言. ...
- 关于golang结束了编程风格中对于左大括号要不要换行之争.
golang规定了左大括号必须紧跟在语句后面,这样一下子就结束了各种代码风格之争. 其实golang是继承了早期的C语言,为了节省空间,才将左括号放到代码后面. 哪种编码风格是你的"菜&qu ...
- k8s标签label
1.给节点设置标签 一遍pod部署选择 kubectl label node 节点名 disktype=ssd kubectl label node master1 disktype=ssd 效果 [ ...
- C++快速读入
使用C++的标准cin进行读入速度比较慢,尤其是在大数据的情况下,所以我们需要使用一种方法,按照字符读入,最后再"组装"成整数.由于字符读入比数字要快,所以这样做可以提高读入速度. ...
- 动态查看及加载PHP扩展
在编译并完成 php.ini 的配置之后,我们就成功的安装了一个 PHP 的扩展.不过, PHP 也为我们提供了两个在动态运行期间可以查看扩展状态以及加载未在 php.ini 中进行配置的扩展的函数. ...
- PHP 流行的框架
Aura Laravel Symphony Yii Zend php components Packagist 最好的组件: Awesome PHP https://www.yiiframework. ...
- Linux服务器时间同步配置
Linux服务器时间同步配置 以CentOS7 做时间服务器,其他服务器(Centos 6.RHEL7)同步该服务器时间 RHEL 7.CentOS 7 默认的网络时间协议 为Chrony 本教程 ...
- c++ 的学习笔记 第一集cim cout
1. 你要用这个东西,所以得有包含它得头文件,就像java 你要用某个模块,你得包含这个模块 模块化??单片机里面学的模块化(可以在vs里面实现) 2. 当我把注册表regedit 程序删除之后成功了 ...