Zookeeper
概述
- Zookeeper本身是一个树状结构 - Znode树
- 根节点是/
- 每一个子节点称之为是Znode节点
- 在Zookeeper中,每一个子节点都必须存储数据,这个数据往往是对这个节点的描述
- 所有节点的路径都必须从根节点开始计算
- 任意一个持久节点下都可以挂载子节点
- Znode树维系在内存以及磁盘中 - 在磁盘中的存储位置由dataDir决定
- 维系在内存中的目的:快速查询 维系在磁盘中的目的:崩溃恢复
- Zookeeper理论上可以作为缓存服务器使用,但是实际开发中几乎不这么做。Zookeeper本身是做分布式架构的管理和协调的,如果存储大量数据占用大量内存,就会导致管理和协调所能使用的资源减少
- Zookeeper会对每一次的写操作(create/set/delete/rmr)分配一个全局递增的编号,这个编号称之为事务id - Zxid
命令
命令 | 解释 |
ls / | 查看根节点的子节点 |
create /log 'log servers' | 在根节点下创建了一个子节点log,log的数据时"log servers" |
delete /video | 删除/video节点 - 要求这个节点没有子节点 |
rmr /log | 递归删除log节点 |
set /log 'log' | 更新log节点的数据为'log' |
get /log | 获取log节点的数据以及节点信息 |
create -e /node02 '' | 创建一个临时节点 |
create -s /log '' | 创建一个顺序节点logxxxxxx |
节点信息
属性 | 解释 |
cZxid | 创建事务id |
ctime | 创建时间 |
mZxid | 修改事务id |
mtime | 修改时间 |
pZxid | 子节点的事务变化id |
cversion | 子节点变化的次数 |
dataVersion | 数据版本。当前节点的更新次数 |
aclVersion | 当前节点的权限变化次数 |
ephemeralOwner | 标记当前节点是否是一个临时节点的 如果是持久节点,则该属性是0 如果是临时节点,则该属性是当前的sessionid |
dataLength | 数据的字节个数 |
numChildren | 子节点个数 |
节点类型
| 持久节点 | 临时节点 |
顺序节点 | Persistent_Sequential | Ephemeral_Sequential |
非顺序节点 | Persistent | Ephemeral |
选举机制
概述
- 第一个阶段:数据恢复阶段
每一个主机(节点)在启动之后,都会先查找当前主机(节点)中最大事务id
2. 第二个阶段:选举阶段
刚开始的时候,每一个节点都会选举自己当leader,并且将自己的选举信息发送给其他节点,和其他节点进行比较。经过多轮比较之后,会选出一个节点成为leader
选举的细节
观察者
- 观察者的特点:既不参与投票也不参与选举,但是监听投票和选举结果,然后根据结果来执行任务
- 适用场景:集群节点数量多的时候可以将一部分节点设置为观察者;网络条件不稳定的情况下,可以将部分节点设置为观察者
ZAB协议
概述:
- Zookeeper Atomic Broadcast - Zookeeper原子广播协议,是专门为Zookeeper设计的协议
- 这套协议在设计过程中,基于2PC算法来设计,利用PAXOS算法进行了改进
- 作用:原子广播和崩溃恢复
原子广播
- 原子广播是为了保证所有节点数据的一致性
- 原子广播基于2PC算法进行改进
- 2PC - 2 Phase Commit - 二阶段提交 - 核心思想是“一票否决”:
a: 分发阶段:协调者收到请求之后,将请求发送给每一个参与者,然后让参与者将这个请求进行记录
b: 提交阶段:如果每一个参与者都记录成功,并且协调者收到了所有参与者的成功信号,那么协调者就会要求所有 的参与者执行这个请求
c: 中止阶段:如果有一个或者多个参与者返回no,或者如果协调者没有收到参与者的返回信号,也会认为这个参与 者返回的是no,那么协调者救护认为这个请求不可执行,那么协调者就会要求所有的参与者删除这个请求的记录
4. 原子广播的过程
5. 如果某个follower记录失败,而又接收到leader要求执行的命令,这个时候follower就会向leader发送请求重新申请这个任务
崩溃恢复
- 当集群中的leader因为某些原因产生丢失,集群中会自动选举出一个新的leader,那么这个过程就称之为崩溃恢复
- 崩溃恢复是为了避免Zookeeper集群中出现单点故障
- 每选举出一个leader,就会给leader一个编号,这个编号称之为epochid。每一个leader都会将epochid发送给每一个follower,follower接收到epochid之后存储在acceptedEpoch中
- 每一个follower接收到请求之后,都会先比较epochid
- 在集群中,Zookeeper的事务id实际上是由64位二进制数字组成,其中高32位表示的是epochid,低32位才是真正的事务id
- 当一个节点重新连入集群之后,这个节点会拿着自己的事务id和当前集群中的事务id进行比较,在比较完成之后,leader就会将确实的操作放入一个队列中发送给这个节点。这个节点在更新过程中不对外服务
思考?
Zookeeper如何动态增删结点
Zookeeper的 容灾性