目录

官网地址 https://zookeeper.apache.org/

概念

  • ​ZooKeeper 是分布式应用程序的分布式开源协调服务。命名空间的组织方式类似于标准文件系统,运行在JAVA环境中。

  • 数据保存在内存中,可实现高吞吐量和低延迟。

  • 内存中维护状态图像

zk_service

  • 数据模型和分层命名空间

分层命名空间

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

节点

  • 持久节点

    • Znode 维护一个统计结构,其中包括数据更改、ACL 更改和时间戳的版本号,存储在命名空间中每个 znode 的数据是原子读取和写入的
  • 临时节点

    • 只要创建 znode 的会话(session)处于活动状态,这些 znode 就存在。当会话结束时,znode 被删除。
  • 序列节点

    • create -s xx00000001 xx00000002

有条件的更新和监视

  • ZooKeeper支持 watch 的概念。客户端可以在 znode 上设置监视。当 znode 发生变化时,watch 将被触发并移除。当 watch 被触发时,客户端会收到一个数据包,说明 znode 已更改。如果客户端和其中一个 ZooKeeper 服务器之间的连接断开,客户端将收到本地通知。
  • **3.6.0 中的新功能:**客户端还可以在 znode 上设置永久的递归监视,这些监视在触发时不会被删除,并且会以递归方式触发已注册 znode 以及任何子 znode 上的更改。

保证

  • 顺序一致性 - 来自客户端的更新将按照它们发送的顺序应用。(写命令都转到leader节点)
  • 原子性 - 更新成功或失败。没有部分结果。
  • 单一系统映像 - 客户端将看到相同的服务视图,而不管它连接到的服务器如何。即,即使客户端故障转移到具有相同会话的不同服务器,客户端也永远不会看到系统的旧视图。
  • 可靠性 - 应用更新后,它将从那时起持续存在,直到客户端覆盖更新。
  • 及时性——系统的客户视图保证在一定的时间范围内是最新的。

API

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

执行

​ ZooKeeper 服务的每个服务器都复制自己的每个组件的副本

组件
  • 复制数据库是包含整个数据树的内存数据库。更新被记录到磁盘以便恢复,写入在应用到内存数据库之前被序列化到磁盘。

  • 每个 ZooKeeper 服务器都服务于客户端。客户端仅连接到一台服务器以提交请求。从每个服务器数据库的本地副本为读取请求提供服务。改变服务状态的请求,写请求,由协议协议处理。

  • 客户端所有写请求都转发由 leader 服务器处理。 ZooKeeper 服务器的其余部分,称为追随者,接收来自领导者的消息提议并同意消息传递。消息传递层负责在失败时替换领导者并将追随者与领导者同步。

  • ZooKeeper 使用自定义原子消息传递协议。由于消息传递层是原子的,ZooKeeper 可以保证本地副本永远不会发散。当领导者收到一个写请求时,它会计算系统在应用写时的状态,并将其转换为捕获这个新状态的事务。

安装笔记

zk集群至少 三台节点,少于三台集群将不可用
1.安装jdk,并设 JAVA_HOME 
2.下载 zookeeper https://zookeeper.apache.org/releases.html
3.解压后移动到/opt目bian
4.设置环境变量 ZOOKEEPER_HOME
5. cp zoo sample.cfg zoo.cfg
6. zoo.cfg 中	
	#服务心跳间隔 2秒
	tickTime = 2000 
	#初始化次数  最大允许等待 2000 * 10 = 20秒
	initLimit = 10  
	#主从同步次数   2000 * 5 = 10秒 未同步  认为失败
	syncLimit = 5   
	#持久化目录
	dataDir = /var/下   
	#客户端连接端口号
	clientPort=2181 
	#server.X的条目列出了组成 ZooKeeper 服务的服务器。
	#服务器启动时,通过在数据目录中查找文件myid来知道它是哪个服务器。该文件包含 ASCII 格式的服务器编号。
	#2888 追随者连接到领导者通信(有leader情况下) 
	#3888 投票选举leader(无leader)
	server.1=zoo1:2888:3888 
	server.2=zoo2:2888:3888
	server.3=zoo3:2888:3888
	
7. 启动
	zkServer.sh {start start-foreground stop restart status upgrade print-cmd}
8. 连接
	zkCli.sh --server ip:port
	> help
	create 无参 非顺序的也就是没有顺序的并且是持久化的 -e 创建临时节点 -s 顺序节点
			 
9. netstat -natp | egrep '(2888|3888)'
10. jps 查看zk 是否启动
11  zkServer.sh status 查看运行状态

observer 模式

​ 问题:随着添加更多投票成员,写入性能下降。因为写入操作需要(通常)集成中 至少一半节点 的协议,因此随着更多选民的加入,投票的成本会显着增加。

​ observer模式 不参与投票,只遵循投票结果 ,其余功能与追随者完全相同

配置文件中:
	peerType=observer
	server.1:localhost:2181:3181:observer

zookeeper全解析Paxos

​ 灵魂 基于消息传递的一致性算法

ZAB协议

  • 原子:成功 失败 没有中间状态(队列+2PC)

  • 广播:分布式节点的,不一定全部都知道

  • 队列:FIFO 顺序性

zk_zab

zookeeper选举过程

  1. 3888端口 两两通讯
  2. 只要任何人投票,都会触发那个准 leader发起自己的投票
  3. 推选制:先比较zxid,如果zXid相同,再比较myid

Watch

  • Created event: Enabled with a call to exists.

  • Deleted event: Enabled with a call to exists, getData, and getChildren.

  • Changed event: Enabled with a call to exists and getData.

  • Child event: Enabled with a call to getChildren.

zk_watch

使用场景

  1. 个客户端争抢锁,只有一个人能获得锁

  2. 获得锁的人出问题怎么办 ,可以用 临时节点( session)解决

  3. 获取锁的人怎么释放锁?锁被 释放 删除 别人怎么知道

    1. 主动轮询,心跳。。。弊端:延迟,压力

    2. watch:解决延迟问题。。弊端:压力(会唤醒所有客户端争抢锁, 惊群现象)

    3. 可使用 sequence +watch 序列节点

      watch谁呢? 每个序列节点 watch 前一个节点, 最小的节点先获取锁,最小节点是否锁后 只会回调下一个节点,避免了惊群现象!