由于ZooKeeper的数据模型简单且全部在内存中,ZooKeeper的速度非常快。它提供了一系列保证:
• 顺序一致性
原子性
单一视图
可靠性
实时性
下面将结合源码(3.4.10版本)介绍下,ZooKeeper如何保证单一视图(Single System Image)。

一、ZooKeeper单一视图定义

单一视图(Single System Image)是指同一个客户端无论连接到集群中的哪台机器上,都将会看到服务的同一视图。即:同一客户端无论什么时候连接到哪个服务器上,都不会看到比自己之前看到的数据更早版本的数据。
单一视图保证是由ZooKeeper客户端与服务端建立连接请求时的一些校验操作实现的,具体如何实现?需要介绍下客户端到服务端连接建立的过程。

二、客户端到服务端连接建立以及请求处理流程

客户端到服务端建立连接流程基本如下:
客户端通过服务器连接字符串、timeout等参数,创建客户端实例,启动客户端相关处理线程
客户端服务端之间创建socket连接
客户端服务端发送连接建立请求
服务端接收到连接建立请求后,会验证是否合法,决定是否建立连接
♦ 如果连接合法,那么将与客户端之间建立起连接,并开始请求处理流程
如果连接不合法,那么将拒绝连接,客户端将会寻找集群中的其他服务器,尝试建立连接
上述描述的流程如下图所示:
下面将结合源码(3.4.10版本)具体分析以上流程。

初始化

当创建ZooKeeper客户端实例(new ZooKeeper)的时候,会初始化客户端的一些设置:除了设置watcher、host提供器(HostProvider)之外,还会创建ClientCnxn实例。
/**
* TIPS:ClientCnxn类功能介绍
* ClientCnxn类主要负责客户端的socket I/O功能,同时还提供了一个透明的到连接可用服务器的理由功能
* TIPS:host提供器(HostProvider)
* 这里介绍的客户端是ZooKeeper提供的原生客户端,其他客户端暂时不做分析。host提供器默认为StaticHostProvider,当连接新的服务器时,采用的是轮询列表中下一个服务器的方案
*/
ClientCnxn初始化的时候启动两个线程:消息收发线程SendThread和事件处理线程EventThread
消息收发线程:处理消息发送、消息接收以及心跳处理
事件处理线程:主要处理节点相关事件以及连接状态事件
/**
* TIPS:节点相关事件包括
* 节点创建(NodeCreated)、节点删除(NodeDeleted)、节点数据更新(NodeDataChanged)、子节点变化(NodeChildrenChanged,包括子节点的创建和删除)
*/
这里主要涉及到消息收发线程。消息收发线程SendThread启动后,会判断与服务器之间是否有连接,如果没有,则会根据host提供器选择集群中的一台服务器建立socket连接,同时发送建立连接的请求。以下将以NIO通信(ZooKeeper3.4.0版本开始提供netty通信方式)为例。

客户端连接建立过程

ClientCnxn类中的SendThread线程里,当检测与服务器之间没有建立的socket连接时,会通过ClientCnxnSocket创建连接(clientCnxnSocket.connect(addr),NIO通信通过ClientCnxnSocketNIO类完成),主要完成以下步骤:
创建与服务端的socket连接
注册selector,并发送建立连接请求到服务端
具体ClientCnxnSocketNIO中连接建立方法如下:
在注册selector和建立连接的过程中,会通过消息收发线程SendThread的primeConnection方法发送连接请求,发送连接建立请求具体如下源码所示:
ClientCnxn.SendThread类中,创建连接请求包,这个包里将会包含客户端上次收到服务端反馈的事务id:zxid信息(客户端每次请求响应,服务端都会将最新的事务id作为消息头发送给客户端)。消息收发线程会通过建立的socket将该请求发送到服务端。
/**
* TIPS:事务id - zxid
* ZooKeeper事务都需要由leader节点处理,每个事务都有一个唯一的标识号,称之为事务id,记做zxid
* 表示:ZooKeeper使用64位long型整数来表示zxid
* 含义:前32位为epoch(此处翻译为时代,每发生一轮选举,epoch增一,因此可以认为一个leader当选的代表);后32位为当前leader处理事务的一个递增序列号
* 深层含义:zxid为递增序列,因此zxid可以代表当前ZooKeeper服务器上的数据版本:zxid越大代表数据版本越新
*/
建立连接请求包信息具体如下所示:

服务端连接建立过程

在ZooKeeper服务端,NIO通信接收连接请求的类为NIOServerCnxn。服务端接收到连接请求后,会通过ZooKeeperServer类的processConnectRequest来单独处理连接建立的请求。服务端读取连接请求过程具体如下:
ZooKeeperServer类的processConnectRequest方法中,主要分为以下几步:
解析请求包数据
获取该客户端之前收到的zxid信息
验证客户端当前看到的数据版本信息是否比服务器的数据版本新,如果客户端当前看到的数据版本比较新,那么服务器将直接拒绝连接建立请求
服务端处理连接请求,验证数据版本zxid信息的过程具体如下:

请求处理过程

服务端:每次服务器端处理客户端的请求,FinalRequestProcessor都会将当前服务器处理的最新的zxid放在响应头中返回。具体响应构建如下:

客户端:客户端收发线程接收到服务端的响应后,解析结果中的zxid,更新自己的lastZxid值信息,readResponse方法中处理如下:

三、单一视图保证

从上面的源码分析可知:当客户端正常连接集群中的一台服务器时,每次请求响应都会返回所连接的服务器上所处理的最新的事务id并进行记录。当客户端由于各种原因导致与服务器之间断连时,客户端将会以自己看到代表数据版本信息的zxid一起发送给服务端,请求建立连接。服务端在收到连接建立请求时,会进行判断:自己的数据版本没有客户端之前看到的数据版本新,服务端将会拒绝连接建立。从而保证客户端不会连接到数据版本比自己之前看到的旧的服务器上,因此不会请求到老版本的数据,从而保证了单一视图特性。
下面通过一个简单示例,来说明整个过程,如下图所示:
 
 
假设:集群中有三台服务器A/B/C,A为leader,其余两台为follower。
/**
* TIPS:ZooKeeper服务器角色说明
* Leader:领导者,是ZooKeeper集群的核心,负责集群各角色之间的协调和调度、事务请求的调度和处理,保证事务的顺序性以及数据一致性
* Follower:追随者,可独立处理非事务请求,转发事务请求给Leader,参与事务的投票以及Leader选举投票
* Observer:观察者,可独立处理非事务请求,转发事务请求给Leader,但是不参与各种投票,可提高整个集群的非事务请求处理能力
* 其中,Follower和Observer称之为Learner
*/
某一时刻,服务器A与C数据一致,zxid均为5,服务器B的zxid为4。当出现以下情况时,客户端与服务端的处理过程:
♦ 客户端client此时连接到服务器C,并且最后一个请求响应返回的zxid为5,client保存到lastZxid中
♦ 由于client与服务器C之间存在网络问题导致client与C之间断连。client开始重新与集群建立连接
♦ client随机到服务器B,开始与B建立连接
♦ 发送的连接建立请求中,携带lastZxid为5
♦ 服务器B接收到client的连接建立请求,判断自己的zxid与client传过来的lastZxid信息。发现客户端所看到的数据版本要比自己新(lastZxid > zxid),因此拒绝了client的建立连接的请求
♦ client与服务器B建立连接失败,开始新一轮尝试,向服务器A发送建立连接请求
♦ 服务器A同样去对比zxid以及客户端的lastZxid信息,发现版本一致,允许连接建立。至此,client与集群中的服务器A建立了新的连接。可以开始请求的发送与处理过程

四、参考资料

1、zookeeper整体概述:http://zookeeper.apache.org/doc/current/zookeeperOver.html
2、Observer角色说明:https://zookeeper.apache.org/doc/r3.3.3/zookeeperObservers.html

ZooKeeper如何保证单一视图的更多相关文章

  1. ZooKeeper保证之单一视图(Single System Image)

    由于ZooKeeper的数据模型简单且全部在内存中,ZooKeeper的速度非常快.它提供了一系列保证(Guarantees): • 顺序一致性(Sequential Consistency) • 原 ...

  2. Zookeeper并不保证读取的是最新数据

    Zookeeper并不保证读取的是最新数据 原文地址:http://www.crazyant.net/2120.html 如果是对zk进行读取操作,读取到的数据可能是过期的旧数据,不是最新的数据. 已 ...

  3. Zookeeper 如何保证分布式系统数据一致性

    写在前面 分布式架构出现后,越来越多的分布式系统会面临数据一致性的问题.目前,ZooKeeper 是在解决分布式数据一致性上最成熟稳定且被大规模应用的工业级解决方案. ZooKeeper 保证 分布式 ...

  4. zookeeper有几种部署模式? zookeeper 怎么保证主从节点的状态同步?

    一.zookeeper的三种部署模式 Zookeeper 有三种部署模式分别是单机模式.伪集群模式.集群模式.这三种模式在不同的场景下使用: 单机部署:一般用来检验 Zookeeper 基础功能,熟悉 ...

  5. ZooKeeper 如何保证数据一致性?

    在分布式场景中,ZooKeeper 的应用非常广泛,比如数据发布和订阅.命名服务.配置中心.注册中心.分布式锁等. 在分布式场景中,ZooKeeper 的应用非常广泛,比如数据发布和订阅.命名服务.配 ...

  6. Zookeeper 保证了如下分布式一致性特性?

    1.顺序一致性 2.原子性 3.单一视图 4.可靠性 5.实时性(最终一致性) 客户端的读请求可以被集群中的任意一台机器处理,如果读请求在节点上注册了 监听器,这个监听器也是由所连接的 zookeep ...

  7. 【分布式】Zookeeper与Paxos

    一.前言 在学习了Paxos在Chubby中的应用后,接下来学习Paxos在开源软件Zookeeper中的应用. 二.Zookeeper Zookeeper是一个开源的分布式协调服务,其设计目标是将那 ...

  8. Zookeeper 的学习与运用

    引子 云计算越来越流行的今天,单一机器处理能力已经不能满足我们的需求,不得不采用大量的服务集群.服务集群对外提供服务的过程中,有很多的配置需要随时更新,服务间需要协调工作,这些信息如何推送到各个节点? ...

  9. ZooKeeper概述(转)

    译自http://zookeeper.apache.org/doc/trunk/zookeeperOver.html ZooKeeper是一个用于分布式应用的开源分布式协调服务.它提供了简单的原语集合 ...

随机推荐

  1. Listview嵌套Listview

    今天做项目,打算模仿淘宝的订单管理,需要Listview嵌套Listview,都是两个控件都是沿着一个方向滑动的,嵌套在一起不幸福,以下是解决方案,打个笔记,以后估计还得用: 其中onMeasure函 ...

  2. CS窗体程序数据列表分页

    以前,觉得winform程序分页很无趣,也没实际意义,直到近期的项目实践中让我认识到原来winform数据列表分页也是非常有必要的,因为由于数据量过大的情况,当窗体在初始加载数据的时候如果不做条件的限 ...

  3. HTML 使用jQuery选中复选框 简易版

    <html><head>   <meta charset="utf-8">   <script src="jquery-1.7. ...

  4. Nomad入门

    Nomad 简介 Nomad是一个管理机器集群并在集群上运行应用程序的工具. Nomad的特点: 支持docker,Nomad的job可以使用docker驱动将应用部署到集群中. Nomad安装在li ...

  5. wkwebview加载本地html的要点

    项目中有些页面,我采用了html页面开发,然后用wkwebview加载的设计.在加载过程中遇见了一些问题,在这里进行一些记载和讨论.如有不同意见欢迎进行评论沟通. 问题时候这样的: 在webview的 ...

  6. 整合SSH时,遇到了org.springframework.beans.factory.BeanCreationException错误

    严重: StandardWrapper.Throwableorg.springframework.beans.factory.BeanCreationException: Error creating ...

  7. openstack集群环境准备

    #0.openstack集群环境准备 openstack pike 部署 目录汇总 http://www.cnblogs.com/elvi/p/7613861.html #openstack集群环境准 ...

  8. 关于ftp的学习:ftp很多人都会用。但会用,不代表我们真正了解它。

    ftp.sftp.ftps,您是否是也跟我一样搞不清楚他们的真正意义.它们之间有关联吗(究竟是何种关联),有区别吗(区别倒地在哪里). 亦或是以为自己知道它们,可我们真的了解并认识它们了吗? 如果您被 ...

  9. String、StringBuilder和StringBuffer

    1.string不可变性 java的docs有这样一句话:Strings are constant; their values cannot be changed after they are cre ...

  10. 可以在手机上看电脑本地html步骤,我自己总结的哦!

    1.打开控制面板 2.打开程序和功能 3.打开或关闭功能 4.internet信息服务展开后里面所有的都要选中 5.回到桌面,然后右键计算机,选择'管理' 6.先在E盘或者D盘创建一个文件夹,自己随意 ...