ZooKeeper:架构和算法
ZooKeeper主要用来解决分布式应用场景中存在的一些问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置管理等。
它支持Standalone模式和分布式模式,在分布式模式下,能够为分布式应用提供高性能和可靠地协调服务,而且使用ZooKeeper可以大大简化分布式协调服务的实现,为开发分布式应用极大地降低了成本。
总体架构
ZooKeeper分布式协调服务框架的总体架构,如图所示:
ZooKeeper集群由一组Server节点组成,这一组Server节点中存在一个角色为Leader的节点,其他节点都为Follower。
- 写请求:写请求会序列化,每个写请求转发给leader通过ZAB协议达到一致性和顺序性(所有节点更新顺序一致)。
- 读请求:与chubby不同,chubby所有读写请求必须转发给leader,在zookeeper中,所有的server(leader和follower)都可以响应读请求。这样会带来不一致的问题,zab协议还没有把写消息同步到所有节点上。zookeeper可以通过sync调用(怎么实现的?)强制同步。
- zxid编号:每次读写,zookeeper都会返回一个zxid编号,zookeeper保证返回的数据不会比客户端传过来的zxid编号更新
- 模糊快照和日志:zookeeper周期性地将内存中的数据保存在磁盘中形成模糊快照(模糊的含义是不一定是最新的),zookeeper将更新操作都会先写入磁盘。zookeeper保证更新操作都是“幂等的”,所以可以通过模糊快照和日志恢复内存数据。
数据模型
zookeeper通过树形命名空间来进行整个系统的协调,其中的每个节点称为znode,znode有两种持久节点和临时节点。临时节点和会话绑定,会话下线临时节点删除(心跳监控是否宕机)
zookeeper的全部数据都保存在内存中,以此来实现高吞吐,低延迟。
API
//创建节点,flag可以指定递增,临时节点
string create(path, data, acl, flags)
//删除节点
void delete(path, expectedVerstion)
//改
stat setData(path, data, expectedVersion)
//查
(data, stat) getData(path, watch)
//存在
stat exist(path, watch)
//获取孩子节点
String[] getChildren(path, watch)
//同步
void sync(path)
所有有关查的api(3个),可以设置监视器,状态发生变化可以通知
主要功能
领导者选举
在一个特定的目录下,创建一个leader临时节点。热备机周期性地检查这个节点是否存在,如果不存在,就尝试在这个目录下创建leader节点,升级为leader。
(data, stat) = zookeeper.get(handle, "/services/myservice/leader",true);
if(stat == none)
path = zookeeper.create(handle, "/services/myservice/leader", 临时节点)
if(path = none)//失败,获取当前leader
(data, stat) = zookeeper.get(handle, "/services/myservice/leader",true);
else
成功,自己是leader
配置管理(pub-sub服务)
创建特定的节点,用于管理集群的配置信息。所有客户端看见的都是一致的内容,并且可以设置watch在节点内容变更的时候通知客户端。
注意:不要使用zookeeper同步大块数据,进行会急剧下降。会走一致性协议同步,写磁盘,然后在反应在内存中。
成员管理
成员管理的目的就是,集群内某个节点宕机或者新加入节点,zookeeper可以及时感知。实现方式是为每台机器创建临时节点,临时节点和会话绑定。同时,监控客户端可以通过getChildren设置watch,临时节点有变更可以及时通知。
任务分配
- 新任务到来:在tasks目录下创建任务节点
- 任务分配:监控进程感知到tasks目录下的节点变化,触发任务分配。图中task1分配到machine1的目录下,代表task1分配给machine1
- 任务执行:machine1发现自己目录下的任务,执行该任务。结束后删除machine1目录下的task1和task目录下的task1。
锁服务
创建互斥锁
- 在l目录下,创建以lock为前缀的递增临时节点,返回节点编号
- 获取l目录下所有节点信息
- 如果刚刚创建的编号是所有节点编号最小的(最先创建节点的),获得锁
- 没有获得锁,进入第2步
创建读写锁
创建写锁
- 在l目录下,创建以write为前缀的递增临时节点,返回节点编号
- 获取l目录下所有节点信息
- 如果刚刚创建的编号是所有节点编号最小的(最先创建节点的),获得锁
- 没有获得锁,进入第2步
创建读锁
- 在l目录下,创建以read为前缀的递增临时节点,返回节点编号
- 获取l目录下所有节点信息
- 如果刚刚创建的编号比所有write前缀的编号小,获得读锁
- 没有获得锁,进入第2步
释放锁
删除临时节点
双向路障同步
任务统一开始
- 在路障节点下创建当前任务节点,代表该任务到达路障
- 检测路障节点下任务个数是否足够,足够代表可以继续统一执行
任务统一离开
- 任务结束后,任务路障节点下的任务节点
- 如果路障节点下没有任务节点,代表所有任务已经执行结束
ZAB协议(ZooKeeper Atomic Broadcast原子消息广播协议)
zab协议所有事务请求必须由leader协调,首先leader发起proposal消息,大多数server同意后,然后leader发送commit消息。
zxid编号
- 低32位为计数器,客户端每次请求+1
- 高32位为epochID,每次选举新leader+1
状态和阶段
- Looking:系统刚启动时或者Leader崩溃后正处于选举状态
- Following:Follower节点所处的状态,Follower与Leader处于数据同步阶段
- Leading:Leader所处状态,当前集群中有一个Leader为主进程
zookeeper主要分为5个阶段,选举,发现,同步,广播
- 选举:Looking状态中选举出Leader节点,Leader的lastZXID总是最新的
- 发现:Follower节点向准Leader推送FOllOWERINFO,该信息中包含了上一周期的epoch,接受准Leader的NEWLEADER指令,检查newEpoch有效性,准Leader要确保Follower的epoch与ZXID小于或等于自身的
- 同步:将Follower与Leader的数据进行同步,由Leader发起同步指令,最总保持集群数据的一致性
- 广播:Leader广播Proposal与Commit,Follower接受Proposal与Commit;
选举
zab必须确保选举出来的leader具有最大的zxid(这和raft很像啊)。这里要注意一下,和raft一样,选举可能会出现两种结果:
- 上一轮的多数派(此时leader zxid可能不是最大的,需要同步的时候调用trunc)
- 上一轮的少数派,leader zxid真的是最大的(但是这个最大的zxid没有提交,在同步阶段提交?)
过程详解:
- 每个Follower都向其他节点发送选自身为Leader的Vote投票请求,等待回复;
- Follower接受到的Vote如果比自己的ZXID更新时则投票,并更新自身的Vote,否则拒绝投票;
- 每个Follower中维护着一个投票记录表,当某个节点收到过半的投票时,结束投票并把该Follower选为Leader,投票结束;
恢复(发现和同步)
发现
- leader生成新的zxid和epoch,接受follower发送来的FOllOWERINFO(含有当前节点的LastZXID)
- leader向follower发送NEWLEADER;Leader根据follower发送过来的LastZXID根据数据更新策略向Follower发送更新指令;
同步
- SNAP:如果follower数据太老,epoch还在上上一轮,leader将发送快照snap指令给follower同步
- DIFF:正常同步阶段
- TRUNC:如果Follower是上一轮的少数派(通过对比ztid),发送TRUNC指令让follower丢弃这段数据
广播
进入正常leader提交阶段,产生递增的zxid,接受半数投票后,再提交。
与raft的区别
我觉得zab和raft没有本质的区别,它们唯一的不同点就是如何处理上一个leader的残留日志。
- raft中,需要本轮iterm有日志提交后,才提交以前的
- zab中,在同步阶段全部解决
ZooKeeper:架构和算法的更多相关文章
- 转载:深入浅出Zookeeper(一) Zookeeper架构及FastLeaderElection机制
转载至 http://www.jasongj.com/zookeeper/fastleaderelection/: 原创文章,转载请务必将下面这段话置于文章开头处.本文转发自技术世界,原文链接 htt ...
- Zookeeper架构、ZAB协议、选举
转载:深入浅出Zookeeper(一) Zookeeper架构及FastLeaderElection机制 (nice) ZooKeeper学习第六期---ZooKeeper机制架构 一.Zookee ...
- Zookeeper架构及FastLeaderElection机制
原文链接:http://www.jasongj.com/zookeeper/fastleaderelection/ Zookeeper是什么 Zookeeper是一个分布式协调服务,可用于服务发现,分 ...
- 读<大数据日知录:架构与算法>有感
前一段时间, 一个老师建议我能够学学 '大数据' 和 '机器学习', 他说这必定是今后的热点, 学会了, 你就是香饽饽.在此之前, 我对大数据, 机器学习并没有非常深的认识, 总觉得它们是那么的缥缈, ...
- 一篇文章带你了解 ZooKeeper 架构
上一篇文章,我们讲解了 ZooKeeper 入门知识,这篇文章主要讲解下 ZooKeeper 的架构,理解 ZooKeeper 的架构可以帮助我们更好地设计协同服务. 首先我们来看下 ZooKeepe ...
- Zookeeper的选举算法和脑裂问题
ZK介绍 ZK = zookeeper ZK是微服务解决方案中拥有服务注册发现最为核心的环境,是微服务的基石.作为服务注册发现模块,并不是只有ZK一种产品,目前得到行业认可的还有:Eureka.Con ...
- ZooKeeper之FastLeaderElection算法详解
当我们把zookeeper服务启动时,首先需要做的一件事就是leader选举,zookeeper中leader选举的算法有3种,包括LeaderElection算法.AuthFastLeaderEle ...
- ZooKeeper架构设计及其应用要点
问题导读: 1.ZooKeeper的数据模型是什么 ?2.ZooKeeper应用有哪些陷阱 ?3.每个节点(ZNode)中存储的是什么?4.一个ZNode维护了一个状态结构都包含了什么?5.ZNode ...
- ZooKeeper架构设计及其应用
ZooKeeper是一个开源的分布式服务框架,它是Apache Hadoop项目的一个子项目,主要用来解决分布式应用场景中存在的一些问题,如:统一命名服务.状态同步服务.集群管理.分布式应用配置管理等 ...
随机推荐
- .NET 调试入门(一) 调试工具的使用
至于WinDbg的下载和基本配置网上到处都是,可以参考 http://www.cnblogs.com/happyhippy/archive/2007/04/08/710933.html 因为现在W ...
- 实例化MD5CryptoServiceProvider报错:此实现不是 Windows 平台 FIPS 验证的加密算法的一部分
System.InvalidOperationException: This implementation is not part of the Windows Platform FIPS valid ...
- Spring Boot - StateMachine状态机
是Spring Boot提供的状态机的现成实现. 理论(有点像工作流) 需要定义一些状态的枚举,以及一些引起状态变化的事件的枚举. 每个状态可以对应的创建一个继承自org.springframewor ...
- CefSharp禁止弹出新窗体,在同一窗口打开链接,并且支持带type="POST" target="_blank"的链接
1.实现ILifeSpanHandler接口,代码如下: using CefSharp; using CefSharp.WinForms; using System; using System.Col ...
- Redux其实很简单(原理篇)
在这一篇文章中,笔者将带大家编写一个完整的Redux,深度剖析Redux的方方面面,读完本篇文章后,大家对Redux会有一个深刻的认识. 核心API 这套代码是笔者阅读完Redux源码,理解其设计思路 ...
- docker registry 私有仓库 安装配置、查询、删除
#++++++++++++++++++++++++++++++ #docker-registry 私有仓库 #搜索,下载register镜像 docker search registry docker ...
- hdoj1575 Tr A(矩阵快速幂)
简单的矩阵快速幂.最后求矩阵的秩. #include<iostream> #include<cstring> using namespace std; ; int n,k; s ...
- SharedFile System Master Slave(共享文件系统)做ActiveMQ集群
WINDOWS环境下:http://www.apache.org/dyn/closer.cgi?path=/activemq/apache-activemq/5.9.0/apache-activemq ...
- node 无脑生成小程序二维码图
RT 新建createwxaqrcode.js: const request = require('request') const fs = require('fs') // eg:生成购物车列表圆形 ...
- 加快mysql导入导出速度
MySQL导出的SQL语句在处理百万级数据的时候,可能导入要花几小时.在导出时合理使用几个参数,可以大大加快导入的速度. -e 使用包括几个VALUES列表的多行INSERT语法; --max_all ...