分布式组件 ZooKeeper 介绍、术语概述以及集群搭建篇

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
日志服务 SLS,月写入数据量 50GB 1个月
简介: 分布式组件 ZooKeeper 介绍、术语概述以及集群搭建篇

前言

ZooKeeper 是分布式应用程序的分布式开源协调服务;它公开了一组简单的原语,分布式应用程序可以基于这些原语来实现更高级别的同步、配置维护以及组和命名服务;数据模型是以熟悉的文件系统目录结构为导向的

ZooKeeper 官网:https://zookeeper.apache.org/doc/current/zookeeperOver.html

  1. ZooKeeper very simple,通过共享的命名空间相互协调,该命名空间的组织类似于标准文件系统;ZK 数据保存在内存中,这意味着 ZK 可以实现高吞吐量和低延迟
  2. ZooKeeper 可以用来做复制->数据同步的,Leader 服务节点用来处理 write 写请求,其他 follower、 observer 服务节点用来处理 read 请求,它们接收到写请求时都是转交给 Leader 节点处理的
  3. ZooKeeper 速度很快,ZooKeeper 应用程序在数千台机器上运行,它在更常见的情况读取比写入表现最佳,比率约为 10:1,读取多于写入的应用程序中具有特别高的性能,因为写入涉及到需要同步所有服务器状态(读取多于写入通常是协调服务的情况

①跟随者的失败和恢复、②不同 follower 的故障和恢复、③领导者的失败、④两个 follower 的故障和恢复、⑤另一个领导者的失败

摘自官网的这张图中,有一些重要的观察结果。首先,如果跟随者失败并快速恢复,那么即使出现故障,ZooKeeper 也能够维持高吞吐量。但也许更重要的是,领导者选举算法允许系统足够快地恢复以防止吞吐量大幅下降。在我们的观察中,ZooKeeper 花费不到 200 毫秒的时间来选举一个新的领导者。其次,随着追随者的恢复,一旦他们开始处理请求,ZooKeeper 能够再次提高吞吐量

服务模型

在 ZK 集群正常运作时,由客户端发起写请求,若请求的节点为 Follow 节点,那么它还会转发给到 Leader,由 Leader 节点去完成这部分写操作;若为读请求,在 Follow 节点这一侧直接读取即可.

既然是集群了,总归是会有网络不稳定或资源不足的情况导致节点宕机,在故障恢复的这一阶段,其他请求的服务都是 不可用状态,而 ZK 作为分布式协调服务组件,它必然会有可靠的方式去保证集群可用态

在 ZK 内部基于 Paxos 一致性算法,通过 ZAB(ZooKeeper Atomic Broadcast)->ZK 原子广播协议来恢复集群为可用状态;它有两种基本模式,如下:

1、崩溃恢复,Leader 出现网络中断、崩溃重启等异常情况下,ZAB 协议就会进行到恢复模式,来重新选举一个新的 Leader 服务来处理事务请求,当新的 Leader 服务器选择出来以后,并且和过半以上的机器进行了状态同步以后,恢复模式就结束了。在选举时,会有如下过程:3888 端口形成 一对一 通信、任何人投票,都会触发准 Leader 发起自己的投票、推选机制:先比较节点内部的 Zxid,若 Zxid 相同,就选取那个 myid 值最大的节点作为 Leader

2、消息广播,消息广播使用的是一个原子广播协议,整体的过程可以看作是一个二阶段提交的过程.

第一阶段,Leader 机器会将事务消息生成对应的 proposal(提案)广播,并且会生成一个单调递增的 ID,作为事务的 ID(Zxid),由于 ZAB 协议需要保证事务严格的上下顺序性,所以会严格按照 Zxid 的先后来处理对应的消息;在消息广播发起后,Leader 会为每一个 Follower 服务器分配一个单独的队列,然后将需要广播出去的事务 Proposal 依次存放进这个 FIFO 队列中,每个 Follower 机器收到事务消息后,会按照事务日志的方式写入,成功反馈给 Leader 服务器 Ack 响应,当收到半数以上的 Ack 响应后,Leader 就会发起第二阶段的 Commit 消息给所有的 Follower 机器,并且这个时候 Leader 也会和 Follower 一样进行本地事务的提交操作,完成整个消息的传递和提交

推荐一篇文章,使用总统选举的例子,来简要描述 ZK 服务中的一些概念模型,Zookeeper全解析——Paxos作为灵魂

术语概述

namespace

ZooKeeper 提供的命名空间很像标准文件系统中的命名空间,名称是由斜杠 (/) 分隔开的一系列路径元素,ZooKeeper 命名空间中的每个节点都有路径去标识,每个节点最大存储数据大小为 1MB

node

ZooKeeper 命名空间中的每个节点都可以拥有与其关联的数据以及子节点,使用术语 znode 来明确 ZooKeeper 的数据节点

节点存在以下几种类型

  1. 持久化节点:默认 create /path data,就是持久化节点
  2. 临时节点:create -e(ephemeral),通过它来创建客户端节点的 session,处于活动状态,znode 存在;当会话结束以后,znode 就会被删除
  3. 序列化节点:create -s,防止多个客户端同时设置同一个节点,若为同一个节点时,通过 -s 创建完的节点会按序列增长 00000000

节点存在以下的特征及使用:

  1. 统一的配置管理,每个 node 节点最多可存储 1M 大小
  2. 分组管理,基于 path 目录树结构
  3. 统一命名,通过 sequence 来保证节点唯一
  4. 会话状态下的同步、分布式锁,通过临时节点来保证,锁依托于一个父节点且它具备 -s 系列化形式,代表父节点下可以同时拥有多把锁,以一个队列式方式存储事务的锁
  5. 大数据场景下,通常用分布式锁来进行选主,谁抢到这把锁那么谁就是主节点

myid

Server Id:服务器 id,它是每个服务节点的唯一标识

比如有三台服务节点,编号分别是 1、2、3,编号越大的服务权重就越大,在初始化启动时就是根据服务器 id 来进行比较的,较小的编号会变更选票偏向于编号大的,当对应的编号获得集群中过半数选票,那么此编号标识的服务就是 Leader

Zxid

ZooKeeper transaction:事务id

服务中存放的事务 id 越大代表它的数据越新,即代表它的权重就越大,在重新选举时通过 Zxid 值比较,谁大谁当主

选举状态

Looking:竞选状态

Following:随从状态,同步 Leader 状态,参与选票

Observing:观察状态,同步 Leader 状态,不参与选票

Leading:领导者状态

特征

ZooKeeper 非常快速且非常简单,但是,由于它的目标是成为构建更复杂服务(例如同步)的基础,因此它提供了一组保证,如下:

  1. 顺序一致性:来自客户端的更新将按发送的顺序应用
  2. 原子性:更新要么成功要么失败,没有部分结果
  3. 统一视图:无论连接到哪个服务器,客户端都将看到相同的服务视图。即使客户端故障转移到具有相同会话的不同服务器,客户端也永远不会看到系统的旧视图
  4. 可靠性:应用更新后,它将从那时起持续存在,直到客户端覆盖更新
  5. 及时性:系统的客户视图保证在特定时间范围内是最新的

安装及使用

基于该文章搭建好多台虚拟机节点:Mac M1 搭建虚拟机节点集群过程及软件分享

前置环境要求:Jdk 1.8,之前在搭建 Nacos 集群有具体描述:Nacos 介绍及搭建集群、相关组件

那么接下来就是如何搭建好一个 ZooKeeper 集群,准备好四台虚拟机节点,172.16.249.10-172.16.249.13(node1-node4)

zookeeper-tar.gz 下载:https://archive.apache.org/dist/zookeeper/zookeeper-3.4.6/

install

前置工作,先为每台机器节点配置域名,实现节点之间通过域名方式绑定

  1. vim /etc/hosts
172.16.249.10 node1
172.16.249.11 node2
172.16.249.12 node3
172.16.249.13 node4
  1. 刷新域名 IP 配置:iptables -F

上传 zookeeper-release-3.4.6.tar.gz 文件到服务器中

1、解压 tar.gz:tar xf zookeeper-3.4.6.tar.gz

2、将文件拷贝到指定目录下:mv -p zookeeper-3.4.6 /opt/vnjohn/zk

3、备份配置文件:cd conf/ && cp zoo_sample.cfg zoo.cfg

4、调整 zoo.cfg 配置文件

# 指定数据目录
dataDir=/var/vnjohn/zk
# 绑定 Server Id、节点 | 端口 关系
server.1=node1:2888:3888
server.2=node2:2888:3888
server.3=node3:2888:3888
server.4=node4:2888:3888

5、创建目录&设置节点的 Servcer Id 值,每个节点要设置的值不一样

# node1
mkdir -p /var/vnjohn/zk && touch /var/vnjohn/zk/myid && echo 1 > /var/vnjohn/zk/myid
# node2
mkdir -p /var/vnjohn/zk && touch /var/vnjohn/zk/myid && echo 2 > /var/vnjohn/zk/myid
# node3 
mkdir -p /var/vnjohn/zk && touch /var/vnjohn/zk/myid && echo 3 > /var/vnjohn/zk/myid
# node4
mkdir -p /var/vnjohn/zk && touch /var/vnjohn/zk/myid && echo 4 > /var/vnjohn/zk/myid

6、由于每台节点的配置信息基本上都是一致的,除了 myid 文件内容需要保持不同而已,所以直接通过SFTP 方式传递到其他节点->node2~node4,目录保持和 node1 一样,再根据第 5 点设置 Server Id 值即可.

7、调整 /etc/profile 配置文件内容,追加内容如下:

ZOOKEEPER_HOME=/opt/vnjohn/zk
export PATH=$PATH:$ZOOKEEPER_HOME/bin

刷新配置文件:source /etc/profile

若配置文件修改出现问题,导致所有命令都不生效了,运行✅:export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin 后,再重新调整配置

8、启动 ZK,后台运行命令【zkServer.sh start】,先通过前台运行观察控制台打印的日志【zkServer.sh start-foreground】,如下:

刚启动的节点目前还是一个竞选 LOOKING 状态,通过 zkServer.sh status 命令可以查看 ZK 节点的状态,输出的日志内容告知它并未在运行【其实也说明它目前所在的选举状态:LOOKING】

[root@localhost ~]# zkServer.sh status
JMX enabled by default
Using config: /opt/vnjohn/zk/bin/../conf/zoo.cfg
Error contacting service. It is probably not running.

当 node2、node3 起来以后,node2 角色是 follow,而 node-3 角色必然就是 leader,初始化启动主要通过 myid【Service id】最大值对比,最大值的那个节点作为 Leader 节点,观察 node3 节点最后的输出日志

选举完成、同步数据给 Follower、收到 ack 响应

若 node4 此时再启动,那么它仍然会变为 node3 跟随者,随即 Leader 也会给它同步一份最新的数据样本

9、查看 node4->2888/3888 端口 TCP 连接信息

从图中可以观察到一些信息,node4 与 node1、2、3 的 3888 端口建立了连接,它们之间的通信是为了选举投票用的;但唯独与 node3 节点 2888 端口建立了连接,它的作用是:当 node4->follower 接到 write 写请求时,通过该端口转发数据包给 Leader 去处理

核心配置文件参数详解

# leader 和 follow 每个连接心跳的毫秒数
tickTime=2000
# 当有新的 follow 节点追随 leader 时,可以被允许 10*2000 20秒时间等待连接
initLimit=10
# leader 同步数据给 follow 时,5*2000 10秒没有获得回复也认为 follow 有问题
syncLimit=5
# 持久化目录
dataDir=/var/vnjohn/zookeeper
# 客户端连接的端口号
clientPort=2181
# 允许客户端最大连接数量,可以调大
# maxClientCnxns=60
# 3888 用处:当主挂了以后,这个时候就需要去投票选举,用这个端口
# 2888 用处:当主选好以后,就用这个端口 Leader 节点做通信 
server.1=node1:2888:3888
server.2=node2:2888:3888
server.3=node3:2888:3888
server.4=node4:2888:3888

使用

ZK 集群搭建好了,现在我们就可以基于它自带的客户端进行连接,去进行一些实际的命令操作!

1、进入控制台,输入:zkCli.sh 后回车即可

2、创建持久节点:create /vnjohn “”

创建一个 ooxx 的空内容节点,如果后面不写内容的话就不会进行创建,比如:create /vnjohn

3、创建临时节点:create /vnjohn/ephemeral -e

若我当前这个客户端连接关闭后,这个节点就会消失不见!

4、创建序列节点:create /vnjohn/sequence:1:1 -s “sequence” 10

防止并行时创建同样的节点从而覆盖掉,ZK 帮忙做了数据隔离

5、获取节点信息:get /vnjohn,获取到 vnjohn 创建时给的内容,同时对以下的参数进行描述:

""                    # 节点内容
cZxid = 0x200000002           # 创建节点时分配的事务 ID
ctime = Sat Mar 18 12:27:56 CST 2023  # 创建节点的时间
mZxid = 0x200000002           # 修改节点时分配的事务 ID
mtime = Sat Mar 18 12:27:56 CST 2023  # 修改节点的时间
pZxid = 0x200000005           # 当前节点下的最后一个子节点事务 ID,没有子节点就是当前节点的事务 ID
cversion = 2
dataVersion = 0
aclVersion = 0      
# 临时拥有者,只有创建临时节点时才会有值,这个值是客户端连接 ZK 时分配的 SESSION_ID
# 如果这个 SESSION 关闭了,这个节点就会消失 
# SESSION 在所有 zookeeper 节点下是都可以被看到的
ephemeralOwner = 0x0                
dataLength = 2
# 子节点数量,/vnjohn 下目前存在两个子节点
numChildren = 2                     

6、查询父节点下有多少个子节点:ls /

[zk: localhost:2181(CONNECTED) 24] ls /
[vnjohn, zookeeper]

连接 ZK 和关闭 ZK 都会消耗一个事务 ID

总结

该篇文,对 ZooKeeper 服务模型以及它的一些特性作了简要的描述,同时,介绍了 ZooKeeper 中一些面试中常常问到的术语,比如:myid、Zxid、选举状态等;为大家准备了在 Linux 中如何搭建好一个 ZK 集群,从日志内容分析出它与上下文之间的关系,对核心配置文件 zoo.cfg 参数作了介绍,最后对一些常见的 ZK 命令操作作了演示,当然,还有更多的特性,比如:分布式锁、Watch 机制!

推荐给大家 Raft 算法演变过程的网站,用动画的方式生动演练了选举主的过程->Raft Distributed Consensus

如果觉得博文不错,关注我 vnjohn,后续会有更多实战、源码、架构干货分享!

大家的「关注❤️ + 点赞👍 + 收藏⭐」就是我创作的最大动力!谢谢大家的支持,我们下文见!


相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
目录
相关文章
|
19天前
|
存储 运维 NoSQL
分布式读写锁的奥义:上古世代 ZooKeeper 的进击
本文作者将介绍女娲对社区 ZooKeeper 在分布式读写锁实践细节上的思考,希望帮助大家理解分布式读写锁背后的原理。
|
1月前
|
存储 分布式计算 负载均衡
分布式计算模型和集群计算模型的区别
【10月更文挑战第18天】分布式计算模型和集群计算模型各有特点和优势,在实际应用中需要根据具体的需求和条件选择合适的计算架构模式,以达到最佳的计算效果和性能。
60 2
|
2月前
|
分布式计算 NoSQL Java
Hadoop-32 ZooKeeper 分布式锁问题 分布式锁Java实现 附带案例和实现思路代码
Hadoop-32 ZooKeeper 分布式锁问题 分布式锁Java实现 附带案例和实现思路代码
48 2
|
2月前
|
分布式计算 Java Hadoop
Hadoop-30 ZooKeeper集群 JavaAPI 客户端 POM Java操作ZK 监听节点 监听数据变化 创建节点 删除节点
Hadoop-30 ZooKeeper集群 JavaAPI 客户端 POM Java操作ZK 监听节点 监听数据变化 创建节点 删除节点
68 1
|
2月前
|
分布式计算 监控 Hadoop
Hadoop-29 ZooKeeper集群 Watcher机制 工作原理 与 ZK基本命令 测试集群效果 3台公网云服务器
Hadoop-29 ZooKeeper集群 Watcher机制 工作原理 与 ZK基本命令 测试集群效果 3台公网云服务器
43 1
|
2月前
|
分布式计算 Hadoop Unix
Hadoop-28 ZooKeeper集群 ZNode简介概念和测试 数据结构与监听机制 持久性节点 持久顺序节点 事务ID Watcher机制
Hadoop-28 ZooKeeper集群 ZNode简介概念和测试 数据结构与监听机制 持久性节点 持久顺序节点 事务ID Watcher机制
46 1
|
2月前
|
分布式计算 Hadoop
Hadoop-27 ZooKeeper集群 集群配置启动 3台云服务器 myid集群 zoo.cfg多节点配置 分布式协调框架 Leader Follower Observer
Hadoop-27 ZooKeeper集群 集群配置启动 3台云服务器 myid集群 zoo.cfg多节点配置 分布式协调框架 Leader Follower Observer
51 1
|
1月前
|
存储 监控 大数据
构建高可用性ClickHouse集群:从单节点到分布式
【10月更文挑战第26天】随着业务的不断增长,单一的数据存储解决方案可能无法满足日益增加的数据处理需求。在大数据时代,数据库的性能、可扩展性和稳定性成为企业关注的重点。ClickHouse 是一个用于联机分析处理(OLAP)的列式数据库管理系统(DBMS),以其卓越的查询性能和高吞吐量而闻名。本文将从我的个人角度出发,分享如何将单节点 ClickHouse 扩展为高可用性的分布式集群,以提升系统的稳定性和可靠性。
103 0
|
2月前
|
存储 SQL 消息中间件
Hadoop-26 ZooKeeper集群 3台云服务器 基础概念简介与环境的配置使用 架构组成 分布式协调框架 Leader Follower Observer
Hadoop-26 ZooKeeper集群 3台云服务器 基础概念简介与环境的配置使用 架构组成 分布式协调框架 Leader Follower Observer
51 0
|
2月前
|
NoSQL Java Redis
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?
Redis分布式锁在高并发场景下是重要的技术手段,但其实现过程中常遇到五大深坑:**原子性问题**、**连接耗尽问题**、**锁过期问题**、**锁失效问题**以及**锁分段问题**。这些问题不仅影响系统的稳定性和性能,还可能导致数据不一致。尼恩在实际项目中总结了这些坑,并提供了详细的解决方案,包括使用Lua脚本保证原子性、设置合理的锁过期时间和使用看门狗机制、以及通过锁分段提升性能。这些经验和技巧对面试和实际开发都有很大帮助,值得深入学习和实践。
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?