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. (二)从分布式一致性谈到CAP理论、BASE理论

    问题的提出 在计算机科学领域,分布式一致性是一个相当重要且被广泛探索与论证问题,首先来看三种业务场景. 1.火车站售票 假如说我们的终端用户是一位经常坐火车的旅行家,通常他是去车站的售票处购买车票,然 ...

  2. Delphi Language Overview

    Delphi is a high-level, compiled, strongly typed language that supports structured and object-orient ...

  3. Python学习-36.Python中的字典解释

    具体同列表解释,也是使用if来进行过滤 例子,生成一个新的字典,并且是原来字典的键值交换. mydict={'Tom':18,'Mary':20} print({value:key for key,v ...

  4. Tmux与Oh-my-zsh环境整合

      在Mac客户端配置好oh-my-zsh后,安装了tmux应用,但是每次进入tmux都会提示以下警告信息,虽然并没有实际上的影响,但是还是感觉每次弹出窗口后会很闹心,所以采用如下配置进行解决. 报错 ...

  5. 基于CORS的GeoServer跨域访问策略

    GeoServer的跨域访问问题,有多种解决方法,本文介绍一种基于CORS的GeoServer跨域访问方法. CORS简介 CORS是一个W3C标准,全称是"跨域资源共享"(Cro ...

  6. Sql查询两个时间段有重叠的记录

    这个问题看上去简单,但是想了很久,最后发现,自己的思路有点乱. 下面四条时间段都和最上面那个有重叠的关系,就是这么个意思. 这里是问题的答案: 2个时间: a_start, a_end b_start ...

  7. python 实现判断一个用户输入字符串是否是小数的小程序

    要判断一个字符串是否是小数:1先判断小数点的个数,即如果是小数,则必须有且仅有一个'.'号2再分别判断'.'号的左右两边是否是数字: 判断左边时,如果负数,则左边包含'-'号:必须以'-'号开头(校验 ...

  8. asp.net core 的用户注册功能——Identity上手

    首先请using这个类库. using Microsoft.AspNetCore.Identity; 这个类库老牛逼了,首先是包含了一个IdentityUser类.我们可以自己写一个User类继承Id ...

  9. NET Core2.1 WEB老项目迁移

    .NET Core2.1 版本新增功能不在赘述. NET Core2.1更新链接 如果开发需要安装Net Core2.1SDK,及Runtime. .NET Core2.1安装地址. 接下来是WEB ...

  10. App.config使用方法(基础教程)

    WPF程序中的App.config文件是应用程序中经常使用的一种配置文件,System.Configuration.dll文件中提供了大量的读写的配置,是一种很高效的程序配置方式. 1.首先在工程中配 ...