zookeeper和redis有很多东西是相通的,为什么zookeeper还能存活?请听我娓娓道来。
目录
问题7,为什么必须有leader,把提议交给leader发起?
一, 参考资料
1,官网
zookeeper.apache.org
https://zookeeper.apache.org/doc/current/zookeeperOver.html
3,马xx周老师的视频
致敬,每当我觉得自己学的很行的时候,总有人打我的脸,不过欢迎,查缺补漏,低调做人。
二, ZooKeeper 分布式开源协调服务
ZooKeeper 的设计目标之一是提供一个非常简单的编程接口。它公开了一组简单的原语,分布式应用程序可以基于这些原语来实现更高级别的同步、配置维护以及组和命名服务。它被设计为易于编程,并使用以熟悉的文件系统目录树结构为样式的数据模型。它在 Java 中运行,并且具有 Java 和 C 的绑定。
create : creates a node at a location in the tree
delete : deletes a node
exists : tests if a node exists at a location
get data : reads the data from a node
set data : writes data to a node
get children : retrieves a list of children of a node
sync : waits for data to be propagated
三, 设计目标
simple | 简单(API简单) |
replicated | 可复制(支持集群) |
ordered | 有序(序列节点) |
fast | 快速(读写分离,且恢复主时间快0.2秒) |
四, 特性/保证
1,官网解释
- 顺序一致性 - 来自客户端的更新将按发送顺序应用。(单点维护顺序是简单的)
- 原子性 - 更新要么成功要么失败。没有部分结果。
- 单一系统映像 - 无论连接到哪个服务器,客户端都将看到相同的服务视图。(统一视图)
- 可靠性 - 应用更新后,它将从那时起一直存在,直到客户端覆盖更新。(持久化的事务日志和快照)
- 及时性 - 系统的客户视图保证在特定时间范围内是最新的。(最终一致性)
2,分析和使用
快速 单机决策速度快,0.2秒恢复leader
扩展性
角色:leader,follower,observer
前两个是主从,observer 是只读(读写分离),为了平衡选举的速度和放大查询能力。
可靠性
快速恢复leader
数据的一致性(最终一致性)
最终一致性过程中,对外提供服务,脑裂怎么解决?
过半通过,一定有部分没有最新数据,可以通过sync
时序性
单点维护顺序是简单的, 有序节点。
五, 安装验证,集群搭建
六,根据特性分析可实现功能
(一)前情提要
特性
1,统一配置管理 存储1M数据
2,分组管理 path结构
3,统一命名 squential(临时有序)
4,同步 临时节点
(二)可实现功能
分布式锁(临时节点):创建临时节点,序号最小的获得
队列有事务的锁:同一目录下,按临时节点的序列来有序执行。(抢票)
(三)实际应用:
大数据的HA选主依赖zk,通过锁的方式选出主节点
负载均衡:kafka依赖zk,生产者通过监听zookeeper上Broker节点感知Broker,Topic的状态变更,来实现动态负载均衡机制
配置中心:通过监听实时更新配置
七,Paxos解读
以下是对Paxos的简化,作者能力有限,如果我说的不清楚,欢迎查看原帖。
(一)简单描述
Paxos基于消息传递的一致性算法。目前为止唯一的分布式一致性算法,其它算法都是对它的改进或简化。
1,信任通信环节;算法成立的基本条件
2,一个环境(集群)中,有一群居民(observer),议员(follower)选择总统(leader),议员的总数(参与选举的人越少,选举的效率越高)是确定的,处理法案的事情;
3,法案的编号是唯一的(操作的事务id),需要半数议员通过才能生效(过半通过);
4,每个议员只会同意大于当前编号的提议,包括已生效和为生效的;(分布式,可能会延迟收到信息)
5,收到小于等于当前编号的提议,会拒绝,并告知通知者;每个议员有自己的记事本,会不断更新这个编号(每个zk都有日志文件记录事务id);
6,只有总统能发起提议。
(二)运作流程
所有议员记事本初始编号都是0;
现在开始发起提议:自身编号+1,把1号提议发给所有议员;
当前编号是0,这个提议可以接收,记录提议并 回复同意;
当提出者收到半数以上回复后,立即发通知给所有人,1号提议提议成立。
(三)解决冲突
s1,s2,s3初始 : 编号都是0;
s1,s2 发起提议 :1号提议,s1房租+1,s2房租+2;
s3 收到回复 :先收到s1的提议;紧接着又收到s2的提议,但是s2的提议号等于它自己当前的提议号,拒绝;
结果 :s1提议生效,s2提议失败。
s2 如果想实现自己的提议怎么办? :向s1或者s3打听(sync )最新法令内容(ZNode及数据),然后发起2号提议。
(四)场景
情况一:(读和同步操作)
屁民甲(Client)到某个议员(ZK Server)那里询问(Get)某条法令的情况(ZNode的数据),议员毫不犹豫的拿出他的记事本(local storage),查阅法令并告诉他结果,同时声明:我的数据不一定是最新的。你想要最新的数据?没问题,等着,等我找总统Sync一下再告诉你。
情况二:(触发写操作)
屁民乙(Client)到某个议员(ZK Server)那里要求政府归还欠他的一万元钱,议员让他在办公室等着,自己将问题反映给了总统,总统询问所有议员的意见,多数议员表示欠屁民的钱一定要还,于是总统发表声明,从国库中拿出一万元还债,国库总资产由100万变成99万。屁民乙拿到钱回去了(Client函数返回)。
情况三:(三台的集群,leader挂了,只有两台机器,选不出leader,集群无法使用)
总统(leader)突然挂了,议员(ZK Server)接二连三的发现联系不上总统,于是各自发表声明,推选新的总统,总统大选期间政府停业,拒绝屁民的请求。
八,ZAB
Zab借鉴了Paxos算法,是特别为Zookeeper设计的支持崩溃恢复的原子广播协议。基于该协议,zk实现了一种主备模型(即Leader和Follower模型)的系统架构来保证集群中各个副本之间数据的一致性。这里的主备系统架构模型,就是指只有一台客户端(Leader)负责处理外部的写事务请求,然后Leader客户端将数据同步到其他Follower节点。
zk原子广播协议,是Paxos的精简版。
原子:成功;失败。没有中间态
广播:分布式多节点,不代表全部知道。(UTP:不确定每人能收到)
队列:FIFO,先进先出,顺序性
内存:存放数据状态
磁盘:存放日志
九,选举机制
(一)选举机制(谦让制)的规则
1,3888两两通讯(任何模型可以和其他任何节点通讯);
2,任何人都会给自己投1票;
3,推举制:先比较zxid,再比较myid;
4,过半通过的数据才是真实数据,zxid只要存在就是真实存在的(可能会不是最新的);
5,发起投票的通讯会触发接收者发起投票;
6,过半通过超过n/2+1。
(二)实际过程解读
在上述图上加入节点node04,且这时node03挂掉,那么推举有两种情况,结果如下:
1,如果zxzid事务id没有变化,主挂掉之后,永远是myid最大的node04是leader。
2,如果原集群有事务操作,那么选举的结果是node02。
描述上述第二个过程
第一次通讯:node04先给自己投一票,node04 连接node01:对比(zxid,myid)后node01后,回执的触发node01发起node04的投票,node04给node01投1票,
node01 | node02 | node04 | |
node01 | 1 | 0 | 1 |
node02 | 0 | 0 | 0 |
node04 | 0 | 0 | 1 |
node01:2票 ;node02:0票 ; node04:1票
第二次通讯:node04 连接node02:对比(zxid,myid)后node01后,回执的触发node01发起node04的投票,node04给node02投1票,
node01 | node02 | node04 | |
node01 | 1 | 0 | 1 |
node02 | 1 | 0 | 1 |
node04 | 0 | 0 | 1 |
node01:2票 ;node02:2票 ; node04:1票
第三次通讯:node02连接node01:对比(zxid,myid)后node01后,回执的同时触发node01发起node02的投票,node01给node02投1票,这时*node02记录的是自己3票,过半(超过n/2+1),随机开启2888端口并发起广播,新的纪元开始了。
node01 | node02 | node04 | |
node01 | 1 | 0 | 1 |
node02 | 1 | 1 | 1 |
node04 | 0 | 0 | 1 |
node01:2票 ;node02:3票 ; node04:1票
有人问,每次一定是node02么,不一定的,这个是根据先zxid后myid比较大小决定的,myid就像人为指定的序列:就像公司里,职员A比职员B来的早,但是职员B经历的项目多经验更丰富(zxid),就可以更好的担任领导职务。
十,WATCH(基于观察者模式的监控)
(一)watch与健康检测(心跳)
健康检测:需要心跳验证,频繁的去按指定的时间去查看对方是否存活;且双方都需实现心跳验证。
watch:通过临时节点+session,当目标宕机后,会触发回调函数,立即通知观察者;
watch的失效性更高(心跳有时间间隔,延迟,如果是多台呢?成本是巨大的),并且没有方向性(心跳是单向的)
十一, 问题
问题1:单点的,如何维持高可用?
leader单点故障-->服务不可用-->不可靠
但是zk说它自己是可靠且高可用的。那么一定有一种方式可以快速回复出一个leader来维持其高可用。
以下是官网提供:
1,性能
运行一个由 7 台机器组成的 ZooKeeper 服务。我们运行了与之前相同的饱和基准测试,但这次我们将写入百分比保持在 30% 不变,这是我们预期工作负载的保守比例。
3台的集群服务能支撑8万的并发
2,可靠性
响应各种故障
- 跟随者的失败和恢复
- 不同follower的故障和恢复
- 领导者的失败
- 两个follower的故障与恢复
- 另一个领导者的失败
每秒4-5W的并发
首先,ZooKeeper 能够维持高吞吐量。
其次,花费不到 200 毫秒恢复leader。
最后,恢复就能够再次提高吞吐量。
ZooKeeper 的性能方面意味着它可以用于大型分布式系统。可靠性方面使其不会成为单点故障。严格的排序意味着可以在客户端实现复杂的同步原语。
问题2:能做数据库用么?
ZooKeeper 旨在存储协调数据:状态信息、配置、位置信息等,因此每个节点存储的数据通常很小,在字节到千字节范围内。
ZooKeeper 应用程序在数千台机器上运行,它在读取比写入更常见的情况下表现最佳,比率约为 10:1。
它支持,但不要,例如:一个资深的架构师可以胜任测试,运维,开发的工作,但这样不会发挥他最大的作用。
节点建议是1M以内,并不是说它只能存这么多数据;
最佳读写比例10:1。
问题3:zk实现分布式锁为什么比redis简单?
zk 的session = redis nx + 过期时间+client多线程过期时间
redis : nx + 过期时间+多线程,客户端会引出多线程,提高复杂度,更新过期时间。
zk : 当client连接到zk会产生一个session(会话)来代表client,session有创建和消亡的概念,临时节点Client存活则session存在,client挂了session也会消失。可以使用顺序节点,通过监听回调方法来逐个实现功能。
zk实现分布式锁比redis实现更简单,可用性更高,代价更小。稍微改动下还能实现有事务的分布式队列。
问题4,如何使用observer?
配置zoo.cfg中添加observer
server.x=node0x:2888:3888 observer
问题5,最终一致性过程中,对外提供服务,脑裂怎么解决?
过半通过,一定有部分没有最新数据,可以通过sync
问题6,zk为什么要分两阶段?
(1),写日志,过半通过;(2),提议成立。为了解决分布式通信中比较麻烦的事情,确保过半通过后,提议成交。
问题7,为什么必须有leader,把提议交给leader发起?
如果s1,s2,s3 都同时发起提议,票数都一致为1,那么都通过不了(大于自身编号的提议生效),永不过半。
问题8,总统是怎么选出来的?
选举机制,zk的ZAB协议
预知后事如何,且听下会分解
用API分别展示watch,CALLBACK,zk实现的一些功能,包括:分布式锁,多进程下队列有事务的锁,注册与发现。
总结:分别说下zookeeper和redis的一些共性和侧重点。