Zookeeper

微服务架构解决方案 Spring Boot + Dubbo + Zookeeper

Zookeeper

分布式协调框架,实现分布式锁
ZooKeeper 将数据保存在内存中,性能是非常棒

Zookeeper数据模型

  • Zookeeper 提供了一个类似于 Linux 文件系统的树形结构,
  • 最上层是根节点以“/”来代表
  • 每个节点还可以拥有 N 个子节点
  • 提供了对于每个节点的监控与通知机制

Zookeeper 的这种节点叫做 Znode, 每个节点的数据最大不能超过 1MB, 每一个 Znode 节点拥有唯一的路径

在这里插入图片描述

Znode节点

在这里插入图片描述

  1. stat:包含 Znode 的各种元数据,比如事务 ID、版本号、时间戳、大小等等。
  2. data:Znode 存储的数据信息。可以是数字、字符串或者是二级制序列。
  3. ACL:记录 Znode 的访问权限,即哪些人或哪些 IP 可以访问本节点。
  4. child:当前节点的子节点引用
节点类型

在这里插入图片描述
顺序节点 保证znode路径将是唯一的, ZooKeeper集合将向znode路径填充10位序列号

stat

Stat 中记录了这个 znode 的三个相关的版本:

  1. dataVersion :当前 znode 节点的版本号
  2. cversion : 当前 znode 子节点的版本
  3. aclVersion : 当前 znode 的 ACL 的版本。
ACL权限设置

对于 znode 操作的权限,ZooKeeper 提供了以下 5 种:

  1. READ :能获取节点数据和列出其子节点
  2. WRITE : 能设置/更新节点数据
  3. ADMIN : 能设置节点 ACL 的权限
  4. CREATE : 能创建子节点
  5. DELETE : 能删除子节点

对于身份认证,提供了以下几种方式:

  1. world : 默认方式,所有用户都可无条件访问。
  2. auth :不使用任何 id,代表任何已认证的用户。
  3. digest :用户名:密码认证方式: username:password 。
  4. ip : 对指定 ip 进行限制。

事件通知Watch

可以把Watch 理解成是注册在特定 Znode 上的触发器。在一些特定事件触发的时候,ZooKeeper 服务端会将事件通知到感兴趣的客户端上去

znode相关的数据的修改或znode的子项中的更改。只触发一次watches。 如果客户端想要再次通知,则必须通过另一个读取操作来完成。当连接会话过期时,客户端将与服务器断开连接,相关的watches也将被删除。
在这里插入图片描述
使用场景:

  1. 服务端在 ZooKeeper 创建一个Znode, 包含服务端的ip、访问方式。把服务端注册在zookeeper
  2. Zookeeper 客户端在请求读操作的时候,选择设置 Watch 。

    比如调用 getData 方法,watch 参数是 true。

  3. Zookeeper 接到请求,返回节点数据,并且在对应的哈希表里插入被 Watch 的 Znode 路径,以及 Watcher 列表。此时这个 Znode 就被客户端 watch
  4. 当这个 Znode 发生写操作,也就是调用了 create,delete,setData 方法的时候,将会触发 Znode 上注册的对应事件,请求 Watch 的客户端会接收到异步通知。

Zookeeper 集群

为了防止单机挂掉的情况,Zookeeper 维护了一个集群Zookeeper Service
Zookeeper Service 集群是一主多从结构。集群为大于等于3的奇数
在这里插入图片描述

  • 在更新数据时,首先更新到主节点(这里的节点是指服务器,不是 Znode),再同步到从节点。
  • 在读取数据时,直接读取任意从节点。

为了保证主从节点的数据一致性,Zookeeper 采用了 ZAB 协议,这种协议非常类似于一致性算法 Paxos 和 Raft。

ZAB 协议

Zookeeper Atomic Broadcast,解决 Zookeeper 集群崩溃恢复主从同步数据的问题

集群崩溃恢复
  • ZAB 协议定义的三种 Server节点状态

    1. Election/Looking :选举状态,寻找 Leader。
    2. Following :Follower 节点(从节点)所处的状态。
    3. Leading :Leader 节点(主节点)所处状态。
    4. 代码实现中,多了一种:Observing 状态
      这是 Zookeeper 引入 Observer 之后加入的,Observer 不参与选举,是只读节点,跟 Zab 协议没有关系。
      在这里插入图片描述
  • Zab 选举的四个阶段

    1. 选举阶段 Leader election
      正常情况 Server主节点是Leading,从节点的是Following
      没有Leading的时候,所以节点都变为Looking,然后会把数据最新节点的选举准 Leader状态变为 Leading,其他节点的状态变为 Following
    2. 发现阶段 Discovery
      followers 跟准 leader 进行通信,同步 followers 最近接收的事务提议。
      接收所有 Follower 发来各自的最新 epoch 值。准Leader 从中选出最大的 epoch,基于此值加 1,生成新的 epoch 分发给各个 Follower。
    3. 同步阶段 Synchronization
      防止产生多个 Leader ,当半数 Follower 同步成功,这个准 Leader 才能成为正式的 Leader。
    4. 广播阶段 Broadcast
      到了这个阶段,ZooKeeper 集群才能正式对外提供事务服务
主从同步数据

Zookeeper 常规情况下更新数据:

  1. 客户端发出写入数据请求给任意 Follower。
  2. Follower 把写入数据请求转发给 Leader。
  3. Leader 采用二阶段提交方式,先发送 Propose 广播给 Follower
  4. Follower 接到 Propose 消息,写入日志成功后,返回 ACK 消息给 Leader。
  5. Leader 接到半数以上ACK消息,返回成功给客户端,并且广播 Commit 请求给 Follower

部署

  • 模式

    • 单机模式:存在单点故障
    • 集群模式:在多台机器上部署 Zookeeper 集群,适合线上环境使用。
    • 伪集群模式:在一台机器同时运行多个 Zookeeper 实例,仍然有单点故障问题,当然,其中配置的端口号要错开的,适合实验环境模拟集群使用
  • 端口

    • 2181:客户端连接 Zookeeper 集群使用的监听端口号
    • 3888:选举 leader 使用
    • 2888:集群内机器通讯使用(Leader 和 Follower 之间数据同步使用的端口号,Leader 监听此端口)
  • 配置文件路径:/conf/zoo.cfg

clientPort=2181 			#客户端连接 Zookeeper 服务器的端口
dataDir=/data				#数据目录
dataLogDir=/datalog			#日志目录
tickTime=2000				#客心跳检测时间间隔
initLimit=5					#Leader 与 Follower 服务器心跳时间间隔数 tickTime*initLimit
syncLimit=2					#Leader 与 Follower 请求和应答时间长度 tickTime*syncLimit
autopurge.snapRetainCount=3	#定时清理需要保留的文件数目
autopurge.purgeInterval=0	#定时清理频率
maxClientCnxns=60			#限制连接到 Zookeeper 的客户端的数量
server.1=192.168.0.1:2888:3888	#集群节点1的 ip:集群通讯端口:选举端口
server.2=192.168.0.2:2888:3888	#集群节点2
server.3=192.168.0.3:2888:3888	#集群节点3

CLI命令行操作

  • ZooKeeper服务器(“bin/zkServer.sh start”)
  • ZooKeeper客户端(“bin/zkCli.sh”)

创建节点:create

语法:
create /path /data
create /parent/path/subnode/path /data
案例:

[zk: localhost:2181(CONNECTED) 0]  create /FirstZnode"node1"
创建顺序节点 -s

create -s /path /data

[zk: localhost:2181(CONNECTED) 2] create -s /FirstZnode "node2"
Created /FirstZnode0000000001
创建临时节点 -e

create -e /path /data

检查状态

znode的元数据。它包含时间戳,版本号,ACL,数据长度和子znode等细项
stat /path

列出子项 ls

ls /path

获取节点的数据:getData

返回znode的关联数据和指定znode的元数据
get /path

get /FirstZnode
get /FirstZnode0000000001
获取并监听节点

get /path [watch] 1

get /FirstZnode 1

删除节点:delete

rmr /path

设置节点数据:setData

set /path /data

  • 读操作 exists,getData,getChildren
  • 写操作 create,delete,setData

java API

Java和C有的官方API
其他语言(.NET,python等)也有提供非官方API

  • connect - 连接到ZooKeeper集合
ZooKeeper(String connectionString, int sessionTimeout, Watcher watcher)
  • create- 创建znode
create(String path, byte[] data, List<ACL> acl, CreateMode createMode)
  • exists- 检查znode是否存在及其信息
exists(String path, boolean watcher)
  • getData - 从特定的znode获取数据
getData(String path, Watcher watcher, Stat stat)
  • setData - 在特定的znode中设置数据
setData(String path, byte[] data, int version)
  • getChildren - 获取特定znode中的所有子节点
getChildren(String path, Watcher watcher)
  • delete - 删除特定的znode及其所有子项
delete(String path, int version)
  • close - 关闭连接

应用场景

分布式锁

这是雅虎研究员设计 Zookeeper 的初衷。利用 Zookeeper 的临时顺序节点,可以轻松实现分布式锁。

  • 方法1

    1. A 发现没有临时节点, 则创建临时节点 获取锁
    2. 后续B, C,D… 发现已有临时节点 , 则watch它排队等待
    3. A释放锁之后 , 通知后一个排队的对象, 后续同上
  • 方法2

    1. A创建临时顺序节点 0000001, 发现自己是最小的节点, 则获取锁
    2. B创建临时顺序节点 0000002, 发现前面有更小的节点则watch 0000001
    3. C创建临时顺序节点 0000003, 发现前面有更小的节点则watch 0000002
  • 对比Redis
    Zookeeper 使用简单,添加和删除节点性能比 Redis 性能低
    Redis 使用复杂(要考虑超时,误删,原子性),性能高,没有等待锁队列只能客户端不断自旋锁

服务注册和发现

利用 Znode 和 Watcher,可以实现分布式服务的注册和发现。最著名的应用就是阿里的分布式 RPC 框架 Dubbo。

共享配置和状态信息

Redis 的分布式解决方案 Codis,就利用了 Zookeeper 来存放数据路由表和 codis-proxy 节点的元信息。同时 codis-config 发起的命令都会通过 ZooKeeper 同步到各个存活的 codis-proxy。

此外,Kafka、HBase、Hadoop,也都依靠Zookeeper同步节点信息,实现高可用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值