由于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. R-CNN论文翻译

    R-CNN论文翻译 Rich feature hierarchies for accurate object detection and semantic segmentation 用于精确物体定位和 ...

  2. 简单说下 Winform 的分页快速开发框架必须要实现的几个功能之一

    简单说下 Winform 的分页快速开发框架必须要实现的几个功能之一 分页非为前端分页  和 后端分页,前端分页只有适用于B/S,B/S的呈现速度远远不如C/S,而C/S则没有这个问题,所以分页必然是 ...

  3. 第四届河南省ACM SUBSTRING 字符串处理

    SUBSTRING 时间限制: 1 Sec  内存限制: 128 MB 提交: 17  解决: 5 [提交][状态][讨论版] 题目描述 You are given a string input. Y ...

  4. 使用tail命令实时查看日志文件

    [Shell] 纯文本查看 复制代码 ? 1 tail -f /日志文件 好了.就这样用.简单吧    退出ctrl+C

  5. WampSever 安装问题解析

    鉴于有些电脑安装wampsever出现的几种问题 [1] 2.2版本问题 这里端口配置正确,本地服务器没有开启(也就是80端口没有占用) 还是出现这种情况 也就是Apache service 和 PH ...

  6. Jsoup(一)Jsoup详解(官方)

    一.Jsoup概述 1.1.简介     jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址.HTML文本内容.它提供了一套非常省力的API, 可通过DOM,CSS以及类似于jQu ...

  7. oracle概念

    .DDL 数据定义语言 create alter drop truncate .DML 数据操作语言 insert delete update select .TCL 事务控制语言 commit ro ...

  8. 刚从it培训班出来的学生如何走向工作岗位

    大家好,这是我本人在博客园的第一篇博文. 相信很多人都是从 it 培训班学习然后加入到程序员这个大家族,或多或少,有些人会和博主有一样的感受,所以此篇博文我们不讨论技术,博主也是刚从培训班坑里跳出来正 ...

  9. 对datatable进行简单的操作

    筛选出datatable中c_level=1的数据 dataRow[] rows = dt.Select("c_level=0"); 克隆表dt的结构到表dt,并将dt的数据复制到 ...

  10. 在centos7中手动编译greenplum

    一.编译环境 Linux version 3.10.0-327.el7.x86_64 (builder@kbuilder.dev.centos.org) (gcc version 4.8.3 2014 ...