Zookeeper简介
ZooKeeper 是一个开源的分布式 协调服务框架,它是一个为分布式应用提供一致性服务的软件,是雅虎公司创建,是 Google 的 Chubby 一个开源的实现。
Zookeeper作用应用
ZooKeeper作用主要包含如下ZooKeeper应用场景:
1.数据发布与订阅
数据发布/订阅系统,顾名思义就是发布者将数据发布到ZooKeeper的一个或一系列节点上,供订阅者进行数据订阅。
数据发布/订阅模式是一对多的关系,多个订阅者对象同时监听某一主题对象,这个主题对象在自身状态发生变化时会通知所有的订阅者对象。
Zookeeper采用了推拉相结合的模式,客户端向服务端注册自己需要关注的节点,一旦该节点数据发生变更,那么服务端就会向相应的客户端推送Watcher事件通知。
客户端接收到此通知后,主动到服务端获取最新的数据。
2.配置管理
假如:我们线上有个服务器集群,成百上千台服务器,如果更新配置的时候怎么更新呢,一台台机器去更新?这时候做修改那就太不切实际了,那么就需要用到统一配置管理。
如下图所示:
将配置信息保存在 Zookeeper 的某个目录节点中,一旦配置信息发生变化,每台应用机器就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中。
3.命名服务
命名服务是指通过指定的名字来获取资源或者服务的地址,利用 ZooKeeper创建一个全局的路径,这个路径就可以作为一个名字。
比如,Dubbo使用ZooKeeper为其命名服务,维护全局的服务地址列表。
下图所示:
左侧Service唯一服务名称:
com.mikechen.helloService
这个就是命名服务,利用 ZooKeeper创建一个全局的路径,这个路径(com.mikechen.helloService)就可以作为一个名字,产生唯一的标识。
Dubbo中使用ZooKeeper来作为其命名服务,维护全局的服务地址列表,客户端应用能够根据指定名字来获取资源或服务的地址,提供者等信息。
Zookeeper数据模型
Zookeeper 中的所有存储的数据是由 znode 组成的,节点也称为 znode,并以 key/value 形式存储数据。
整体结构类似于 linux 文件系统的模式以树形结构存储,其中根路径以 / 开头。
1.节点构造
如下图所示:
2.节点组成:
图中的每个节点称为一个Znode,每个Znode由3部分组成:
- stat:此为状态信息, 描述该Znode的版本权限等信息;
- data:与该Znode关联的数据;
- children:该Znode下的子节点;
3.节点类型
Znode主要包含4种类型:分别为临时节点、永久节点、序列化节点。
Zookeeper通知Watch
客户端注册监听他关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,Zookeeper会通知客户端。
client端会对某个znode建立一个watcher事件,当该znode发生变化时,zk会主动通知watch这个znode的client,然后client根据znode的变化来做出业务上的改变等。
watch的整体流程如下图所示:
主要流程如下:
1.客户端先向Zookeeper服务端成功注册想要监听的节点状态。
2.同时客户端本地会存储该监听器相关的信息在WatchManager中。
3.当Zookeeper服务端监听的数据状态发生变化时,Zookeeper就会主动通知发送相应事件信息给相关会话客户端,从WatherManager中取出对应Wather对象执行回调逻辑。
Zookeeper工作原理
Zookeeper原理是一个集群结构,有一个leader节点负责写请求,多个follower负责响应读请求,并且在leader节点故障时会自动根据选举机制从剩下的follower中选出新的leader。
1.Zookeeper角色
1).leader
处理所有的事务请求(写请求),可以处理读请求,集群中只能有一个Leader
2). Follower
只能处理读请求,同时作为 Leader的候选节点,即如果Leader宕机,Follower节点要参与到新的Leader选举中,有可能成为新的Leader节点。
3). Observer
Observer:只能处理读请求,不能参与选举。
2.Zookeeper集群
集群为2N+1台,比如N为1的情况就是3台,为什么是3台而不是2台呢?因为集群需要一半以上的机器可用。
3).ZAB协议
Zab协议是为分布式协调服务Zookeeper专门设计的一种 支持崩溃恢复 的 原子广播协议 ,是Zookeeper保证数据一致性的核心算法。
Zab借鉴了Paxos算法但又不像Paxos那样,与Raft算法类似,是一种通用的分布式一致性共识算法。
Zab 协议的原理可细分为如下四个阶段:
1.Leader election(选举阶段)
节点在一开始都处于选举阶段,只要有一个节点得到超过半数节点的票数,它就可以当选准 Leader。
2.Discovery(发现阶段)
在这个阶段,Followers跟准Leader进行通信,同步Followers最近接收的事务提议。
3.Synchronization(同步阶段)
同步阶段主要是利用Leader前一阶段获得的最新提议历史,同步集群中所有的副本。同步完成之后准Leader才会成为真正的Leader。
4.Broadcast(广播阶段)
到了这个阶段,Zookeeper集群才能正式对外提供事务服务,并且Leader 可以进行消息广播,同时如果有新的节点加入,还需要对新节点进行同步。
Zookeeper下载
zookeeper官方下载地址:
https://zookeeper.apache.org/releases.html
选择上图红框的版本,点击下载对应需要的zookeeper版本即可。
zookeeper安装
1.zookeeper解压
下载完最新zookeeper 3.7.1稳定版本后,解压下载的压缩包。
如下图所示:
2.重命名配置文件
解压后进入conf文件夹下面,把zoo_sample.cfg复制一份并改名为zoo.cfg。
如下图所示:
备注:zoo.cfg是zookeeper配置文件入口,必须修改为zoo.cfg。
3.新建数据和日志文件
在根目录下新建一个data文件夹和一个log文件夹,分别存储数据和日志。
如下图所示:
4.修改Zookeeper配置文件
进入conf文件夹下面,修改zoo.cfg配置文件,把dataDir=/tmp/zookeeper 修改成 zookeeper 安装目录所在的 data 文件夹,以及dataLogDir修改为log文件夹。
如下图所示:
3.启动zookeeper
1).启动zookeeper服务端
进入bin文件夹,双击点击zkServer.cmd启动zookeeper。
如下图所示:
控制台显示:
bind to port 0.0.0.0/0.0.0.0:2181
表示服务端启动成功了。
2).启动zookeeper客户端
双击zkCli.cmd启动客户端,出现:
Welcome to ZooKeeper!
表示启动成功了。
Zookeeper命令
1.启动zookeeper命令
bin/zkServer.sh start
2.查看zookeeper服务命令
bin/zkServer.sh status
3.停止zookeeper命令
bin/zkServer.sh stop
4.重启zookeeper命令
bin/zkServer.sh restart
5.连接zookeeper服务
启动ZooKeeper服务之后,我们可以使用如下命令连接到 ZooKeeper 服务:
./zkCli.sh -server 127.0.0.1:2181
6.create创建节点
create 命令用于创建节点并赋值
比如:
create /mikechen "架构"
7.获取节点数据命令
get 命令用于获取节点数据和状态信息:
get /mikechen watch
8.修改节点数据命令
set 命令用于修改节点存储的数据:
set /zk "zkbak"
Zookeeper使用
下面我以Java为例详解Zookeeper使用:
1.加入Maven ZooKeeper依赖
<dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.6.2</version> </dependency>
2.客户端连接服务端
要操 ZooKeeper首先得先创建一个客户端对象:
ZooKeeper client = new ZooKeeper("127.0.0.1:2181/mikechen", 3000, null);
3.创建路径
连接ZooKeeper服务端后,客户端就开始使用了,先创建路径:
client.create("/架构/视频", "视频具体内容".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
最后的 CreateMode.PERSISTENT 代表当前节点是一个持久类型的节点。
路径创建完就会是这样:
mikechen |--架构 |--视频
4.设置数据
代码:
client.setData("/架构/视频", "并发编程视频".getBytes(), -1);
5.获取数据
代码:
byte[] data = client.getData("/架构/视频", false, null); System.out.println(new String(data)); // 这是Data,可以写一些关于业务的参数
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》