前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Zookeeper入门(一)

Zookeeper入门(一)

作者头像
用户3587585
发布2022-09-21 07:16:51
4670
发布2022-09-21 07:16:51
举报
文章被收录于专栏:阿福谈Web编程阿福谈Web编程

zookeeper简介

ZooKeeper是一个分布式开源的分布式应用协调服务。它公开了一组简单的原语,分布式应用程序可以在其基础上实现用于同步、配置维护以及分组和命名的更高级别服务。它的设计便于编程,并使用了一种熟悉的文件系统目录树结构样式的数据模型。它使用Java语言编写,并且有针对Java和C的客户端。

众所周知,协调服务很难做好。它们特别容易出现竞争条件和死锁等错误。ZooKeeper背后的动机是为了减轻分布式应用从头开始实现协调服务的压力。

zookeeper特性

简单

ZooKeeper允许分布式进程通过一个共享的分层命名空间来相互协调,这个命名空间的组织方式类似于一个标准的文件系统。命名空间由数据寄存器组成,在ZooKeeper中称为znodes,它们类似于文件和目录。与为存储而设计的典型文件系统不同,ZooKeeper的数据保存在内存中,这意味着ZooKeeper可以实现高吞吐量和低延迟数。

ZooKeeper的实现重视高性能、高可用性、严格有序的访问。ZooKeeper的性能意味着它可以用于大型分布式系统。可靠性方面使它不会成为单点故障。严格的排序意味着可以在客户机上实现复杂的同步。

可备份

就像它所协调的分布式进程一样,ZooKeeper本身也被用于在一组称为集群的主机上进行复制

图 1 zookeeper集群架构图(来源:apache zookeeper官网)

组成ZooKeeper服务的服务器必须相互了解。它们在内存中维护状态快照,并在持久存储中维护事务日志和快照。只要大多数服务器可用,ZooKeeper服务就可用。

客户端连接单个ZooKeeper服务器。客户机维护一个TCP连接,通过该连接发送请求、获取响应、获取监视事件和发送心跳。如果与服务器的TCP连接中断,客户端将连接到另一个服务器

有序

ZooKeeper用一个数字标记每个更新,这个数字反映了所有ZooKeeper事务的顺序。后续操作可以使用该顺序来实现更高级的抽象,比如同步原语

快速

它在“读为主”的工作负载中尤其快。ZooKeeper应用程序运行在数千台机器上,在读比写更常见的地方性能最好,其比率约为10:1

数据模型和层次命名空间

ZooKeeper提供的命名空间很像标准的文件系统。名称是由斜杠(/)分隔的路径元素序列。ZooKeeper命名空间中的每个节点都由路径标识

图 2 zookeeper 数据结构图(来源:apache zookeeper 官网)

ZooKeeper数据节点类型

zookeeper的数据节点有4中类型,分别是持久节点、有序持久节点、临时节点和临时有序节点。

  • 持久节点(persistent node): zookeeper默认创建的数据节点都是持久节点,持久节点创建之后只要用户不主动删除就会一直存在于Zookeeper的命名空间中
  • 持久有序节点(persistent sequence node):通过 create -s 命令创建的节点是持久有序节点,有序节点创建后会在/path后面自动加上一个10位的数字,这个数字从0开始一路递增,后面每次对相同的路径执行create 操作都会让后面的数字+1,执行get pathname获取路径下的数字时pathname后面也需要带上对于版本号的序列号。
  • 临时节点(ephemeral node):通过create -e 参数创建的节点属于临时节点,临时节点在会话关闭后就会被删除。临时节点常用于实现微服务实例上线和下线。
  • ;临时有序节点(ephemeral sequence znode):临时有序节点:通过create -s -e 参数创建的节点属于临时有序节点。顾名思义,临时有序节点就是有序号的临时节点,节点名称的后面也会自动加上一个10位的序号数字。临时有序节点常用语实现分布式事务锁。

文件系统不同,ZooKeeper名称空间中的每个节点都可以有与其关联的数据以及子节点。这就像拥有一个文件系统,它允许一个文件同时也是一个目录。(ZooKeeper被设计用来存储协调数据:状态信息、配置、位置信息等,所以每个节点存储的数据通常很小,以字节到千字节为单位) 我们使用术语znode来表明我们谈论的是ZooKeeper数据节点

Znodes维护一个统计结构,其中包括数据更改的版本号、ACL更改和时间戳,以允许缓存验证和协调更新。每次znode的数据发生变化,版本号就会增加。例如,每当客户机检索数据时,它也会接收数据的版本。

存储在名称空间中的每个znode中的数据是原子地读取和写入的。读操作获取与znode相关的所有数据字节,写操作替换所有数据。每个节点都有一个访问控制列表(Access Control List, ACL),用于限制谁可以做什么。

条件更新与监听

zookeeper支持监听器的概念,客户端可以在一个znode节点上设置监听,监听器watcher可以通过节点的变化来触发和删除。当一个watch被触发时,客户端会收到一个通知znode已经改变的数据包。当客户端与ZooKeeper服务器之间的连接中断时,客户端会收到本地通知

3.6.0 版本新特性:客户端还可以在一个znode上设置永久的递归监视,该监视在触发时不会删除,并递归地触发已注册的znode以及任何子节点上的变化

数据一致性保证

ZooKeeper非常快速和简单。但是,由于它的目标是成为更复杂的服务(如同步)构造的基础,因此它具有如下几个保证数据一致性的特性:

  • 顺序一致性: 客户端的更新将按照它们被发送的顺序更新
  • 原子性:更新要么成功,要么失败,没有中间结果
  • 但系统镜像:客户机将看到服务的相同视图,而不管它连接到哪个服务器。也就是说,即使客户端故障转移到具有相同会话的不同服务器,客户端也永远不会看到系统的旧视图
  • 可靠性:一旦应用了更新,它将从那时起持续存储,直到客户端覆盖了更新
  • 及时性:系统的客户端视图保证在一定的时间范围内是最新的

简单的API

ZooKeeper的设计目标之一就是提供一个非常简单的编程界面。因此,它只支持这些操作

  • create: 在树中的某个位置创建节点
  • delete: 删除节点
  • exists:测试在某个位置是否存在节点
  • get data : 从节点中读取数据
  • set data: 将数据写到节点中
  • get children:从一个节点中检索中所有子节点
  • sync: 等待数据被传播

zookeeper的安装与启动

下载地址:https://zookeeper.apache.org/

笔者下的是最新的稳定版本压缩包:apache-zookeeper-3.7.1-bin.tar.gz

解压

将下载的压缩包上传到Linux服务器,然后执行解压缩命令

代码语言:javascript
复制
tar zxvf apache-zookeeper-3.7.1-bin.tar.gz

图 3 linux服务器上执行解压缩命令

执行重命名命令:mv apache-zookeeper-3.7.1-bin zookeeper-3.7.1

配置

1) 执行以下命令进入配置项目录: cd ./zookeeper-3.7.1/cfg

2)执行拷贝zoo_sample.cfg文件并重命名为zoo.cfg命令:cp zoo_sample.cfg zoo.cfg

  1. 执行编辑zoo.cfg命令vim zoo.cfg可以看到其中的配置项;

图 4 zookeeper配置文件配置选项

配置项解释

  • tickTime: zookeeper服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个tickTime时间就会发送一个心跳, 单位毫秒(ms。该参数用来定义心跳的时间间隔,zookeeper的客户端和服务端之间也有类似和Web开发里类似的session的概念, 而zookeeper里最小的session过期时间就是tickTime的两倍
  • initLimit: Follow启动过程中会从Leader同步所有最新数据,然后确定自己能够对外服务的起始状态。Leader允许Follow在nitLimit时间内完成这个工作。通常情况下,我们不要太在意这个参数。如果zookeeper集群的数据量确实很大了,Follow在启动时从Leader同步数据的时间也要相应变长,在这种情况下才有必要调大参数值。initTime默认值为10
  • syncLimit: Leader在运行过程中负责与ZK集群中的所有机器通信,例如通过一些心跳检测机制来检测机器的存活状态,如果Leader在发出心跳包之后在syncLimit时间之后还没有收到Follow的回应,那就任务这台Follow机器挂掉了。注意不要把这个参数设置过大,否则可能掩盖一些问题。
  • dataDir: 存储快照文件snapshot的目录。默认情况下事务日志也会存储在这里,建议同时配置参数dataLogDir, 事务日志的写性能直接影响ZK性能
  • clientPort: 客户端连接服务器的端口
  • maxClientCnxns: ZK服务器最多允许的分客户端连接数

简化以下配置文件:

代码语言:javascript
复制
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/local/zookeeper-3.7.1/data
dataLogDir=/usr/local/zookeeper-3.7.1/logs

cd到/usr/local/zookeeper-3.7.1目录通过下面的命令创建data和logs目录

代码语言:javascript
复制
mkdir data logs

启动与停止ZK服务

进入到/usr/local/zookeeper-3.7.1/bin目录下

图5 zookeeper/bin目录下命令可用命令

可通过下面的方式将zookeeper/bin目录加入到环境变量

代码语言:javascript
复制
# 编辑环境变量
vim /etc/profile
# 在开发的文件中按住i键进入编辑状态后在CLASSPATH变量后面暴露zookeeper的环境变量
export ZOOKEEPER_HOME=/usr/local/zookeeper-3.7.1
PATH=$ZOOKEEPER_HOME/bin:$JAVA_HOME/bin:$PATH
# 然后按住esc键输入:wq后保存退出
# 输入如下的命令使配置的环境变量生效
source /etc/profile

图 6 配置ZOOKEEPER_HOME环境变量

这样就可以在任服务器的任意目录下运行zkServer.sh和zkCli.sh命令了,无需进入zookeeper的bin目录下执行

启动服务和建立客户端连接命令

打开命令行工具运行zkServer.sh start命令,运行成功后控制太显示如下信息表示zookeeper服务启动成功

代码语言:javascript
复制
Starting zookeeper ... STARTED

zookeeper启动成功后可通过下面的命令停止zookeeper服务

代码语言:javascript
复制
zkServer.sh stop

关闭成功后会在命令控制台看到如下信息:

代码语言:javascript
复制
Stopping zookeeper ... STOPPED

客户端连接zookeeper服务

在启动zookeeper服务的前提下,打开一个新的客户端会话,在命令行中输入如下命令

代码语言:javascript
复制
zkCli.sh

运行成功后会看到客户端连接成功日志,最后可以在命令行中看到入戏控制台信息

代码语言:javascript
复制
[zk: localhost:2181(CONNECTED) 0]

关于API的使用下一篇文章我们再介绍

集群环境搭建

由于是在单机环境下模拟集群环境, 因而需要使用不同端口来模拟不同主机

复制配置文件

代码语言:javascript
复制
cd /usr/local/zookeeper-3.7.1/cfg
cp zoo.cfg zoo1.cfg
cp zoo.cfg zoo2.cfg
cp zoo.cfg zoo3.cfg

创建数据和日志文件目录

代码语言:javascript
复制
# 切换到zookeeper主目录
cd ../
# 执行创建过个目录命令
mkdir data_1 data_2 data_3 logs_1 logs_2 logs_3

创建myid文件

代码语言:javascript
复制
echo "1" > ./data_1/myid
echo "2" > ./data_2/myid
echo "3" > ./data_3/myid

修改配置文件

  1. zoo1.cfg
代码语言:javascript
复制
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/local/zookeeper-3.7.1/data_1
clientPort=2181
dataLogDir=/usr/local/zookeeper-3.7.1/logs_1
# server.x中的x和myid中的值保持一致,第一个端口用于Leader和Learner之间的同步通信,第二个端口用于选举过程中的投票通信
server.1=localhost:2887:3887
server.2=localhost:2888:3888
server.3=localhost:2889:3889
  1. zoo2.cfg
代码语言:javascript
复制
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/local/zookeeper-3.7.1/data_2
clientPort=2182
dataLogDir=/usr/local/zookeeper-3.7.1/logs_2
# server.x中的x和myid中的值保持一致,第一个端口用于Leader和Learner之间的同步通信,第二个端口用于选举过程中的投票通信
server.1=localhost:2887:3887
server.2=localhost:2888:3888
server.3=localhost:2889:3889
  1. zoo3.cfg
代码语言:javascript
复制
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/local/zookeeper-3.7.1/data_3
clientPort=2183
dataLogDir=/usr/local/zookeeper-3.7.1/logs_3
# server.x中的x和myid中的值保持一致,第一个端口用于Leader和Learner之间的同步通信,第二个端口用于选举过程中的投票通信
server.1=localhost:2887:3887
server.2=localhost:2888:3888
server.3=localhost:2889:3889

启动集群

zookeeper主目录下的命令控制台中依次执行下面三条命令

代码语言:javascript
复制
zkServer.sh  start ./conf/zoo1.cfg

zkServer.sh start ./conf/zoo2.cfg

zkServer.sh  start ./conf/zoo3.cfg

以上每输入一条命令回车后控制台都会有表示ZK服务节点启动成功的信息

代码语言:javascript
复制
Starting zookeeper ... STARTED

验证服务节点状态

zookeeper主目录下的命令控制台中依次执行如下命令

代码语言:javascript
复制
zkServer.sh status ./conf/zoo1.cfg

zkServer.sh status ./conf/zoo2.cfg

zkServer.sh status ./conf/zoo3.cfg

可以看到如下信息:

代码语言:javascript
复制
Server1: Mode: follower
Server2: Mode: leader
Server2: Mode: follower

打开三个客户端分别连上三个服务端

代码语言:javascript
复制
zkCli.sh -server localhost:2181

zkCli.sh -server localhost:2182

zkCli.sh -server localhost:2183

连上之后可以看到在三个客户端执行 ls /命令 可以分别查到三个Server的当前目录结构都是一致的,都是[zookeeper]

在连接Server1的客户端命令控制台中输入创建节点命令

代码语言:javascript
复制
create /firstNode  serverCreated

然后执行获取新创建节点数据命令:

代码语言:javascript
复制
get /firstNode

可以看到serverCreated 信息

在连接Server2Server3的客户端命令控制台执行get /firstNode命令也可以看到相同的信息

说明在集群模式下任意一个服务端节点创建了节点数据,都会同步到另外的ZK服务节点中去

集群中增加Observer节点

zoo4.cfg节点配置中增加如下配置

代码语言:javascript
复制
# zoo4.cfg中单独添加
peerType=observer
#servers列表中增加(集群中的所有zoox.cfg都需要添加)
server.4=localhost:2890:3890

集群中的角色

  • 领导者(Leader): 领导者不接受客户端请求,负责进行投票的发起和决议,
  • 跟随者(Follower): 用于接收客户端请求并返回结果,同时参与Leader发起的投票
  • 观察者(Observer):Observer可以接受客户端请求,并把请求转发给Leader, 但是Observer不参与投票过程,只是同步Leader的转态, Observer为系统扩展提供了一种方式
  • 学习者(Learner):和Leader进行状态同步的server统称为Learner, 以上的Follower和Observer都是Learner

结语

本文是一篇分布式协调器zookeeper中间件的入门文章,主要介绍了zookeeper的基本概念、特性、数据模型和命名空间、安装与启动以及集群模式。下一篇文章我们在介绍利用zookeeper的监听机制使用Java客户端连接zookeeper实现一个分布式配置中心。

往期原创

【1】SpringBoot项目整合Vue做一个完整的用户注册功能

【2】看官网自学Kafka太慢,我选择在掘金小册订阅《图解Kafka之实战指南》

【3】VueblogServer项目短信验证码登录功能前端实现

【4】手把手带你在集成SpringSecurity的SpringBoot应用中添加短信验证码登录认证功能

【5】从源码的角度详细分析SpringBoot启动流程

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-07-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 阿福谈Web编程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • zookeeper简介
  • zookeeper特性
    • 简单
      • 可备份
        • 有序
          • 快速
          • 数据模型和层次命名空间
            • ZooKeeper数据节点类型
              • 条件更新与监听
                • 数据一致性保证
                  • 简单的API
                  • zookeeper的安装与启动
                    • 解压
                      • 配置
                        • 配置项解释
                          • 启动与停止ZK服务
                            • 客户端连接zookeeper服务
                            • 集群环境搭建
                              • 复制配置文件
                                • 创建数据和日志文件目录
                                  • 创建myid文件
                                    • 修改配置文件
                                      • 启动集群
                                        • 验证服务节点状态
                                          • 集群中增加Observer节点
                                            • 集群中的角色
                                              • 结语
                                              相关产品与服务
                                              验证码
                                              腾讯云新一代行为验证码(Captcha),基于十道安全栅栏, 为网页、App、小程序开发者打造立体、全面的人机验证。最大程度保护注册登录、活动秒杀、点赞发帖、数据保护等各大场景下业务安全的同时,提供更精细化的用户体验。
                                              领券
                                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档