ZooKeeper 是一个开源的分布式协调服务。它是一个为分布式应用提供一致性服务的软件,分布式应用程序可以基于 Zookeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。
ZooKeeper 的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
Zookeeper Service集群是一主多从结构。
存储数据时,zookeeper 使用树形结构,其中的每个节点称作 ZNode,访问一个 ZNode 时,需要提供从 root 开始的绝对路径。
每个 ZNode 可以存储最多 1MB 的数据,用户可以:
用户可以对一个 ZNode 设置 watch,当这个 ZNode 发生了变化时,例如 创建、删除、数据变更、添加或移除子节点,watch API 就会发出通知,这是 zookeeper 非常重要的功能。
zookeeper 的 watch 有一个缺点,就是这个 watch 只能被触发一次,一旦发出了通知,如果还想对这个节点继续 watch,用户需要重新设置 watch。
初始化数据 -> leader选举 -> 发现阶段-> 数据同步
ZAB协议所定义的三种节点状态:
ZooKeeper对Zab协议的实现有自己的主备模型,即Leader和learner(Observer + Follower),有如下几种情况需要进行领导者的选举工作
有几个概念我们需要知道:
epoch:投票纪元,每个节点都会保存自己的epoch,每进行一次选举,这个值便会加一。
zxid:事务id,它是一个 64 位的 数字,它高32位是epoch,低32位用于递增计数。
myid:搭建集群时,需要为每个zk服务器配置全局唯一的myid。
vote:虚拟概念,可以想成节点投出去的票,格式为(myid,zxid),这个myid指的是任意节点的myid。
选举规则:首先比较zxid,优先选择zxid大的,若zxid相同则比较myid,选择myid大的。当集群中有超过半数的票都投给了同一个节点,那么这个节点就会成为leader,然后进入数据同步阶段。为什么要超过半数同意,如果是半数同意就可以成为leader会怎么样?
假设当前集群中有5个机器分别为1(1,2),2(2,3),3(3,3),4(4,1),5(5,3)号机器。
①每一个节点在进入选举流程时会首先投票给自己,例如myid为1,zxid为2的节点(1号机器)在进入选举流程时会投出第一张票(1,2),同理myid为2,zxid为3的节点(2号机器)会投出(2,3),并且每个节点会将这张选票发给集群中所有的节点。
②每个节点都会接收到其他节点发来的选票,1号机器会收到(2,3),然后进行比较,自己当前的投票为(1,2),所以会将自己的投票改为(2,3),然后将(2,3)再发送给集群中的其他节点。2号机器同理。
我们按照机器加入顺序分别为:1,2,3,5,4 来分析整个选举的流程
数据同步阶段:从节点将主节点的数据同步过来,使各个节点的数据都与主节点的相同,当集群中超过半数的从节点都完成数据同步后集群就可以对外提供服务了。
Zookeeper集群是一主多从,即只有主节点(leader)可以执行写请求,从节点(follower)和observer(不能参与选举)只能执行读请求,当一个客户端发送写请求时,会进行如下流程:
只有当leader接收到超过集群半数的ack时才会在本地commit,然后将commit广播给所有的follower。
这是雅虎研究员设计Zookeeper的初衷。利用Zookeeper的临时顺序节点,可以轻松实现分布式锁。
利用Znode和Watcher,可以实现分布式服务的注册和发现。最著名的应用就是阿里的分布式RPC框架Dubbo。
Redis的分布式解决方案Codis,就利用了Zookeeper来存放数据路由表和 codis-proxy 节点的元信息。同时 codis-config 发起的命令都会通过 ZooKeeper 同步到各个存活的 codis-proxy。
此外,Kafka、HBase、Hadoop,也都依靠Zookeeper同步节点信息,实现高可用。
指在一个高可用(HA)系统中,当联系着的两个节点断开联系时,本来为一个整体的系统,分裂为两个独立节点,这时两个节点开始争抢共享资源,结果会导致系统混乱,数据损坏。