本文主要是介绍zk experience,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
zk 估计就是:
分布式锁、
一致性原理、zab 协议。用于保证zk 集群事务一致性和命令的全局有序性。
选举算法
什么是zab 协议
回答什么是zab 协议:
zab 协议包括两种基本的模式:崩溃恢复和消息广播
什么是zab 协议?
特地为zk 设计的一种支持崩溃恢复的原子广播协议,保证分布式事务的最终一致性。
实现了一种主备模型(leader 和follower 模型)的架构保证集群中各个副本之间的数据一致性。
特性:
leader 上提交的事务,被所有server 提交
leader 只提出但是没有提交的,被丢弃
广播的步骤
- 将request 转为proposal
- 为每个proposal 设置一个zxid
- leader 为每个follower 设置一个单独的队列,fifo,proposal 置入
- f 收到后,将事务以日志的方式写入本地磁盘中,成功后向leader 发送ack 消息
- leader 收到半数以上ack,发commit 消息
- leader 自己同时也会提交事务,follower 接收到commit 之后,会将上一条事务提交
崩溃恢复
包含两个步骤:leader 选举、数据恢复
需要满足两个条件:
- 确保已经被 Leader 提交的 Proposal 必须最终被所有的 Follower 服务器提交。
- 确保丢弃已经被 Leader 提出的但是没有被提交的 Proposal。
所以新的leader 选举条件
- 新选举出来的 Leader 不能包含未提交的 Proposal
- 新选举的 Leader 节点中含有最大的 zxid
不写了,参考链接:https://www.jianshu.com/p/2bceacd60b8a
zk 十二连问
-
Zookeeper的「用途」
命名服务、配置管理、集群管理、分布式锁
-
什么是命名服务,什么是配置管理,又什么是集群管理吧
-
命名服务
命名服务是指通过「指定的名字」来获取资源或者服务的地址。
zk 可以创建全局唯一的路径,这个路径就是一个“名字”。通过这个名字来标识【集群中的机器、服务的地址、或者远程对象等】。
一些分布式服务框架(RPC、RMI)中的服务地址列表,通过使用命名服务,客户端应用能够根据特定的名字来获取资源的实体、服务地址和提供者信息等。
-
配置管理
对于你的应用程序,一般是部署到不同的机器上。一般会需要一些配置信息,如数据库连接信息,业务实现配置等等
如果把程序的这些配置信息「保存在zk的znode节点」下,当你要修改配置,即znode会发生变化时,可以通过改变zk中某个目录节点的内容,利用「watcher通知给各个客户端」,从而更改配置。
-
集群管理
集群管理包括集群监控和集群控制,其实就是监控集群机器状态,剔除机器和加入机器。
zookeeper可以方便集群机器的管理,它可以实时监控znode节点的变化,一旦发现有机器挂了,该机器就会与zk断开连接,用的临时目录节点会被删除,其他所有机器都收到通知。新机器加入也是类似酱紫,所有机器收到通知:有新兄弟目录加入啦。
-
-
znode 的几种类型、znode 的数据模型
-
数据模型:类似文件系统,树状的
-
znode 四种类型
-
持久节点
被创建后,就会一直存在于Zk服务器上。直到手动删除。 -
持久顺序
父节点会维护一个自增整性数字,用于子节点的创建的先后顺序。 -
临时节点
临时节点的生命周期与客户端的会话绑定,一旦客户端会话失效(非TCP连接断开),那么这个节点就会被自动清理掉。zk规定临时节点只能作为叶子节点 -
临时顺序
添加了顺序的特性
-
-
znode 节点里存储的是什么;数据量支持多少
-
存储内容:
里面还有
create_time
modify_time
version 当前节点的版本号
child_version 当前节点中创建的子节点的版本号
acl_version 当前节点中ACL权限相关的版本号
ephemeralOwner 保存创建节点的时候生成的会话sessionId(持久节点为0)
numChildren
「存储数据、访问权限、子节点引用、节点状态信息」- 「data:」 znode存储的业务数据信息
- 「ACL:」 记录客户端对znode节点的访问权限,如IP等。
- 「child:」 当前节点的子节点引用
- 「stat:」 包含Znode节点的状态信息,比如「事务id、版本号、时间戳」等等。
- 数据量不能超过1M,最好都小于1k
-
- 监听机制(watch 机制)
Watcher机制
监听机制的工作原理
Watcher特性总结
- watcher 机制
客户端向服务端的某个znode 注册一个watcher 监听,把Watcher理解成客户端注册在某个Znode上的触发器,当这个Znode节点发生变化时(增删改查),就会触发Znode对应的注册事件,注册的客户端就会收到异步通知,然后做出业务的改变。
- watcher 监听机制工作原理
整个Watcher机制中,主要包括watcherManager、客户端线程以及Zookeeper服务端三部分
watcher 接口,表示一个标准的事件处理器。定义了对应的逻辑,其中KeeperState和EventType两个枚举类型的属性分别代表了通知的状态以及通知的事件类型,并且在Watcher接口中,定义了一个方法作为触发通知以后的逻辑处理方法:process(WatchedEventevent)
KeeperState 定义了watcher 时间的状态类型,如:断开连接,已连接,废弃,权限异常,关闭连接等
EventType 定义了通知类型,如:创建节点成功通知,节点移除通知,当前节点数据变化通知,子节点列表变化通知 - watcher 特性
一次性
异步
轻量级
客户端串行
- watcher 机制
- zk 特性
Zookeeper 保证了如下分布式一致性特性:
- 「顺序一致性」:从同一客户端发起的事务请求,最终将会严格地按照顺序被应用到 ZooKeeper 中去。
- 「原子性」:所有事务请求的处理结果在整个集群中所有机器上的应用情况是一致的,也就是说,要么整个集群中所有的机器都成功应用了某一个事务,要么都没有应用。
- 「单一视图」:无论客户端连到哪一个 ZooKeeper 服务器上,其看到的服务端数据模型都是一致的。
- 「可靠性:」 一旦服务端成功地应用了一个事务,并完成对客户端的响应,那么该事务所引起的服务端状态变更将会被一直保留下来。
- 「实时性(最终一致性):」 Zookeeper 仅仅能保证在一定的时间段内,客户端最终一定能够从服务端上读取到最新的数据状态。
- zookeeper是如何保证事务的顺序一致性的呢
ZXID的低32位是计数器,所以同一任期内,ZXID是连续的,每个结点又都保存着自身最新生效的ZXID,通过对比新提案的ZXID与自身最新ZXID是否相差“1”,来保证事务严格按照顺序生效的
详情参考:聊一聊ZooKeeper的顺序一致性-极客时间
zk 设计了zab 协议作为其数据一致性协议。
利用zab 协议的数据,写入由leader 节点协调,使用两阶段提交的方式,达到数据的最终一致性。
数据写入过程:
(1)第一阶段:每次的数据写入事件作为提案广播给所有 Follower 结点;可以写入的结点返回确认信息 ACK
(2)第二阶段:Leader 收到一半以上的 ACK 信息后确认写入可以生效,向所有结点广播 COMMIT 将提案生效
zk 保证的最终一致性,也叫顺序一致性。即每个节点的数据都是严格按照事务的发起顺序生效的。
zk 如何保证顺序的?
zk 有个事务id,即zxid,由leader 节点生成。
有新写入事件时,leader 生成新的zxid,并随着事件一起广播。
每个结点本地都保存了当前最近一次事务的 ZXID,ZXID 是递增的,所以谁的 ZXID 越大,就表示谁的数据是最新的。
ZXID 的低 32 位是计数器,所以同一任期内,ZXID 是连续的,每个结点又都保存着自身最新生效的 ZXID,通过对比新提案的 ZXID 与自身最新 ZXID 是否相差“1”,来保证事务严格按照顺序生效的
ZooKeeper 集群的写入是由 Leader 结点协调的,真实场景下写入会有一定的并发量,那 Zab 协议的两阶段提交是如何保证事务严格按顺序生效的呢?
Leader 在收到半数以上 ACK 后会将提案生效并广播给所有 Follower 结点,Leader 为了保证提案按 ZXID 顺序生效,使用了一个 ConcurrentHashMap,记录所有未提交的提案,命名为 outstandingProposals,key 为 ZXID,Value 为提案的信息。
对 outstandingProposals 的访问逻辑如下:
每发起一个提案,会将提案的 ZXID 和内容放到 outstandingProposals 中,作为待提交的提案;
收到 Follower 的 ACK 信息后,根据 ACK 中的 ZXID 从 outstandingProposals 中找到对应的提案,对 ACK 计数;
执行 tryToCommit 尝试将提案提交,判断流程是
先判断当前 ZXID 之前是否还有未提交提案,如果有,当前提案暂时不能提交;
再判断提案是否收到半数以上 ACK,如果达到半数则可以提交;
如果可以提交,将当前 ZXID 从 outstandingProposals 中清除并向 Followers 广播提交当前提案;
Leader 是如何判断当前 ZXID 之前是否还有未提交提案的呢?由于前提是保证顺序提交的,所以 Leader 只需判断 outstandingProposals 里,当前 ZXID 的前一个 ZXID 是否存在
所以 ZooKeeper 是通过两阶段提交保证数据的最终一致性,并且通过严格按照 ZXID 的顺序生效提案保证其顺序一致性的。
- zk 如何保证主从节点数据一致性
关注两个问题:
(1)「主服务器挂了,或者重启了」
(2)「主从服务器之间同步数据」
使用zab 协议保证主从节点“数据一致性”。
ZAB协议支持「崩溃恢复和消息广播」两种模式,很好解决了这两个问题:
(1)崩溃恢复:Leader挂了,进入该模式,选一个新的leader出来
(2)消息广播:把更新的数据,从Leader同步到所有Follower
Leader服务器挂了,所有集群中的服务器进入LOOKING状态,首先,它们会选举产生新的Leader服务器;
接着,新的Leader服务器与集群中Follower服务进行数据同步,当集群中超过半数机器与该 Leader服务器完成数据同步之后,退出恢复模式进入消息广播模式。Leader 服务器开始接收客户端的事务请求生成事务Proposal进行事务请求处理。
- Leader挂了,进入崩溃恢复,是如何选举Leader的呢?ZooKeeper选举机制
- 分布式锁
使用临时顺序节点
创建锁:- 首先创意一个持久节点/locks
- 当客户端请求来到时,需要在持久节点下创建一个顺序节点/lock1
- 然后查找/lock 节点下所有临时顺序节点,判断自己的是不是最小的,如果是,则获取到锁;如果不是,向其之前的一个节点注册watcher,进行监听
释放锁: - 故障、或者主动释放,临时节点都会删除。
- dubbo 使用zk 的原因
- 命名服务,服务提供者向Zookeeper指定节点写入url,完成服务发布。
- 负载均衡,注册中心的承载能力有限,而Zookeeper集群配合web应用很容易达到负载均衡。
- zk支持监听事件,特别适合发布/订阅的场景,dubbo的生产者和消费者就类似这场景。
- 数据模型简单,数据存在内存,可谓高性能
- 在Zookeeper中,提供了ACL权限机制来保障节点及对应数据的安全
分别分为:权限模式(Scheme)、授权对象(ID)和权限(Permission),通常是以Scheme:ID:Permission方式组合成一个有效的ACL信息
权限模式:world、ip、auth、digest、super(超级管理员)world 是默认的,digest 是常用的。
权限模式授权对象IP通常是一个ip或者一个ip段
权限:create、delete、read、write、admin(管理acl 权限的权限)
- 如何实现zk 的最终一致性
问题提出:一个事务被leader 广播后,如果收到过半的ack 就可以commit,但是假若其他没有返回ack 的follower 节点真的同步失败,导致事务没有在这些节点最终提交,那么这个follower数据就不是新的,那这个follower的数据什么时候被同步
解答:这涉及的问题是zookeeper如何实现最终一致性的问题。如果是重新选举的时候就违背了zookeeper的最终一致性原则,因为从你的提的问题的条件判断,这个机器没有宕机没有网络延时只是commit失败,那么这个节点就会进入崩溃恢复阶段,而又存在leader故直接链接leader 进行同步,如果一直commit失败那么运维人员就会看出端倪只能人为解决commit失败原因,当解决后将该节点加入集群,重新开始崩溃恢复然后实行follower的正常工作
(另外的解答:这个follower会在可用的时候,直接连接当前的leader,由leader负责这个follower的同步。这种情况不一定会重新选举leader。)
-
以上参考:
https://bigdata.51cto.com/art/202009/625181.htm(主要)
https://zhuanlan.zhihu.com/p/145065980
zk 基本知识:https://www.cnblogs.com/rickiyang/p/11074200.html
- znode 可以是临时节点,一旦创建这个 znode 的客户端与服务器失去联系,这个 znode 也将自动删除,Zookeeper 的客户端和服务器通信采用长连接方式,每个客户端和服务器通过心跳来保持连接,这个连接状态称为 session,如果 znode 是临时节点,这个 session 失效,znode 也就删除了
另一些知识点:https://blog.csdn.net/weixin_39934302/article/details/111135956
两阶段提交和三阶段提交的区别:
https://blog.csdn.net/qq_26222859/article/details/52067011
paxos 算法
一致性协议:2pc、3pc、paxos
2pc 3pc 主要用于分布式事务一致性中,主要有个协调者,去协调整个集群中的请求,把所有参与者的请求集合在协调者中,通过协调者协调整个集群的事务是否提交。
2pc 首先确认参与者是否都达成了条件,然后提交
3pc 多了个校验的过程
2pc 3pc 只是降低了协议提交产生不一致的范围。
是什么:
paxos 主要用于数据一致性中,是一种基于消息传递且具有高度容错性的一致性算法。
解决了什么:
宕机、网络异常的情况下,在集群内部对某个数据的值达成一致,保证不论发生以上任何异常,不会破坏整个系统的一致性。
原理及内容:
paxos 的小岛,采用议会的形式通过法令,议会中的议员通过信使进行消息的传递。消息可能重复传递,也可能丢失。(不会出现被篡改的问题)
在这样的环境下,通过议会协议,仍然能保证有法令会被通过。
角色:
提议者(proposer):进行提议的角色
批准者(acceptor):通过提议的角色
学习者(learner):感知(learn)被选定的提议
具体实现中,一个进程可能同时充当多种角色。可能既是proposer,又是acceptor,又是learner。
有空再补充吧
总的来讲,ZAB协议和Paxos算法的本质区别在于,两者的设计目标不太一样。ZAB协议主要用于构建一个高可用的分布式数据主备系统,例如Zookeeper,而Paxos算法则是用于构建一个分布式的一致性状态机系统。
https://juejin.cn/post/6926761585071357966
这个小结的知识比较杂乱,没有体系,就作为一个知识入门的参考。
一、基础知识
zookeeper是一款开源的分布式协调服务框架,为分布式环境提供了一致性服务的功能,常见应用场景有:发布订阅,主动通知,文件管理,集群管理,分布式锁等功能。zk在设计的时候满足了cp两要素,即一致性和分区容错性。
节点类型
四种:
- 持久化节点(默认)
- 临时节点
- 持久化顺序节点
- 临时顺序节点
ACL 权限设置
world、默认,全世界都可以访问
ip、使用ip 地址认证
auth(用户名密码,明文)、代表已经认证通过的用户
digest(同auth,密码加密,常见)、即用户名:密码这种方式认证,这也是业务系统中最常用的
集群
至少3 个
这两种场景下会有选举发生:
-
服务节点初始化
-
或者半数以上的节点无法和leader进行连接建立
集群里面的zk机器均具有读和写的功能。
zk 设计理念
一致性,如果leader 挂掉,则直接停止对外服务
有个leader
数据按照树的结构进行存储
二、zab 概要
zk 集群的选举
zxid
对于zk的节点数据,每次发生数据变动都会有一个流水id做递增的记录,这个id我们称之为zxid
不同机器的zxid可能会有所不同,越大代表当前的数据越新。
这个全局有序
每个zk节点都有几个用于记录更新的id,分别是czxid和mzxid。通过名称的缩写可以翻译为:
-
czxid:创建节点时候的xid。
-
mzxid:修改节点数据时候的xid。
-
pzxid:只有子节点列表变化才会重新生成pzxid,如果某个子节点内容修改等操作并不会生成新的pzxid。孙子节点不相关
ZXID(64bit) = epoch(32bit) + counter(32bit)
Zxid定义:Zxid是一个long型(64位)整数,分为两部分:纪元(epoch)部分和计数器(counter)部分,是一个全局有序的数字。
epoch定义:epoch表示当前集群所属的哪个leader,leader的选举就类似一个朝代的更替,你前朝的剑不能斩本朝的官,用epoch代表当前命令的有效性。
counter定义:counter是一个递增的数字。
投票整体思路
第一轮投票全部投给自己
第二轮投票给zxid比自己大的相邻节点 如果得票超过半数,选举结束。
假设现在有3台机器参与选举,分别是1,2,3号机器,启动顺序是1,2,3。最终2 好机器为leader
如何保证主从节点的数据状态同步
zab 协议
集群中,保证各个server端的数据一致性其实是依靠了一个叫做zab的基础协议。zab协议的全称是zookeeper atomic broadcast zk原子广播协议,可以理解为是一种用于保证分布式环境下事务一致性的一种协议。保证zk 集群的数据一致性和命令全局有序性。
(一致性的理解:https://blog.csdn.net/weixin_36979214/article/details/104794592)
(一致性相当于使计算机模拟的世界“能量守恒”)
由一台主机器用于接受集群的请求指令(暂时称之为leader),然后通过leader将指令复制传递给各个follower角色进行数据复制。
如何判断写请求提交成功
当leader将数据成功写入超过半数以上的节点的时候就算是写请求提交成功了
zk集群环境中写入数据过程中发生了什么
客户端首先连接到zk集群环境,然后将需要写入的数据提交给任意一台zk服务器,如果当前服务器是leader,则由leader接受,然后将数据广播给集群的每一台follower机器。如果接受指令的是follower,则会将请求转给leader,再广播给各个follower机器。
广播细节分为两个步骤:
- Leader 可以接受客户端新的事务Proposal请求,将新的Proposal请求广播给所有的 Follower。如何确认广播出去的请求,follower确认接收呢?需要借助一个ack的标记信息响应进行反馈。
- 假设集群里面有一半的机器都返回了ack信号,那么此时leader就可以再次广播每个机器执行相应事务的commit操作了,并且执行之后需要在本地记录该行为到事务日志中。
崩溃模式
zk集群中的leader可能因为网络抖动或者某些异常问题,失去了和其余follower的联系,此时剩余的follower需要重新进行选举。
或者如果集群中只有不到一半的机器能和leader进行通信,那么此时也算是进入到了崩溃模式,需要重新选举。
zk节点的数据变动通知特性
当客户端链接到zk服务端的时候,某个节点如果出现了数据变动,之前有监听过这个节点数据的客户端都会接收到相关信号。
可能会有什么问题?
这种主动通知是一种弱最终一致性,而且只会发送一次通知,并不能保证更新的实时准确性。
zk 集群中的三个角色(leader follower observer)
Leader:同一时间集群总只允许有一个Leader,提供对客户端的读写功能,负责将数据同步至各个节点;
Follower:提供对客户端读功能,写请求则转发给Leader处理,当Leader崩溃失联之后参与Leader选举;
Observer:与Follower不同的是不参与Leader选举。
zk 集群有两个阶段:选举阶段 + 广播阶段
选举阶段
有了leader 不需要了就
follower 有选举权和被选举权
observer 无选举权和被选举权
选举过程是所有follower 来投票,从follower 中选举出一个超过半数follower 同意的follower 当做leader
广播阶段
关于leader,有且只有一个,用来处理写请求,是zookeeper集群中唯一一个处理写请求的节点。
关于follower,在读写操作下,读操作自己处理(不过问leader节点),写请求发给leader,写请求第二阶段所有follower投票过半即可
关于observer,在读写操作下,读操作自己处理(不过问leader节点),写请求发给leader,写请求第二阶段投票没observer什么事。
(由于observer没有 投票权 和 被选举权,选举时的过半数通过和写操作时的过半数ACK 都和它没关系,都是follower和leader的事)
observer 存在的意义
加入更多 Observer 节点,提高伸缩性,同时不影响吞吐率。(不参与投票,不会增加投票延迟)
leader存在的意义
(为什么要投票选择一个leader,投票是一个延迟大的内部消化,为什么不去掉)
保证集群server 的数据一致性
保证主从结构
zk 四种状态 + zab 四种状态
对于zookeeper的四个状态
looking仅在选主阶段出现
following是zookeeper在广播阶段的follower节点的状态,
leading是zookeeper在广播阶段的leader节点的状态,
observing是zookeeper在广播阶段的observer节点的状态。
对于ZAB的四个状态,实际上选主阶段的四种过程(选举、发现、同步、广播)
ELECTION: 集群进入选举状态,此过程会选出一个节点作为leader角色;
DISCOVERY:连接上leader,响应leader心跳,并且检测leader的角色是否更改,通过此步骤之后选举出的leader才能执行真正职务;
SYNCHRONIZATION:整个集群都确认leader之后,将会把leader的数据同步到各个节点,保证整个集群的数据一致性;
BROADCAST:过渡到广播状态,集群开始对外提供服务。
zk 选举过程(基于zab 协议)
选择leader 的两个时机
1. zk 启动的时候
2. zk 不提供服务的时候(断网、断电、宕机),其他节点心跳检测leader 失联之后,集群进入选举状态
理论上,leader 选举的三种规则
达到选举时机之后,开始选举。
- 比较epoch,选大的
- 比较zxid,选大的
- 比较serviceId,选大的。(配置zk 集群的时候指定的)
实践上,leader 选举流程四个步骤
- 每个节点先选自己:投票信息广播出去
- 每个节点接受其他n - 1 个节点:从队列中接收投票信息
- 根据三个比较规则(上面1,2,3),确定自己选举的leader,然后第二次广播出去:按照三条规则判断是否需要更改投票信息,将更改后的投票信息再次广播出去
- 是否一个节点过半数,是了就行了,不是跳到步骤2,继续接收 n-1 节点:判断是否有超过一半的投票选举同一个节点,如果是选举结束根据投票结果设置自己的服务状态,选举结束,否则继续进入投票流程。
(超过1/2 的原因:超过1/2 就可以确认唯一的leader,而2/3 却又浪费资源)
关于zookeeper中的投票过半数(包含两层意思):
第一,选举过程中,一半的节点选举了,就好了
第二,广播过程中,两阶段提交,eader收到一半的follower发过来的ACK,就提交了(所以,zookeeper不是强一致性的)
zk 的广播过程(读写操作)
zookeeper集群对外提供服务(即读写操作)如何保证各个节点数据的一致性。
zab 协议有序性
有序性定义?
标准答案:zab在广播状态中保证以下特征
第一,可靠传递: 如果消息m由一台服务器传递,那么它最终将由所有服务器传递。
第二,全局有序: 如果一个消息a在消息b之前被一台服务器交付,那么所有服务器都交付了a和b,并且a先于b。
第三,因果有序: 如果消息a在因果上先于消息b并且二者都被交付,那么a必须排在b之前。
ZAB保证有序性实现?
标准答案:zab协议的有序性保证是通过几个方面来体现的,
第一,服务之间用TCP协议进行通讯,保证在网络传输中的有序性;
第二,节点之间都维护了一个FIFO的队列,保证全局有序性;
第三,通过全局递增的zxid保证因果有序性。
为什么需要zab需要保证有序性?
标准答案:
zookeeper的存储结构是类型目录结构,不保证有序性无法定位,会报错。
有序性是zab协议必须要保证的一个很重要的属性,因为zookeeper是以类似目录结构的数据结构存储数据的,必须要求命名的有序性。
比如一个命名a创建路径为/test,然后命名b创建路径为/test/123,如果不能保证有序性b命名在a之前,b命令会因为父节点不存在而创建失败。
基础知识:两阶段提交
(定义、流程、优缺点)
两阶段提交定义:
在分布式系统中,每一个机器节点虽然能够明确的知道自己在进行事物操作过程的结果是失败或成功,但却无法直接获取其他分布式节点的操作结果,所以,事物操作需要跨越多个分布式节点的时候,需要引入一个协调者统一调度所有节点的执行逻辑。
两阶段提交详细:
阶段一:提交事物请求
1.1 leader事务询问
协调者向所有的参与者发送事物内容,询问是否可以执行事物操作,并开始等待各参与者的响应。
1.2 follower/observer执行事务
各参与者节点执行事物操作,并将Undo和Redo信息记入事物日志中
1.3 各参与者follower/observer向协调者leader反馈事务询问的响应
如果参与者成功执行了事物操作,那么就反馈给协调者Yes响应,表示事物可以执行;如果参与者没有成功执行事物,那么就反馈给协调者No响应,表示事物不可以执行。
阶段二:执行事物请求
在阶段二中协调者会根据参与者的反馈情况来决定最终是否可以进行事物操作,其中有两种可能 Commit/Cancel。假如协调者从所有的参与者获得的反馈都是Yes响应,那么就会执行事物响应(zookeeper是过半就好)。
2.1 Leader发送提交请求
协调者向所有参与者节点发出Commit请求
2.2 follower/observer事物提交
参与者接收到Commit请求后,会正式执行事物提交操作,并在完成提交之后释放在整个事物执行期间占有的事物资源。
2.3 follower/observer反馈事物提交结果
参与者在完成事物提交之后,向协调者发送Ack消息。
2.4 leader完成事务
协调者接收到所有参与者反馈的Ack消息后,完成事物。
二阶段提交优缺点
优点:原理简单,实现方便
缺点:同步阻塞,单点问题,脑裂,数据丢失(四个问题,在分布式事务中讲到过)。
Zookeepr四状态 + ZAB四状态
从 “zookeeper分为选主阶段和广播阶段” 看 zookeeper 的四个状态和 ZAB 的四个状态
对于zookeeper的四个状态
looking仅在选主阶段出现
following是zookeeper在广播阶段的follower节点的状态,
leading是zookeeper在广播阶段的leader节点的状态,
observing是zookeeper在广播阶段的observer节点的状态。
对于ZAB的四个状态,实际上选主阶段的四种过程
ELECTION: 集群进入选举状态,此过程会选出一个节点作为leader角色;
DISCOVERY:连接上leader,响应leader心跳,并且检测leader的角色是否更改,通过此步骤之后选举出的leader才能执行真正职务;
SYNCHRONIZATION:整个集群都确认leader之后,将会把leader的数据同步到各个节点,保证整个集群的数据一致性;
BROADCAST:过渡到广播状态,集群开始对外提供服务。
以上来自:zookeeperzookeeper的ZAB协议 | 码农家园
然后再看这十二问:
ZooKeeper的十二连问,你顶得了嘛? - 51CTO.COM
Zookeeper使用篇-Zookeeper系统核心模型 - 知乎
这个用来复习:https://www.jianshu.com/p/08dc8a9d9240
zk 那个东西 - 分布式锁
分布式协调服务,基于zk,实现同步服务、配置维护、命名服务等
znode 可以被监控,监控的内容包括此节点中存储的数据的修改,子节点目录的变化等,一旦变化,可以通知到设置监控的客户端,这是zk 的核心特性,很多功能基于此而实现。
正常线程、进程同步机制:互斥量、信号量、读写锁、条件变量
-
互斥:同一时间,只有一个线程可以操作共享资源。如synchronized,Lock 等。其本质是一把锁,在访问共享资源变量前,对互斥量进行加锁,访问完成后,释放互斥量上的锁。
-
信号量:互斥量只能用于一个资源的互斥访问,不能实现多个资源的多线程互斥问题。信号量可以实现多个同类资源的多线程互斥和同步。Semaphore 类。当信号量为单值信号量时,也可以完成一个资源的互斥访问。比如发令枪CDL,Semaphore等
(semophore:Semaphore 使用详解 - 简书) -
读写锁:类似互斥,但是有更高的并行性。互斥要么是锁住,要么是不加锁状态,而且一次只有一个线程可以对其加锁。而读写锁,有三种状态,读加锁、写加锁、不加锁。读写锁也叫“共享-独占锁”。
-
条件变量、监视器(临界值、事件通知):条件变量,与互斥量一起使用,允许线程以无竞争的方式等待特定的条件发生。临界值,让多线程串行化去访问资源。事件通知,通过事件的通知去保证大家都有序访问共享资源。
而线程的同步机制只能保证当前机器线程安全,对于分布式还是有问题。zk 节点有个唯一的特性,创建过此节点之后,再创建会报错。所以可以用它的唯一性去实现。 相当于创建成功代表加锁成功,通过删除节点来解锁。
有可能造成死锁,服务器宕机,无法删除,所以用临时节点。但是如果只监听一个节点,有可能产生“羊群效应”,而羊群效应举例如:一个节点失效,900 个服务器监听,导致向900 个server 发送消息,随时可能干掉机器。而解决这个问题,就用临时顺序节点。 每个线程创建临时顺序节点,然后对父节点的所有子节点做判断,如果当前创建的项目是最小的节点,就说明加锁成功。而监听的时候,只监听自己的前一个节点,释放也是一个个释放下去,这样就不会出现羊群效应了。
————————————————
节点名字由uuid + 递增序列组成。而通过对比自身的序列数是否在所有子节点的第一位,来判断是否成功获取到了锁。当获取锁失败时,它会添加watcher来监听前一个节点的变动情况,然后进行等待状态。直到watcher的事件生效将自己唤醒,或者超时时间异常返回。
————————————————
而zk 性能可能没有缓存高,因为每次在创建和释放锁的过程中,都需要动态 创建、销毁 临时节点来实现锁的功能。zk 中创建节点和删除节点只能通过leader 服务器执行,然后将所有数据同步到follower 机器上。(zk 集群的知识)
zk 有可能产生并发问题,由于网络抖动,客户端和zk 集群的session 连接断了,那么zk 认为server 宕机,就会删除这个临时节点,这时候其他客户端就会获得到分布式锁了。这就可能产生并发问题,而此问题不常见。因为zk 有重试机制,一旦zk 集群检测不到客户端心跳,就会重试。
zk 通过节点排队监听机制,实现了阻塞原理,其实就是个递归在那无限等待最小节点释放的过程。
有序性是zk 中的一个重要特性,所有更新都是全局有序的,每个更新都有一个唯一的时间戳。这个时间戳成为zxid(zk transaction id)
二、基于ZooKeeper的实现方式
ZooKeeper是一个为分布式应用提供一致性服务的开源组件,它内部是一个分层的文件系统目录树结构,规定同一个目录下只能有一个唯一文件名。基于ZooKeeper实现分布式锁的步骤如下:
(1)创建一个目录mylock;
(2)线程A想获取锁就在mylock目录下创建临时顺序节点;
(3)获取mylock目录下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说明当前线程顺序号最小,获得锁;
(4)线程B获取所有节点,判断自己不是最小节点,设置监听比自己次小的节点;
(5)线程A处理完,删除自己的节点,线程B监听到变更事件,判断自己是不是最小的节点,如果是则获得锁。
优点:具备高可用、可重入、阻塞锁特性,可解决失效死锁问题。
以上大部分参考:阿里面试官让我用Zk(Zookeeper)实现分布式锁_敖丙-CSDN博客_zk 分布式锁
zk 那个东西 - 常见问题
zk 是一个开源分布式协调服务,基于zk 可以实现的功能:
- 数据发布/订阅
- 分布式协调/通知
- 分布式同步
- 分布式锁
- 分布式队列
- 负载均衡
- 集群管理
- master 选举
- 配置服务
- 命名服务
zk 是一个开源分布式协调服务,为分布式应用提供一致性服务,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
zk 都有哪些功能:
- 集群管理:监控节点存活状态、运行请求等
- 主节点选举:主节点挂掉,从备用节点开始新一轮选主。zk 协助完成这个过程
- 分布式锁:zk 提供两种,独占、共享。zk 可以对分布式锁进行控制。
- 命名服务:分布式系统中,通过使用命名服务,客户端应用能够根据指定名字获取资源或服务的地址,提供者等信息
对zab 协议的了解
zab 是为分布式协调服务zk 专门设计的一种支持崩溃恢复的原子广播协议。
包含两种基本模式:崩溃恢复 & 消息广播。
总结了12道Zookeeper面试题 - 云+社区 - 腾讯云
Zookeeper面试题 - lanqiu5ge - 博客园
面试完腾讯,总结了这12道Zookeeper面试题! - 云+社区 - 腾讯云
ZooKeeper面试题(2020最新版) - 云+社区 - 腾讯云
执行一个sql mysql 系统的流程 - 国内版 Bing
字节三面:详解一条 SQL 的执行过程 - 知乎
zk 的作用:(1)集群管理:容错、负载均衡(2)配置文件的集中管理(3)集群的入口
zk 中leader 的选举使用的zab 协议,zab 的核心思想是当多数server 写成功,则任务数据写成功。
zk 底层其实只提供了两个功能:(1)管理[存储、读取]用户程序提交的数据。(2)为用户程序提交数据节点监听服务。
zk 的几个概念:会话、znode、版本、watcher、acl
session
指的是zk 服务器与客户端会话。zk 中,一个客户端连接是指客户端和服务器之间的一个tcp 长连接。客户端启动的时候,首先会与服务器建立一个tcp 连接,第一次建立连接开始,客户端会话的生命周期也开始了。通过这个连接,客户端通过心跳检测与服务器保持有效的会话,也能够向zk 服务器发送请求并接受响应,还能够通过该连接接收来自服务器的watch 事件通知。
sessionTimeout 设置会话超时时间。时间内重新连接上集群中任意一台服务器,则session 还有效。
服务端为每个客户端分配一个sessionId,是zk 会话的一个重要 标识,全局唯一
版本。每个znode,都有个stat 的数据结构。记录了此znode 的三个数据版本,分别是version(当前znode 的数据内容版本)、cversion(当前znode 子节点的版本)和aversion(当前znode 的acl 变更版本)
watcher(事件监听器)。zk 允许用户在指定节点上注册一些watcher,并且在一些特定事件触发的时候,zk 服务端会将时间通知到感兴趣的客户端上去,以此实现分布式协调服务。
使用acl(access control list)策略,进行权限控制。有五种权限(1)create 创建子节点的权限(2)read 获取子节点数据和子节点列表的权限(3)write 更新节点数据的权限(4)delete 删除子节点的权限(5)设置节点acl 的权限。create 和delete 都是针对子节点的权限。
zk 特点:顺序一致性(同一客户端请求,按顺序被应用到zk),原子性(要么集群中所有机器成功应用一个事物,要么都没应用),单一系统映像(无论客户端连接到哪个server,其看到的服务端数据模型都是一致的),可靠性(更改被应用则就持久化)。
来自客户端的每个更新请求,zk 都会分配一个全局唯一的递增编号,编号反应了所有操作事务的先后顺序,这个编号也叫做时间戳zxid
最典型集群模式:master/slaver 模式(主备模式)。zk 没有选择传统的master/slaver 概念,而是引入了Leader、Follower 和Observer 三种角色。F 和O 的区别在于O 机器不参与Leader 的选举过程,也不参与写操作的“过半成功”策略,所以O 不影响写操作却可以提升集群的读性能。
zab 协议、paxos 算法。pa 算法是zk 的灵魂,但是zk 并没有完全采用pa 算法,而是使用zab 协议作为保证数据一致性的核心算法。zab 并不像pa 算法那样,是一种通用的分布式一致性算法,它是一种特别为zk 设计的崩溃可恢复的原子消息广播算法。
zab(zk atomic broadcast 原子广播)。zab 两种基本模式:崩溃恢复和消息广播。启动过程和leader 崩溃的时候,zk 会进入恢复模式。当选举产生了新的leader 之后,并且完成了数据同步(整个集群中国版follower 完成了和leader 的状态同步),那么整个服务框架就可以进入消息广播模式了。
ZooKeeper 概念讲解 - 知乎 查看
这篇关于zk experience的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!