月泉的博客

ZooKeeper来初步了解一下?

月泉 ZooKeeper分布式

不多哔哔大纲先行

  • ZooKeeper是啥
  • ZooKeeper如何使用
  • ZooKeeper分布式搭建
  • ZooKeeper的应用场景

ZooKeeper是啥

ZooKeeper是一种分布式协调框架,最早是由雅虎的一个研究小组所开发,最早是用来解决分布式单点问题,因为技术氛围很多项目都是用动物命名,正好ZooKeeper是用于协调分布式应用因此得名“动物园管理员”(译过来是这样啊~),那么什么是分布式单点问题,那么就要举一个简单的架构演技进例子来说明了(怕有钻牛角尖的,所以这里的架构演进是为了写这篇文章,笔者自己根据目前的知识想出来的演进,所以我的地盘听我的,不接受任何牛角尖)。

首先从最原始的最常见的单体应用。 这个无需解释吧

随着并发需求越来越大,一个顶不住了,然后按照这个架构再扩展一下

每次拓展又他喵的要多开一个服务器然后在部署一套商城,而且很多系统都能用到类似的服务,难以达到复用的效果,而且扩展起来比较耗费财力,不能针对某一个点来进行性能的扩展,容易造成某些方面的浪费,例如 订单是一个高并发使用,而钱包是一个低并发,那么讲道理我只想针对并发高的这个服务进行性能的扩展,于是我们先将它拆成服务

服务拆分好了以后我们再来扩展一哈

OK,演进就先到这里,舞台搭建好了,我们来发现这其中的问题

首先无论是水平扩展还是垂直扩展,有些许问题(以水平扩展来说,垂直差不多意会到了就行)这里挑几个针对的来说

  • 共享资源
  • 服务注册
  • 负载均衡

其实这里就已经把应用场景说了,但这里只描述下问题,在应用场景的那一个小节再继续刻画,总的来说就是在分布式环境中的协调问题,例如共享资源,我几十几百个订单服务要同时使用一个共享资源,例如配置文件中的一些开关,通过修改配置文件的一些开关配置就能让我几百几千个服务同时打开,通过服务的注册来实现服务的统一地址管理、服务的上下线等,说到这里应该要对ZooKeeper分布式协调有点感觉了(如果还不能理解可以加微信共同探讨一下吧),那我就走进ZooKeeper了

先介绍一下ZooKeeper的存储结构,它是以树形结构来存储但每个Node又都是一个Key-Value,说起来太抽象,画个图

虚线连接的都是当前节点的value,实线连接之处便是其子节点了,这些子节点也有一个名字那便是ZNode,这下对ZooKeeper是个什么以及存储结构都有一个基本的了解了,接着进入下一个小节

ZooKeeper如何使用?

首先说一下我的环境 * CentOS7 * OpenJDK8

这便是我依赖的环境了 自行去Apache ZooKeeper下载,然后解压,进入目录

首先进入conf目录

ZooKeeper默认会读取zoo.cfg文件,默认是没有的,但是有一个自带的zoo_sample.cfg文件,可以使用这个 cp zoo_sample.cfg zoo.cfg,这里面写了什么我们暂时不关心,等会细讲,然后回退目录接着进入bin目录下

可以看到目录下有如下几个文件,首先启动ZooKeeper

./zkServer.sh start

接着使用提供的客户端,连接它

./zkCli.sh

我们先来看看,默认有哪些数据

ls /

可以看到默认只有一个zookeeper节点,接着我们来创建一个节点

create /a a 
ls /

接着就可以看到我们所创建的节点,接着在继续给它创建一个子节点

create /a/aa aa
ls /a

接着我们来创建一个临时节点,什么是临时节点呢,为什么叫临时有什么特殊之处呢?只需要记住2点,临时节点只在会话中有效,当连接会话结束后在一个心跳周期后会将它删除掉,还有一个需要注意的地方就是临时节点是不可以有子节点的

create -e /temp temp
ls /

接着我们ctrl + c结束客户端控制台,等待个几秒钟在继续进行连接

./zkCli.sh
ls /

接着临时节点就已经木有了,还有一个节点类型,就是有序节点,有序节点不需要你给它指定它的序列编号,会自动生成,例如

create -s /seq seq01
ls /

你们的应该会是从0开始为什么我的是从4开始呢?因为我用的Docker跑的CentOS挂载了虚拟卷QAQ所以之前的记录也还是在的,无伤大雅,我们继续,接着给它创建一个子节点

create -s /seq0000000004/cs children01
ls /seq0000000004

创建说完了,接着如何查询一个节点的信息呢?例如我们指定的value,很简单使用get命令即可

get /a

可以看到返回了一串信息,分别介绍下

// 这个地方是value
a
// 事务ID号
cZxid = 0xd
// 事务发生时间,也可以理解为创建时间
ctime = Wed Jul 04 15:11:09 UTC 2018
// 最后修改的事务ID号
mZxid = 0xd
// 修改发生时间
mtime = Wed Jul 04 15:11:09 UTC 2018
// 添加或者删除子节点操作的事务ID👌
pZxid = 0xe
// 当前节点的版本号
cversion = 1
// 当前节点数据的版本号
dataVersion = 0
// ACL版本号
aclVersion = 0
// 这个默认都是0,只有临时节点有,如果是临时节点,这里显示的是临时节点的会话ID
ephemeralOwner = 0x0
// value 长度
dataLength = 1
// 有多少个子节点
numChildren = 1

查询说完了,接我们来说下如何修改节点,也很简单利用set命令即可

set /a aa
get /a

可以看到修改时间和数据版本还有value都发生了变化,为什么这里要记录version呢?因为ZooKeeper面对并发写入情况下采用的是乐观锁的概念。

接着说一下如何删除一个节点,利用delete命令但有一个要注意的地方就是,要删除的节点必须没有子节点,否则你就要先从该节点的子节点删起

delete /a

看直接就提示了,该节点不是用空节点

ls /a
delete /a/aa
delete /a
ls /

已经删除掉了,更多的命令可以使用help来查询,接着我们来说一下集群,但在集群之前,先来说一下那个配置文件,还记得之前那个zoo.cfg嘛?接着先说说它,拿几个默认的出来说说

// 心跳维持时间,每个tickTime间隔就会发送一次心跳
tickTime=2000
//集群中fllower服务与leader服务器之间最长心跳时间 initLimit * tickTime
initLimit=10
//集群中leader和fllower之间发送消息请求和应答最大时间长度 syncLimit * tickTime
syncLimit=5
// 客户端连接端口
clientPort=2181
// 数据存放目录
dataDir=/tmp/zookeeper

OK,接着说说ZooKeeper的集群

分布式搭建

这便是ZooKeeper的集群结构了,从图上可以看到有三个角色,分别是 Leader、Follower、Observer,在理解这些角色之前我们要先知道ZooKeeper是依赖ZAB协议来实现分布式下的数据一致性算法,ZAB算法是一种专门为ZooKeeper设计的一种支持崩溃恢复的原子广播协议,基于该协议ZooKeeper实现了一种主备模式的架构来保证分布式下的数据一致性,在分布式环境下,所有的事务操作(例如创建和修改)都会交给Leader来实现,其它的Follower也只负责转发,所有的非事务操作自然就交给Follower是不是有点像数据库的读写分离?那这个Leader和Follower是怎么配置和设定的?这个不需要设定,ZooKeeper对主从有几种选举机制,就算在集群环境中Leader节点挂了也会立马从Follower节点中选举出一个Leader来,具体的选举算法,我留在下一篇,下一篇我们来聊聊ZooKeeper的一些原理,接着来说说Observer这个角色,这个角色比较特殊,因为它只负责在不影响集群事务处理能力的前提下来提升集群的非事务的处理性能(如何处理的也放在下一篇原理篇),说了一堆概念,接着我们来说说ZooKeeper的集群环境搭建

首先我准备了3台CentOS的机器,我是使用Docker搭建的环境,推荐大家也使用,当然大家用本机或者虚拟机都是可行的,环境而已无所谓。

首先修改各自下面的zoo.cfg文件 添加内容如下:

// 格式为 IP or HOST + Port1 + Port2
server.1=centos_centos1_1:2333:3333
server.2=centos_centos2_1:2333:3333
server.3=centos_centos3_1:2333:3333

来说一下,IP or Host这个我就无需解释了,port1也就是第一个端口是Leader和Follower之间的通信传输端口,port2也就是第二个端口是主机间选举Leader时使用的接口,接着我们在各

接着我们去各个主机的dataDir目录下去创建myid文件,其内容为各自节点ID

第一台主机 第二台主机 第三台主机 配置完成,接着启动来看看 启动后接着来看看它的日志文件,就在bin目录下cat zookeeper.out 发现虽然是启动完成了,但是抛了一个异常,这个不用太在意,是另外2台机器还没有启动起来,接着把他们分别启动,OK都启动后,我们分别使用他们的客户端连接Server

./zkCli.sh 

接着我分别执行

可以发现我们之前插入的数据也被同步到各个节点了,接着随意在一台机器上插入数据

create /a cc

那如何知道我这台机器是Follower还是Leader呢?使用bin目录下的zkServer.sh

./zkServer.sh status

第一台机器 第二台机器 第三台机器

可以看到这些数据都有一个mode的属性,这个mode的值即指明了当前谁是follower谁是leader,集群搭建就到这里,下一篇说ZooKeeper的一些原理的时候还会再细写

使用场景

简单举几个例子,范围太广了

负载均衡

通过ZooKeeper的负载均衡可以很好的通过ZooKeeper来做到负载均衡,例如我们的节点都是注册在ZooKeeper上,那么我们就可以根据ZooKeeper下节点的使用情况来自定义负载路由算法,最常见的使用场景也就是 Dubbo + ZooKeeper 、Kafka

注册中心

还需要解释么,而且利用其临时节点的特性非常好实现,众所周知,ZooKeeper的临时节点在其会话断开时会在一个心跳周期内将其干掉~

未完待续,敬请关注下一篇:《ZooKeeper的一些原理,了解一下》

如果你觉得作者写的这篇文章对你有帮助或者收获很大的话,你可以尝试着请我喝一瓶《东方树叶》或者吃一块《鸡胸》来激励我!!!

微信请客

支付宝请客

月泉
伪文艺中二青年,热爱技术,热爱生活。