分布式管理员 zookeeper
晚上好,我是卢卡,发现很多技术学的不太扎实,比如经典的 zookeeper,Apache zookeeper 开源的分布式协调通知,对于电商系统,高并发,以及微服务的系统服务适用信息都比较高。重新再学习了一下,总结下自己的知识点,对知识点提炼和自己的理解很有帮助,技术人生从重学技术点开始。
zookeeper 的定位
Zookeeper 是 apache Zookeeper 开源的项目,
Zookeeper 的主要作用
对于微服务分布式的协调管理,元数据的管理,Master 选举, 实际使用场景下,主要是三类项目
1.zookeeper 的适用方向
① 后端以 Java 为主的电商类管理系统
Zookeeper 主要作用于 分布式锁,注册中心 ,这里 Zookeeper 主要保持 CAP 理论中的 CP(一致性和分区容错性),也就是说 Zookeeper 保证的是强一致性
②对于大数据存储,数据管理,主从数据切换等系统
这里我们熟知的 Kafla,canal 等在使用 Zookeeper 的元数据管理 ,通过 master 选举出具体的主从,ZAB 原子一致性协议,
③大型互联网公司,自研的分布式组件
一般以 zookeeper 为原型, zookeeper 已经被大规模的工业级适用于主要的分布式系统,做元数据管理,以及注册中心,一般使用于 dubbo+Zookeeper 做一个基本的微服务架构来实现基本的数据调用
小总结:
zookeeper 分布式协调系统, 封装了分布式架构中所有的核心和主流的需求和功能;
分布式锁, 元数据管理, master 选举, 分布式协调和通知
zookeeper 的基本特性:
在了解 zookeeper 的基本架构之前,我们来了解一下,zookeeper 为什么可以实现分布式系统的协调通知, 元数据管理等;
熟悉 zookeeper 技术栈的都比较了解,它本身是处于通知协调机制,数据同步方面有很强的处理能力,这也就是为什么很多自研的框架,底层都用 zookeeper 的原因,好了,废话不多说,我们开干;
背景:
集群环境下,zookeeper 集群搭建了 3 台物理机器;
1.顺序一致性
2.原子性
3.高可用性
4.数据一致性:
5.高性能性
小总结:
基于 zookeeper 的集群架构的特点图:
zookeeper 的集群化:
背景:
和上述的场景一致,都是 3 台机器,自动化部署的 zookeeper 集群,现在我们来具体拆分下每个机器的主要功能
Zookeeper 的同步数据,是经过主 leader 提交 commit 然后同步到各个 follow 角色 :2PC 提交事务--留个念想,后面细聊
1.Zookeeper 集群化角色划分:
Leader(领导)
集群启动后,根据半数选举成功的机器,成为 Leader 角色,支持读写,主要用于写操作,
Follower(候选人)
剩余的选举不成功,为 follower 角色,支持读取数据和同步数据,(leader 宕机,提供不了写数据操作时,其他 Follower 中选举出新的 L earner 来实现写数据的操作)
Observer
只是支持读取数据,不参与 leader 的竞争
这里面角色都是自身理解,也可以说成模式等等;
当每个角色确定功能之后,我们可以将数据直接开始同步,提供服务;
1.1 注意事项:
当一个写操作的请求直接访问 follower 角色的 zookeeper 的进程时,follower 角色处理不了写操作,因为自身没有权限,只有 Leader 角色处理写操作的请求,这样的话,follower 角色就会转发请求到 Leader 角色处理此请求,处理之后,开始数据同步,然后返回到其他 follower 角色,完成数据同步,阿虎;
2.Zookeeper 集群与客户端访问的过程:
背景:
Zookeeper 集群化,处理请求,可能来源于消息队列,或者是单独的发生请求读取数据,等等;那么每个请求到底是怎么连接到 Zookeeper 集群建立连接的呢,这节我们来具体聊聊?
当建立连接后,就会产生一个服务端的 session ,形成一个会话的机制,相应的也会有 sessionTimeout 的存在
如果当前环境下,突然连接中断了,在 sessionTimeout 时间内连接成功不会影响此次长连接的使用;
3.Zookeeper 集群化的数据一致性是怎么保证的?
背景:
上述说到 Zookeeper 支持 CAP 理论中的 CP ,主要是 consistency,一致性; 他保证数据强一致性,就很有自己的架构特点,我们来一步步揭开 Zookeeper 怎么保证强一致性的面纱?
Zookeeper 的强一致性是通过: ZAB(Zookeeper Atomic Broadcast) 协议: 原子广播协议
这个协议是 Zookeeper 的数据操作的核心,也用于元数据管理的关键;
协议来进行 Zookeeper 集群之间的数据同步,保证数据的强一致性;
ZAB: zookeeper Atomic broadcast 协议的思想:
划分角色: leader 和 follower
发送一个 Proposal(提议),leader 给所有的 follower 都同步一个 proposal(提议)如果半数以上的 follower,都收到事务的 proposal 提议,每个 follower 都会返回一个 ack
每个提议 Pproposal ->先不会写入 follower 中 znode 数据中,而是会往一个自己本地磁盘日志文件中写入,然后返回给 leader 一个 ackleader 会发送一个 commit 提交事务
半数提交:2PC 也就是两个阶段提交;leader 如果异常宕机,会从 follower 中重新选举;
4.Zookeeper 集群化数据同步的过程:
划分的比较细,坚持看完一定会有收获的⛽️
1⃣️当集群启动的时候,选举算法开始进行在机器中分配 leader 和 follower 角色,通过半数选举机制成功选到 leader 角色的机器
2⃣️剩下的当然就是 follower 角色的机器了,然后可以向外提供服务了
3⃣️当一个(写操作)请求经过 Zookeeper 集群后,leader 角色机器会优先分配一个 zxid 用于创建节点或者变更节点的全局唯一自增 ID,然后将发起一个提议 Proposal(只是一个提议,相当于告诉其他人来活了,准备一下),将提议都放入,之前给每个 follow 角色准备好的队列中,(这里到可以保证顺序一致性)。
4⃣️每个 follower 角色的机器,拿到提议 proposal,然后将数据放入自身的磁盘日志文件中,(不会放入 znode 节点),然后给 leader 节点回复一个 ACK(确定连接成功,返回的确定字符)
5⃣️当 leader 角色的机器,拿到半数以上的 follower 角色机器返回的 ACK 之后,代表已经准备成功,leader 角色会推送一个 commit 消息,
其他 follower 就会将数据从磁盘文件写入,自身进行 znode 节点中存储起来,提交之后,数据同步完成,也就可以读取数据了
因为这个过程,分了两阶段提交,又称为 2PC 事务,用于解决分布式事务的方法
5.Znode 的数据模型:
1.zookeeper 的数据模型是,
基于纯内存的树形结构: Znode
zk 中有一个基于分布式锁的要求环境,curator 框架,我们开展临时节点来实现的,加锁的时候创建一个顺序节点
2.zk 节点的用途
zookeeperk 做元数据管理的时候: 肯定是持久节点但是一般做分布式锁,分布式协调和通知,都是临时节点,如果断开,临时节点消失,
3 .znode 的节点的组成部分:
![img](file:///private/var/folders/5j/9nz1gp6d53b2tfxnrl8xg6yr0000gn/T/WizNote/d07bc0e0-88a1-4a6a-8702-1fd8a335449c/index_files/af5843a0-09d9-4a98-b236-7c6dc3c0b768.jpg)
6.zookeeper 启动集群到数据同步过程
leader 选举
集群启动,开始进行 leader 选举,半数机器认可当前机器作为 leader,各个 follower 开始进行数据同步,完成就可以退出恢复模式,然后可以的对外提供服务了
宕机重新选举 leader
3 台机器,允许不超过一半的机器宕机
2 台机器, 两个机器都同意某台机器作为 leader ,这个就可以选举出 leader;
1 台机器是没法自己选举自己的;因为 1 台机器,小于半数,所有不能启动集群环境了;
数据同步
leader 选举出来后,其他机器都是 follower--开始数据同步
强制剩下的 follower 数据与自己 leader 一致;
数据同步完成之后,就会进去, 消息广播模式;
消息写入: leader 写入,采用 2PC 模式过半写机制,给 follower 进行同步
将自己数据更新到,znode 数据节点中
宕机修复
leader 宕机,或者 follower 宕机,只要存活的机器超过一半,那就可以重新选举 leader 选举 leader,要求有一半以上的支持 ,其他跟 follower 数据同步,消息广播模式
zk 从恢复模式到消息广播模式开始同步数据
7.谈谈在 zookeeper 集群下数据一致性的理解?
在数据同步的过程中,leader 将提议 proposal 放入队列(先进先出),然后开始同步到 follower,当过半的 follower 返回 ACK(确认字符)之后,leader 直接推送一个 commit 用于提交,follower 同步数据;(这里我们注意,不是全部的 follower 返回结果)
zk 的数据同步不是强一致性,
当 follower 将磁盘日志文件中的数据,提交到 znode 之后,数据才可以被读取到,最终数据会一致的,但是
zk 官方给的一个回复是,顺序一致性,会根据 zxid,以及提议 proposal 的顺序保证
因为 leader 一定会保证所有的 proposal 同步到 follower 上,是按照顺序,最终实现顺序一致性
zk 也可以支持强一致行,但是需要手动调节 zk 的 sync()操作
8.ZAB 协议下,数据不一致的情况有哪些?
情况 1:
当 leader 推送一个 commit 提交数据,刚自己提交了,但是他还没有吧 commit 提交给 follower 的时候,就已经挂掉了?
简介: 当客户端发送一个写操作的请求,leader 已经收到半数以上 follower 发来的 ack,他自己本地已经将数据写入 znode 中,leader 自己 commit 成功,但是在没有给别的 follower 发出 commit 之前就已经挂了, 客户端在收到,leader 已经 commit 数据之后,就默认已经将数据更新完成,但是我们新请求,查询数据 follower 机器的时候,发现没有,与之间 leader 返回的不一样;(导致了数据不一致)
这时,follower 中的数据和刚刚宕机的 leader 机器上的数据肯定是不一致的,接下来 zk 会怎么做呢?
在具体的时间中,zk 集群中的 follower 角色发现,老大 leader 无法回复,处于失联,宕机状态,他们就说我们再选一个 leader,然后就再重新选一个 leader01(新的),那之前已经挂掉的 leader,就顺势变成了 follower,
情况 2:
如果客户端在,请求写数据操作的 leader 机器上,然后 leader,发送一个 proposal 提议,但是还没发出去,就挂了;
导致本地磁盘日志文件中存在一个 proposal;但是其他的 follower 中没有这个数据;
当集群奔溃之后,开展恢复模式,ZAB 协议的关键核心就显示出来了,根据
情况 1 的解决思路:
众多的 follower,开始半数选举机制,选出新的 leader 之后,发现本地磁盘上有没有提交的 proposal,然后查看别的 follower 也存在这样 的情况,这里的新 leader(是之前未接收到 commit 消息的 follower),然后我们开始发送 commit 给其他 follower,将数据写入 znode 节点中 解决客户端读取数据不一致的情况;
情况 2 的解决过程:
根据上述的情况,已经宕机的 leader 存在一个 proposal 的提议,但是其他的 follow 没有收到,所以在恢复模式之后,新的 leader 被选择出来,开展写操作,但是发优先去查询一下本地磁盘中是否有之前遗留的 proposal 提议,查询到一个 follower(之前宕机的发送的一个 proposal 的 leader)磁盘数据与其他的不一致,然后现在的新 leader 将会同步数据给其他的 follower,之前宕机的 leader 存在一个的提议(proposal 提议)会被舍弃掉;
9.奔溃恢复时选举出来的新 leader 如何跟其他 follower 进行同步数据的过程
我们还是来模拟一个场景,5 台机器的 zookeeper 集群化部署
其中四台是 follower 角色用于读取数据和同步数据的,剩下的一台就是 leader 专门进行写操作的机器
背景:
当一个 leader 发出一个 proposal 提议后,其他三台的 follower 机器都收到了,唯独剩下的一个没收到 proposal,但是现在已经有三台 j follower 机器已经返回了 ack 的确认字符, 所以 leader 判断已经都通知成功,(半数选举),然后自身开始 commit,没等到给剩下的 follower 角色进行提交就宕机了;
分析一下:
目前 leader 已经 commit 数据到自己的 znode 节点上了,但是已经挂了,但是其他四台 follow 机器,三台已经将 proposal 放到自己本地的磁盘日志文件中,剩余一台啥都没有(之前半数返回 ack 已经够了没有收到 proposal 提议),万一其他三台机器恢复机制时,都选举最后一台机器,作为新的 leader,那这条数据就永久丢失了,
先告诉大家一个答案,就是这中事情不会发生,zookeeper 集群不会选择一个没有数据的角色选举成 leader
主要是要了解一个 zxid 的概念:
Zxid: 可以理解为一个事物的自增 ID,要是对提议改变了,他就自增,
要是这个 follow 没有收到提议,也就 zxid 相应的比收到返回 ack 的 follower 节点的机器肯定是大的;
选举 leader 的要求是,在 follower 中,收到事务 zxid 最大的,也就是相当于创建时间最早的,作为新的 leader
10.zxid
znode 节点的状态信息中包含 czxid, 那么什么是 zxid 呢?
ZooKeeper 状态的每一次改变, 都对应着一个递增的 Transaction id, 该 id 称为 zxid. 由于 zxid 的递增性质, 如果 zxid1 小于 zxid2, 那么 zxid1 肯定先于 zxid2 发生.
创建任意节点, 或者更新任意节点的数据, 或者删除任意节点, 都会导致 Zookeeper 状态发生改变, 从而导致 zxid 的值增加.
ZooKeeper 中 ZXID 是一个长度 64 位的数字,其中低 32 位是按照数字递增,即每次客户端发起一个 proposal,低 32 位的数字简单加 1。高 32 位是 leader 周期的 epoch 编号。也就是 leader 的一个版本号
比如说后面 epoch 编号为 8, 也就说当前的 leader 版本是 8 ,挂掉之后重新选举就自增 1,epoch 的编号就是 9
所以睡要是想之前的情况 2,发生就知道是为什么会出来丢掉的数据,因为会找 leader 的 epocn 最大的一个版本作为可以提交的领导者
重新发号命令;
11.Observer 节点(角色)的作用:
需要配置文件,只会单纯的接受和同步数据,observer 不会参与过半写机制,不参与选举
只是被动的接受数据,
如果读的请求需求很大,我们可以添加几个 Observer,
优点:
可一扛下很大的并发量,
不会影响过半写的机制,
不会特别影响性能
原因:
要是都是 follower 节点的话,当 leader 要发 proposal 提议,要等待过半的机器返回 ack,然后同步数据,也是过半的,
选举的时候也是过半的,这样会很耗费时间以及网络资源,但是只要读取的数据,不参与选举的 observer 就很大程度上解决了这个痛点
12.zookeeper 适用于实际部署场景:
适用于小集群的部署,读多写少的场景;
奇数台机器,半数选举,
过半写+磁盘日志文件====》commit+znode 节点
主要是写入压力过大 leader
版权声明: 本文为 InfoQ 作者【卢卡多多】的原创文章。
原文链接:【http://xie.infoq.cn/article/7e30162f3204e66ac4a92072b】。文章转载请联系作者。
评论