分布式应用程序可以基于 Zookeeper 实现诸如数据发布/订阅、负载均衡、命名
服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。
Zookeeper 一个最常用的使用场景就是用于担任服务生产者和服务消费者的注册中心(提供发布订阅服务)。 服务生产者将自己提供的服务注册到Zookeeper中心,服务的消费者在进行服务调用的时候先到Zookeeper中查找服务,获取到服务生产者的详细信息之后,再去调用服务生产者的内容与数据。如下图所示,在 Dubbo架构中 Zookeeper 就担任了注册中心这一角色。
zookeeper保证了如下分布式一致性特性:
1.顺序一致性 2.原子性 3.单一视图 4.可靠性 5.实时性
ZAB协议
ZAB 协议是为分布式协调服务 Zookeeper 专门设计的一种支持崩溃恢复的原子广播协议。
ZAB协议的两种模式:崩溃恢复和消息广播
消息广播:leader将请求广播出去,让Leader问问Followers是否同意更新,超过半数同意,就可以进行follower和observe的更新。用图来标示一下。
队列需要让follower和observe保证顺序性
崩溃恢复:
选举算法---第一阶段:宕机重新选举 ;第二阶段:当zookeeper启动需要进行系统的Leader初始化选择。
假设有三台,启动server1,投票给自己,内容为服务器的myid和ZXID,因为初始化ZXID都是0,server1的发出的投票为(1,0),server1投票为1,不能为leader,此时为looking状态,
server2投票为(2,0),广播出去(server1也会,只是当时没有其他服务器),server1收到后和自己比较,先比较ZXID,ZXID大的为Leader,若相同,比较myid,myid大的为Leader。此时server1发现server2更适合,如更新自己的投票信息为(2,0)然后广播出去。server2收到后,和自己一样不更新,且已经超多一般的票数,则server2是Leader,server1是Follower。整个服务器从Looking变成正常状态。
server3启动发现句群没有Looking,直接以Follower的身份加入的集群。
四种类型的节点
1.持久节点 2.临时节点 3.持久顺序节点 4.临时顺序节点
可为节点添加一个属性--SEQUENTIAL,加上属性后,在被创建时,zookeeper会给节点追加一个数字。
这个数字有父节点维护的自增数字。
数据变更通知 Zookeeper Watcher
最好用奇数台构成集群
会话 Session
在Zookeeper中,一个客户端连接是指客户端和服务器之间的一个TCP长连接。通过连接,客户端通过心跳与服务器保持连接。
Znode
通常我们所说的节点是指组成集群的每台机器。然而,在zookeeper中,节点分两种
第一类:指构成集群的机器,称之为机器节点
第二类:指数据模型中的数据单元,称之为数据节点-ZNode
znode三个数据版本:version(当前的ZNode版本),cversion(当前ZNode子节点的版本)和aversion(当前ZNode的ACL版本)
ACL权限控制机制
zookeeper五种权限,CREATE和DELETE这两种权限都是针对子节点的权限控制
顺序访问
zookeeper集群角色
最典型集群模式: Master/Slave 模式(主备模式)
在 ZooKeeper 中
没有选择传统的 Master/Slave 概念,而是引入了Leader、Follower 和 Observer 三种角色
ZAB协议
ZAB(ZooKeeper Atomic Broadcast 原子广播) 协议是为分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的原子广播协议。主要依赖 ZAB 协议来实现分布式数据一致性。
两种模式:崩溃恢复和消息广播
服务器角色
Leader 1.事务请求的唯一调度和处理者,保证集群事务处理的顺序性 2.集群内部各服务的调度着
Follower:1.处理费非事务请求,转发事务请求给Leader服务器 2参与事务请求Proposal的投票 3.参与leader选举投票
Observer:提升非集群的非事务处理能力,处理客户端的非事务请求,转发事务请求给Leader服务器。不参与任何形式的投票
服务器四种状态:LOOKING,FOLLOWING,LEADING,OBSERVING
zookeeper的数据同步通常为四类
直接差异同步DIFF
先回滚在差异化同步 TRUNC+DIFF
仅回滚同步TRUNC
全量同步 SNAP
部署模式:
单机模式,为集群模式,集群模式
集群规则为:2N+1台,N>0,即3台。
能支持动态添加吗?
不太好,能添加。两种方式:
全部重启,逐个重启。 3.5版本后支持动态扩容。
zookeeper对节点的监听不是永久的。
常用命令:ls,get,set,create,delete等
ZAB和Pacos算法的联系和区别
基于zk的实现:数据存储,数据获取,数据变更
负载均衡
集群管理:是否有及其退出和加入,选举master
zk分布式锁
一致性文件系统,锁分两类:保持独占,控制时序
zk队列
同步队列:当一个队列的所有成员聚齐,才能使用,否则一直等待。
对待按照FIFO方式入队和出队操作。
一致性协议和算法
拜占庭将军:在不可靠信道上试图通过消息传递的方式达到一致性是不可能得。
2PC
角色:协调者,参与者
事务发起者向协调者发送事务,协调者给所有参与者发送prepare请求,若能执行,就先执行不提交。执行后给协调者返回prepare消息,告诉协调者是否准备好进行提交。
当所有的参与者都返回准备好了的消息,协调者会给参与者发送Commit请求,参与者收到请求后会执行前面事务的提交操作,提交完毕之后给协调者发送提交成功的响应。
2pc带来的问题:
单点登陆:协调者宕机,全部不可用。
阻塞问题:即协调者发送prepare请求,参与者受到之后,会进行事务处理,但不及提交,此时会占用资源不释放。如果此时协调者挂了,资源不会释放,这会极大影响性能。
数据不一致:如果第二阶段,协调者只发送了一部分的commit请求就挂了,那么收到的参与者进行事务的提交,而后面没收到的则不会进行事务提交,此时就会进行数据不一致。
3PC
CanCommit阶段:协调者向所有的参与者发送CanCommit请求,参与者根据自身返回是否能执行事务,如果返回yes进入预备状态,都在返回NO。
PreCommit阶段:协调者根据参与者返回响应来判断是否可以进行下面的PreCommit操作。如果上面的参与者返回的都是YES,那么协调者将向所有的参与者发送PreCommit预提交请求,参与者收到预提交请求后,会进行事务的执行操作,将Undo和Redo信息写入事务日志。若参与者顺利执行,则给协调者返回成功的响应。
如果在第一阶段协调者收到任何一个no,或者在一定时间内没有收到全部参与者的成功响应,那么就会中断事务,他会向参与者发送中断请求。参与者会立即中断事务,在一定时间没有收到协调者的请求,他也会中断事务。
DoCommit阶段,这个阶段其实和2pc的第二阶段差不多,如果协调者收到所有的参与者在PreCommit阶段的YES响应,协调者将会给所有的参与者发送DoCommit请求,参与者受到DoCommit请求后则会进行事务的提交工作。完成后则会给协调者返回响应。协调者收到所有参与者返回的事务提交成功的响应之后完成事务。若协调者的precommit阶段收到任何一个no或者在一定时间内没有收到参与者的响应,那么就会进行中断请求的的发送,参与者受到中断请回后通过日志进行回滚。并向协调者反馈回滚状态。
Paxos算法 --解决数据一致性问题
基于消息传递且具有高度容错特性的一致性算法,其解决的问题是分布式系统中如何就某个值达成一致。
角色:proposer提案者、Acceptor表决者、Learner学习者。Paxos算法和2pc一致,
也有两个阶段:分别为Prepare和accept阶段。
Proposer提案者:负责提出 proposal
,每个提案者在提出提案时都会首先获取到一个 具有全局唯一性的、递增的提案编号N,即在整个集群中是唯一的编号 N,然后将该编号赋予其要提出的提案,在第一阶段是只将提案编号发送给所有的表决者。
Acceptor表决者:每个表决者在accept某提案后,会将提案编号N记录在本地,这样在每个表决者中保存的已经在accept的提案中会存在一个编号最大的提案。每个表决者仅会accept编号大于自己本地的提案。在批准提案时表决者会将以前接收的自大编号的提案给提案者。
Prepare阶段:
当提案被提出时,如果提案者收到了超过半数的表决者的同一,那就就会给所有的表决者发送真正的提案,这个时候,Proposer就会发送提案内容和编号。
表决者收到提案后,会和自身比较已经批准过得最大提案的编号和该提案编号,如果该提案编号大于已经批准过得提案编号,就accept该提案(执行不提交),随后返回proposer,如果不行不返回,或者返回no。
accept阶段
当 Proposer
收到超过半数的 accept
,那么它这个时候会向所有的 acceptor
发送提案的提交请求。需要注意的是,因为上述仅仅是超过半数的 acceptor
批准执行了该提案内容,其他没有批准的并没有执行该提案内容,所以这个时候需要向未批准的 acceptor
发送提案内容和提案编号并让它无条件执行和提交,而对于前面已经批准过该提案的 acceptor
来说 仅仅需要发送该提案的编号 ,让 acceptor
执行提交就行了。
而如果 Proposer
如果没有收到超过半数的 accept
那么它将会将 递增 该 Proposal
的编号,然后 重新进入 Prepare
阶段 。
paxos算法死循环问题