Zookeeper是啥?
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
ZooKeeper包含一个简单的原语集,提供Java和C的接口。
ZooKeeper代码版本中,提供了分布式独享锁、选举、队列的接口,代码在$zookeeper_home\src\recipes。其中分布锁和队列有Java和C两个版本,选举只有Java版本。(来自百度百科)
ZooKeeper 是一个典型的分布式数据一致性解决方案,分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。
角色
角色 | 描述 |
---|---|
Leader | 响应写请求,负责发起投票和决议,更新系统状态 |
Follower | 1、响应读请求,向client返回数据 2、响应client写请求,把请求转发到Leader; 3、参与投票 |
Observer | 1、响应读请求,向client返回数据 2、响应client写请求,把请求转发到Leader;(不参与投票,目的是为了扩展系统,提升读速度) |
Client | 请求客户端 |
状态 | 描述 |
---|---|
Looking | 当前Server不知道leader是谁,正在搜寻 |
Leading | 当前Server即为选举出来的leader |
Following | leader已经选举出来,当前Server与之同步 ,并参与投票 |
Observing | leader已经选举出来,当前Server与之同步,不参与投票 |
zNode
zNode类型
zNode类型 | 描述 |
---|---|
持久节点 | 客户端断开连接后仍然保持 |
临时节点 | 客户端断开连接后,zNode删除(-e 参数) |
持久顺序节点 | 自动递增生成32位顺序标志,客户端断开连接后仍然存在 (-s 参数) |
临时顺序节点 | 自动递增生成32位顺序标志,客户端断开连接后删除 (-e -s参数) |
zNode结构
3个zxid、3个version(cVersion、dataVersion、修改时进行CAS验证)
字段 | 描述 |
---|---|
cTime | 节点创建时间 |
mTime | 最新修改时间,若对此节点进行数据修改会刷新 |
cZxid | 节点创建时zookeeper事务ID(Zxid=zookeeper Transication id,由Leader生成的全局唯一标志,64位,前32位为Leader标志,后32位为递增序列) |
mZxid | 最新修改事务ID,若对此节点进行数据修改会刷新 |
pZxid | 最新修改子节点事务ID,若此节点的子节点发生变更则会刷新 |
cVersion | 子节点变更版本,每次修改自增1 |
dataVersion | 数据版本,每次修改自增1 |
acLVersion | 权限变更版本,每次修改自增1 |
ephemeralOwner | 创建该临时节点的会话的sessionID。(如果该节点是持久节点,那么这个属性值为0) |
dataLength | 该节点的数据长度 |
numChildren | 直接子节点的数量 |
CAP原则
C:一致性
A:可用性
P:分区容错性
CAP原则就是这三个特性,最多只能同时满足两个。
Zookeeper更倾向与C与P。
why?
答:Zookeeper的投票写入机制:只有超过半数的server投票后才写入(如果一共有5台服务器,则必须有3台或以上投票),即使发生脑裂,成功写入的已经超过半数投票,能够保证恢复分区后,重新加入集群的机器只需要按序同步即可。而在脑裂后的选举期间,Zookeeper是不可用的,而且若剩余的有效机器不足一半以上,Zookeeper也无法写入,不满足可用性。
写请求流程
Client请求Follower => Follower转发请求(REQUEST消息)到Leader => Leader发起投票,广播提案到各Follower(PROPOSAL消息)=> Follower回复投票(ACK消息) => Leader判断超过半数投票,写入变更,广播通知(Commit消息)各Follower写入,并返回成功
消息类型 | 描述 |
---|---|
PING消息 | 心跳消息,Leader与Follower之间维持心跳 |
REQUST消息 | Follower转发到Leader的写入请求 |
PROPOSAL消息 | Follower接收写入请求后发起投票的消息 |
ACK消息 | Follower接受到投票请求后回复Follower的消息 |
COMMIT消息 | 服务器端写入最新一次提案的信息; |
SYNC消息 | 强制同步消息 |
选举
选举优先级
优先级:ServerID < zxid < selectionEpoch
ServerID:是值服务器ID
zxid: 是指服务器当前最新的写入数据事务ID
selectionEpoch:是指当前服务器参与选举投票的次数
(选举结果跟参与投票顺序有关系)
例子:
ServerA——ID:1 zXid:1 selectionEpoch:1
ServerB——ID:2 zXid:1 selectionEpoch:2
ServerC——ID:3 zXid:1 selectionEpoch:1
若:
ServerB、ServerC同时挂掉,那么ServerA则会变成Looking状态
1、当ServerB先启动加入集群,则A发现B的selectionEpoch比A大,所有把自己的票投给B,而且B投票给自己,此时已经大于半数(2>1),B成为Leader,后面C再加入时只能作文Follower
2、当ServerC先启动加入集群,则A发现C的ServerID比A大,所有把自己的票投给C,而且C投票给自己,此时已经大于半数(2>1),C成为Leader,即使B启动后selectionEpoch比C大,由于C已经是Leader,所以B只能是Follower
选举算法
FastLeaderElection:
(选自己 => 广播 => 回复 => 更新结果(收到其他server投票信息,根据优先级更新) => 超过半数当选)
⬆–<--<–<--<–<--<–<--<–<--<—<–<--<–<--<–<--<–⬇
使用场景
- 数据发布/订阅(使用watcher机制)
- 负载均衡——在zk中注册服务器列表节点,根据算法负载均衡
- 命名服务——利用顺序节点生成分布式唯一ID
- 分布式协调、心跳检测——利用临时节点特性,每个服务作为客户端注册临时节点,若节点消失则说明断链
- Mster选举——利用节点ID不可重复特性,各个实例并发向Zk发起写master临时节点请求,成功者为master;其他服务器对master节点注册删除事件watcher,若master删除,则重新发起选举请求。
- 分布式读写锁——利用顺序节点+watcher;写锁——注册事件监听比自己小的最后一个锁请求;读锁——监听比自己小的最后一个写锁请求
- 分布式队列——利用顺序节点,监听ID比自己小的最后一个请求。