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,临时节点有变更可以及时通知。

任务分配

  1. 新任务到来:在tasks目录下创建任务节点
  2. 任务分配:监控进程感知到tasks目录下的节点变化,触发任务分配。图中task1分配到machine1的目录下,代表task1分配给machine1
  3. 任务执行:machine1发现自己目录下的任务,执行该任务。结束后删除machine1目录下的task1和task目录下的task1。

锁服务

创建互斥锁

  1. 在l目录下,创建以lock为前缀的递增临时节点,返回节点编号
  2. 获取l目录下所有节点信息
  3. 如果刚刚创建的编号是所有节点编号最小的(最先创建节点的),获得锁
  4. 没有获得锁,进入第2步

创建读写锁

创建写锁

  1. 在l目录下,创建以write为前缀的递增临时节点,返回节点编号
  2. 获取l目录下所有节点信息
  3. 如果刚刚创建的编号是所有节点编号最小的(最先创建节点的),获得锁
  4. 没有获得锁,进入第2步

创建读锁

  1. 在l目录下,创建以read为前缀的递增临时节点,返回节点编号
  2. 获取l目录下所有节点信息
  3. 如果刚刚创建的编号比所有write前缀的编号小,获得读锁
  4. 没有获得锁,进入第2步

释放锁

删除临时节点

双向路障同步

任务统一开始

  1. 在路障节点下创建当前任务节点,代表该任务到达路障
  2. 检测路障节点下任务个数是否足够,足够代表可以继续统一执行

任务统一离开

  1. 任务结束后,任务路障节点下的任务节点
  2. 如果路障节点下没有任务节点,代表所有任务已经执行结束

ZAB协议(ZooKeeper Atomic Broadcast原子消息广播协议)

zab协议所有事务请求必须由leader协调,首先leader发起proposal消息,大多数server同意后,然后leader发送commit消息。

zxid编号

  1. 低32位为计数器,客户端每次请求+1
  2. 高32位为epochID,每次选举新leader+1

状态和阶段

  1. Looking:系统刚启动时或者Leader崩溃后正处于选举状态
  2. Following:Follower节点所处的状态,Follower与Leader处于数据同步阶段
  3. Leading:Leader所处状态,当前集群中有一个Leader为主进程

zookeeper主要分为5个阶段,选举,发现,同步,广播

  1. 选举:Looking状态中选举出Leader节点,Leader的lastZXID总是最新的
  2. 发现:Follower节点向准Leader推送FOllOWERINFO,该信息中包含了上一周期的epoch,接受准Leader的NEWLEADER指令,检查newEpoch有效性,准Leader要确保Follower的epoch与ZXID小于或等于自身的
  3. 同步:将Follower与Leader的数据进行同步,由Leader发起同步指令,最总保持集群数据的一致性
  4. 广播:Leader广播Proposal与Commit,Follower接受Proposal与Commit;

选举

zab必须确保选举出来的leader具有最大的zxid(这和raft很像啊)。这里要注意一下,和raft一样,选举可能会出现两种结果:

  1. 上一轮的多数派(此时leader zxid可能不是最大的,需要同步的时候调用trunc)
  2. 上一轮的少数派,leader zxid真的是最大的(但是这个最大的zxid没有提交,在同步阶段提交?)

过程详解:

  1. 每个Follower都向其他节点发送选自身为Leader的Vote投票请求,等待回复;
  2. Follower接受到的Vote如果比自己的ZXID更新时则投票,并更新自身的Vote,否则拒绝投票;
  3. 每个Follower中维护着一个投票记录表,当某个节点收到过半的投票时,结束投票并把该Follower选为Leader,投票结束;

恢复(发现和同步)

发现

  1. leader生成新的zxid和epoch,接受follower发送来的FOllOWERINFO(含有当前节点的LastZXID)
  2. leader向follower发送NEWLEADER;Leader根据follower发送过来的LastZXID根据数据更新策略向Follower发送更新指令;

同步

  1. SNAP:如果follower数据太老,epoch还在上上一轮,leader将发送快照snap指令给follower同步
  2. DIFF:正常同步阶段
  3. TRUNC:如果Follower是上一轮的少数派(通过对比ztid),发送TRUNC指令让follower丢弃这段数据

广播

进入正常leader提交阶段,产生递增的zxid,接受半数投票后,再提交。

与raft的区别

我觉得zab和raft没有本质的区别,它们唯一的不同点就是如何处理上一个leader的残留日志。

  • raft中,需要本轮iterm有日志提交后,才提交以前的
  • zab中,在同步阶段全部解决

ZooKeeper:架构和算法的更多相关文章

  1. 转载:深入浅出Zookeeper(一) Zookeeper架构及FastLeaderElection机制

    转载至 http://www.jasongj.com/zookeeper/fastleaderelection/: 原创文章,转载请务必将下面这段话置于文章开头处.本文转发自技术世界,原文链接 htt ...

  2. Zookeeper架构、ZAB协议、选举

    转载:深入浅出Zookeeper(一) Zookeeper架构及FastLeaderElection机制  (nice) ZooKeeper学习第六期---ZooKeeper机制架构 一.Zookee ...

  3. Zookeeper架构及FastLeaderElection机制

    原文链接:http://www.jasongj.com/zookeeper/fastleaderelection/ Zookeeper是什么 Zookeeper是一个分布式协调服务,可用于服务发现,分 ...

  4. 读<大数据日知录:架构与算法>有感

    前一段时间, 一个老师建议我能够学学 '大数据' 和 '机器学习', 他说这必定是今后的热点, 学会了, 你就是香饽饽.在此之前, 我对大数据, 机器学习并没有非常深的认识, 总觉得它们是那么的缥缈, ...

  5. 一篇文章带你了解 ZooKeeper 架构

    上一篇文章,我们讲解了 ZooKeeper 入门知识,这篇文章主要讲解下 ZooKeeper 的架构,理解 ZooKeeper 的架构可以帮助我们更好地设计协同服务. 首先我们来看下 ZooKeepe ...

  6. Zookeeper的选举算法和脑裂问题

    ZK介绍 ZK = zookeeper ZK是微服务解决方案中拥有服务注册发现最为核心的环境,是微服务的基石.作为服务注册发现模块,并不是只有ZK一种产品,目前得到行业认可的还有:Eureka.Con ...

  7. ZooKeeper之FastLeaderElection算法详解

    当我们把zookeeper服务启动时,首先需要做的一件事就是leader选举,zookeeper中leader选举的算法有3种,包括LeaderElection算法.AuthFastLeaderEle ...

  8. ZooKeeper架构设计及其应用要点

    问题导读: 1.ZooKeeper的数据模型是什么 ?2.ZooKeeper应用有哪些陷阱 ?3.每个节点(ZNode)中存储的是什么?4.一个ZNode维护了一个状态结构都包含了什么?5.ZNode ...

  9. ZooKeeper架构设计及其应用

    ZooKeeper是一个开源的分布式服务框架,它是Apache Hadoop项目的一个子项目,主要用来解决分布式应用场景中存在的一些问题,如:统一命名服务.状态同步服务.集群管理.分布式应用配置管理等 ...

随机推荐

  1. .NET 调试入门(一) 调试工具的使用

    至于WinDbg的下载和基本配置网上到处都是,可以参考 http://www.cnblogs.com/happyhippy/archive/2007/04/08/710933.html   因为现在W ...

  2. 实例化MD5CryptoServiceProvider报错:此实现不是 Windows 平台 FIPS 验证的加密算法的一部分

    System.InvalidOperationException: This implementation is not part of the Windows Platform FIPS valid ...

  3. Spring Boot - StateMachine状态机

    是Spring Boot提供的状态机的现成实现. 理论(有点像工作流) 需要定义一些状态的枚举,以及一些引起状态变化的事件的枚举. 每个状态可以对应的创建一个继承自org.springframewor ...

  4. CefSharp禁止弹出新窗体,在同一窗口打开链接,并且支持带type="POST" target="_blank"的链接

    1.实现ILifeSpanHandler接口,代码如下: using CefSharp; using CefSharp.WinForms; using System; using System.Col ...

  5. Redux其实很简单(原理篇)

    在这一篇文章中,笔者将带大家编写一个完整的Redux,深度剖析Redux的方方面面,读完本篇文章后,大家对Redux会有一个深刻的认识. 核心API 这套代码是笔者阅读完Redux源码,理解其设计思路 ...

  6. docker registry 私有仓库 安装配置、查询、删除

    #++++++++++++++++++++++++++++++ #docker-registry 私有仓库 #搜索,下载register镜像 docker search registry docker ...

  7. hdoj1575 Tr A(矩阵快速幂)

    简单的矩阵快速幂.最后求矩阵的秩. #include<iostream> #include<cstring> using namespace std; ; int n,k; s ...

  8. SharedFile System Master Slave(共享文件系统)做ActiveMQ集群

    WINDOWS环境下:http://www.apache.org/dyn/closer.cgi?path=/activemq/apache-activemq/5.9.0/apache-activemq ...

  9. node 无脑生成小程序二维码图

    RT 新建createwxaqrcode.js: const request = require('request') const fs = require('fs') // eg:生成购物车列表圆形 ...

  10. 加快mysql导入导出速度

    MySQL导出的SQL语句在处理百万级数据的时候,可能导入要花几小时.在导出时合理使用几个参数,可以大大加快导入的速度. -e 使用包括几个VALUES列表的多行INSERT语法; --max_all ...