flink 入门程序-wordcount flink 配置项介绍 在 Mac 上搭建 Flink 的开发环境 lambda 架构问题的阅读笔记 IDEA常用插件 Mybatis源码分析(1) - Mybatis关键类 Mybatis源码分析(1) - Mybatis包目录简介 tair 1:tair学习 dataflow论文阅读笔记 Polysh的安装使用 SnappyData排序函数比较 Squirrel-sql客户端连接SnappyData手册 在虚拟机里显示Hello World spark学习博客推荐 SnappyData学习博客和官网文章 Docker常用命令 MyBatis支持的OGNL语法 mysql性能优化 mysql性能优化-优化Sql语句 java各版本新特性 mac上命令行操作 explain输出格式 从文件中读取zk配置——ZooKeeper编程技能(1) git进阶经验-从项目中删除移除的目录 Mongodb 学习之shell命令操作(3) mysql命令 git进阶经验-从多模块项目中分理子模块 从零学hadoop-搭建基础(单点)的Hdfs环境 ZooKeeper集群操作脚本 Vue安装使用 2 初学JVM之问答式记住类加载机制 2 初学JVM之问答式记住虚拟机性能监控与故障处理工具 2 初学JVM之问答式记住垃圾收集器 log4j2 按天生成日志文件 1 初学JVM之问答式记住java自动内存管理 MapReduce学习心得之MapReduce初识 log4j2 日志发送到kafka配置实战 log4j2 日志配置实战 Mongodb 学习之shell命令操作(二) Mongodb 学习之linux版本安装(一) Dubbo的初级使用 ServiceLoader内部实现分析 ServiceLoader 初级应用 log4j日志发送邮件配置实战 红黑树笔记 IDEA首次使用之前的配置 java源码学习之Enum java源码学习之String 自定义Spring tag标签 编写一键发布脚本 记一次Spring Scheduler莫名不执行的一次堆栈分析 kafka的基本操作 nginx 5:Nginx内部变量 nginx 4:Nginx日志管理 提高hadoop配置效率的shell脚本 Hive编程指南之一 Hive的安装 Ambari服务器安装 Ambari服务器管理集群 HBase分布式安装 windows下Eclipse远程调试运行MR程序 基于MapReduce新的API的编程Demo-wordCount window下Eclipse远程只读HDFS上的文件 YARN上节点标签 编写第一个MapReduce的wordcount程序 NodeManager的重启 搭建JStorm集群 YARN上的web应用代理 YARN上的ResourceManager的高可用方案 配置vmware中的虚拟机使用宿主机的共享网络 YARN架构简述 HDFS 架构 Spring的统一异常处理机制 Tomcat 配置服务 HDFS的viewfs指南 HDFS的Federation之路 HDFS基于QJM的HA之路 nginx 3:Nginx反向代理 mybatis操作主体流程 1.正则表达式学习-基础篇 log4j日志配置详解 mysql的时间函数 nginx 2:Nginx模块配置理论及实战 HashMap相关解析和测试文章 工作一年后的面试 用私有构造器或枚举类型强化Singleton属性 java中比较重要的图 mybatis处理枚举类 mybatis集成进spring Spring比较重要的几个截图 21.hadoop-2.7.2官网文档翻译-使用NFS的HDFS高可用性 20.hadoop-2.7.2官网文档翻译-使用仲裁日志管理器的HDFS高可用性 markdown在jekyll中支持的一些操作 Spring项目中配置sl4j和log4j的日志配置 19.hadoop-2.7.2官网文档翻译-HDFS命令指南 Spring的profile机制介绍 mybatis-generator反向生成 18.hadoop-2.7.2官网文档翻译-HDFS用户指南 17.hadoop-2.7.2官网文档翻译-实现Hadoop中Dapper-like追踪 16.hadoop-2.7.2官网文档翻译-Hadoop的KMS(key 管理服务器)-文档集 15.hadoop-2.7.2官网文档翻译-Hadoop的http web认证 14.hadoop-2.7.2官网文档翻译-服务级别的授权指南 13.hadoop-2.7.2官网文档翻译-安全模式中的Hadoop 09.hadoop-2.7.2官网文档翻译-Hadoop命令行微型集群 12.hadoop-2.7.2官网文档翻译-机架感知 11.hadoop-2.7.2官网文档翻译-代理用户-超级用户对其他用户的代表 10.hadoop-2.7.2官网文档翻译-原生库指南 08.hadoop-2.7.2官网文档翻译-文件系统规范 07.hadoop-2.7.2官网文档翻译-Hadoop接口类别 (转)浅析 Decorator 模式,兼谈 CDI Decorator 注解 06.hadoop-2.7.2官网文档翻译-Hadoop的兼容性 05.hadoop-2.7.2官网文档翻译-文件系统命令 04.hadoop-2.7.2官网文档翻译-Hadoop命令指南 03.hadoop-2.7.2官网文档翻译-集群安装 02.hadoop-2.7.2官网文档翻译-单节点集群安装 01.hadoop-2.7.2官网文档翻译-概述 Http 协议相应状态码大全及常用状态码 IDEA快捷键 JDBC Type与Java Type redis 12:redis 操作集合 mybatis-generator错误集合 redis 11:redis 错误集合 nginx 1:nginx的安装 redis 10:redis cluster命令操作 redis 9:redis实例集群安装 java设计模式 hadoop集群学习笔记(1) Apache Shiro 简介 vim编辑神器的进阶命令 Eclipse配置 Eclipse快捷键 Linux 测试题 Linux脚本学习(1) Linux启动简要过程 Centos7上安装Mysql hadoop集群学习笔记(1) (转)分布式发布订阅消息系统 Kafka 架构设计 maven 命令 Kafka集群安装 Kafka初步使用 redis 8:redis server 和 scripting命令操作 redis 7:redis transaction 和 connection命令操作 redis 6:redis hash 命令操作 redis 5:redis sorted_set 命令操作 搭建本地Jekyll+Markdown+Github的开发环境 Spring源码阅读笔记(2) redis 4:redis set命令操作 Spring添加任务调度配置 redis 3:Redis list命令操作 redis 2:redis 一般命令操作 redis 1:redis单机安装笔记 redis 0:redis配置属性描述 Spring源码阅读笔记(1) spark 错误集锦 spark集群安装 Linux 基本命令操作 Hadoop错误信息处理 Hadoop代码拾忆 从零开始搭建spring-springmvc-mybatis-mysql和dubbo项目 java知识点札记 java排错 Google Java Style 中文版 git进阶经验 github使用经验 MongoDB用户角色授权与AUTH启用 MongoDB 命令 MongoDB 特定规范 Spring MVC实现跳转的几种方式 史上最全最强SpringMVC详细示例实战教程 Spring 零星笔记 js中(function(){…})()立即执行函数写法理解 如何解决跨域问题 创建ajax简单过程 前端定位 设置MYSQL允许通过IP访问 mybatis异常 :元素内容必须由格式正确的字符数据或标记组成 如何为 WordPress 绑定多个域名的方法s WordPress工作原理之程序文件执行顺序(传说中的架构源码分析) Spring源码导入Eclipse中 基于PHPnow搭建Eclipse开发环境 解决wordpress首页文章内容截断处理的几种方法 ZooKeeper理论知识 ZooKeeper集群安装配置 Git常用命令速查表 Linux 4:磁盘与文件系统管理 Linux 3:文件与目录管理 Linux 2:文件权限与目录配置 Markdown输入LaTeX数学公式
从零学hadoop-搭建基础(单点)的Hdfs环境 MapReduce学习心得之MapReduce初识 Ambari服务器安装 Ambari服务器管理集群 windows下Eclipse远程调试运行MR程序 基于MapReduce新的API的编程Demo-wordCount window下Eclipse远程只读HDFS上的文件 YARN上节点标签 编写第一个MapReduce的wordcount程序 NodeManager的重启 YARN上的web应用代理 YARN上的ResourceManager的高可用方案 YARN架构简述 HDFS 架构 HDFS的viewfs指南 HDFS的Federation之路 HDFS基于QJM的HA之路 21.hadoop-2.7.2官网文档翻译-使用NFS的HDFS高可用性 20.hadoop-2.7.2官网文档翻译-使用仲裁日志管理器的HDFS高可用性 19.hadoop-2.7.2官网文档翻译-HDFS命令指南 18.hadoop-2.7.2官网文档翻译-HDFS用户指南 17.hadoop-2.7.2官网文档翻译-实现Hadoop中Dapper-like追踪 16.hadoop-2.7.2官网文档翻译-Hadoop的KMS(key 管理服务器)-文档集 15.hadoop-2.7.2官网文档翻译-Hadoop的http web认证 14.hadoop-2.7.2官网文档翻译-服务级别的授权指南 13.hadoop-2.7.2官网文档翻译-安全模式中的Hadoop 09.hadoop-2.7.2官网文档翻译-Hadoop命令行微型集群 12.hadoop-2.7.2官网文档翻译-机架感知 11.hadoop-2.7.2官网文档翻译-代理用户-超级用户对其他用户的代表 10.hadoop-2.7.2官网文档翻译-原生库指南 08.hadoop-2.7.2官网文档翻译-文件系统规范 07.hadoop-2.7.2官网文档翻译-Hadoop接口类别 06.hadoop-2.7.2官网文档翻译-Hadoop的兼容性 05.hadoop-2.7.2官网文档翻译-文件系统命令 04.hadoop-2.7.2官网文档翻译-Hadoop命令指南 03.hadoop-2.7.2官网文档翻译-集群安装 02.hadoop-2.7.2官网文档翻译-单节点集群安装 01.hadoop-2.7.2官网文档翻译-概述 hadoop集群学习笔记(1) hadoop集群学习笔记(1) Hadoop错误信息处理 Hadoop代码拾忆

ZooKeeper理论知识

2015年04月04日
摘要:初识ZooKeeper

1. 简介

zookeeper是Google的Chubby的一个开源实现,是hadoop的分布式协调服务

ZooKeeper的是分布式应用的分布式,开放源码的协调服务。它公开了一套简单的分布式应用程序可以建立在为同步,配置维护,组服务和命名实施更高级别的服务原语集。它被设计为易于编程,使用熟悉的文件系统目录树结构风格的数据模型。它运行在Java中,并支持Java和C。

协调服务是出了名很难得到正确。它们特别容易出错,如竞态条件和死锁。背后的ZooKeeper的动机是缓解分布式应用程序从头开始实施协调服务的责任。

2. Zk的设计目标

  • a.简单化:

通过共享体系的命名空间进行协调,与文件系统相似,有一些数据寄存器组成,被称为Znode,与文件和目录类似。与典型的文件系统不同的是,Zk的数据是放在内存中的,因此zk可以达到高吞吐量、低延迟。 Zk能用在大型、分布式的系统。 严格的序列访问控制意味者复杂的控制源可以用在客户端上。

  • b.健壮性:

zk互相知道其他服务器存在。维护一个处于内存中的状态镜像,以及一个位于存储器中的交换日志和快照。只要大部分服务器可用,zk服务就可用。

客户端连接到一个单一的ZooKeeper服务器。客户机维护通过它发送请求时,获取响应,获取观看事件,并发送心脏跳动一个TCP连接。如果TCP连接到服务器断开,客户端将连接到不同的服务器。

  • c.有序性:

zk为每次更新赋予一个版本号,全局有序。

  • d.速度优势:

去读主要负载时尤其快,当读操作比写操作多时,性能会更好。

  • e.Zk还有原子性、单系统镜像、可靠性和实效性特点。

3.数据模型和分级名字空间

ZooKeeper提供的namespace很像标准的文件系统,名称是用斜杠(/)分隔路径元素的序列。在ZooKeeper的名字空间中的每个节点由路径标识。

分级名字空间

4.节点和临时节点

不像标准FS,ZooKeeper命名空间中的每一个Node节点都可以拥有其及其子节点的数据,就像那允许文件也是目录的FS。ZooKeeper的目标是要存储协调数据、状态信息、配置和本地信息等。所以存储在每个节点上的数据很少,在KB范围内。用术语ZNode可以更清楚的表达我们讨论的是ZooKeeper的数据节点

ZooKeeper保持了包含数据改变、ACL改变、时间戳的版本信息的stat结构。允许缓存验证和协调的更新。每次的znode数据的改变,版本号也会增长。

存储在一个空间的每个znode的数据被读出,并以原子写入。读取获得与znode相关联的所有数据字节和一个写替换所有的数据。每个节点都有限制谁可以做什么的访问控制列表(ACL)。

动物园管理员还具有临时节点的概念。这些znodes存在,只要创建该znode会话处于活动状态。当会议结束znode被删除。当你想实现短暂的节点是有用的[待定]。

Zookeeper状态结构

zookeeper中的每个znode节点的状态结构体都包含以下 属性:

  • czxid

    znode被创建时造成的zxid的改变

  • mzxid

    znode最后修改时的zxid的改变

  • ctime

znode创建的时间(毫秒/单位)
  • mtime

    znode最后修改的时间(毫秒/单位)

  • version

    znode上数据改变的版本号

  • cversion

    该znode的子节点的数据改变的版本号

  • aversion

    该节点的ACL改变的版本号

  • ephemeralOwner

    如果节点是临时节点,其为该节点拥有者的session的id。如果节点为非临时节点,该值为零。

  • dataLength

    该znode节点的数据属性长度

  • numChildren

    该znode的子节点的数量

示例:

创建并查看znode

5.有条件的更新和监控

ZooKeeper支持监控的概念,客户端可以设置一个znode上的监控,当znode改变时,触发器会被触发或删除。当触发器被触发时,客户端会收到znode改变的通知。

并且,如果客户端和一个ZooKeeper服务节点断开,客户端将接收本地通知。

数据访问

zookeeper不是设计用来通用的DB或者大对象存储的,他是管理协调数据的。管理的数据可以包括:配置,状态信息,集合点等。属性很小,也就KB级别。

客户端和服务端的实现会明确检查znode节点的数据是否超过1M大小。 在相对比较大的节点操作会造成一些操作花费更长的时间并且会影响一些操作的潜在因素因为会花费额外的时间在网络上移动更多的数据到存储介质。

如果需要存储大量的数据,通常模式是使用如NFS或者HDFS等容量存储上处理这样的数据。并且在ZK中存储这些数据的存储位置。

zk的session

状态图:

session状态分析

如果能建立连接,连接成功,状态为CONNECTED。 断开连接,状态为CLOSED时几种情况:

  • session失效

  • 权限验证失败

  • 应用异常关闭

创建客户端session时,会从提供的zk服务器列表中随机获取一个,如果不能成功连接,会继续寻找下一个直到连接建立成功或所有服务都不可访问。 服务器列表是以逗号分隔的host:port字符串。

在3.2以后,如果指定的服务端节点带有路径,如host:port/app/a,则以该路径为root起点。如客户端指定/foo/bar,则服务端解析为/app/a/foo/bar。 该特性在ZK的多租户环境下非常有用。

在客户端获得到zk服务的一个手柄(handle)时,zk会创建zk的session,一个62位数字分派给客户端,如果客户端连接到不同的zk服务,它会发送该session id作为连接握手的一部分。

基于安全考虑,服务端会为session id创建任何zk服务都能验证的密码。该密码在客户端建立会话时随session id一起发送给客户端。 在客户端与心得服务重新建立session时会随session id发送该密码。

session过期是由zk集群自动管理,而不是客户端。集群会根据在分发给zk客户端session时附带的过期时间值决定session是否过期。

session过期后,集群会删除该session拥有的所有临时节点。并立即通知所有监控该节点的已经连接上的客户端。 但session过期的客户端不会被通知,而且会被断开连接直到其重新与zk集群建立连接。

6.担保

ZooKeeper的速度非常快,非常简单。因为它的目标,不过,是成为更复杂的服务,如同步的结构的基础上,提供了一组保证。这些是:

  • 顺序一致性 - 从客户端的更新将在它们发送的顺序应用。

  • 原子 - 更新成功或失败。没有部分结果。

  • 单一系统映像 - 一个客户将看到相同的服务的认识,而它连接到服务器。

  • 可靠性 - 一旦更新已被应用,它会从那个时候向前持续到客户端覆盖更新。

  • 时效性 - 该系统的客户端视图保证是向上最新结合的一定时间内。

7.简单的API

一个动物园管理员的设计目标是提供一个非常简单的编程接口。其结果是,它仅支持这些操作:

  • 创建 在树中的位置创建一个节点

  • 删除 删除一个节点

  • 存在 判断节点是否存在

  • 获取数据 从一个节点读取数据

  • 设置数据 写入数据到节点

  • 获取子节点 检索节点的子节点的列表

  • 同步 等待要传播的数据

8.实现

实现

ZooKeeper的组件显示的ZooKeeper服务的高层组件。与请求处理器外,各构成ZooKeeper服务的服务器进行复制其自身的各组成部分的副本。

9.用途

ZooKeeper的编程接口有意被设计的很简单,但你可以实现更高阶的操作,比如同步原语、组成员关系、所有权等等。

10.性能

ZooKeeper被设计用于高性能。

ZooKeeper的吞吐量读写比变化

吞吐量读写比变化

11.可靠性

可靠性错误的存在

吞吐量读写比变化

12. Zk可以用来保证数据在zk集群之间的数据的事务性的一致 (一般数据在2M以下)

Zk可以用来保证数据在zk集群之间的数据的事务性的一致

13. zookeeper进行leader选举

核心思想:

  • 1.首先创建EPHEMERAL目录节点,如”/election”;

  • 2.每个zookeeper服务器在此目录下创建一个SEQUENCE EPHEMERAL类型节点”如/election/n_”;
  • 3.zookeeper将自动为每个zookeeper服务器分配一个比前面所分配的序号要大的序号,拥有最小编号的zookeeper服务器将成为leader。

    为了能在leader发生意外时,整个系统能选出leader,需要所有的follower都监视leader所对应节点,当leader故障时,leader对应的临时节点将会被删除,会触发所有监视的follower的watch,从而进行选举leader操作。 缺点:这样的解决方案会导致从众效应

实现:

每个follower为follower集群中对应着比自己节点序号小的节点中x序号最大的节点设置一个watch,只有当follower所设置的watch被触发时,他才进行leader操作,一般将其设置为集群的下一个leader。这样很快,因为每一leader选举几乎只涉及单个leaderfollower的操作

14.zookeeper锁服务

  • a.zookeeper中完全分布的锁是全局存在的。
  • b.zookeeper的锁机制(实现加锁)

    i. zk调用create(),创建路径格式为”locknode/lock”的节点,此节点类型为sequence(连续)和ephemeral(临时),创建节点为临时节点,所有节点连续编号“lock-i”格式

    ii. 在创建锁节点上调用getChildren()方法,以获取锁目录下的最小编号节点,并且不设置watch。

    iii. 步骤2获取的节点是步骤1中客户端创建的节点,此客户端会获得该种类型的锁,然后退出操作。

    iv. 客户端在锁目录上调用exists()方法,并设置watch来监视锁目录下序号相对自己次小的连续临时节点的状态。

    v. 如果监视节点状态发生变化,则跳转到步骤2,继续后续操作直到退出锁竞争。

    vi. Zookeeper解锁简单,只需在步骤1中创建的临时节点删除即可。

PS:

  • 1.一个客户端解锁后,将只可能有一个客户端获得锁,因此每个临时的连续节点对应一个客户端,并且节点间没有重叠;

  • 2.在zookeeper锁机制中没有轮询和超时。

15. BooKeeper

  • 副本功能。

  • 提供可靠的日志记录。 BooKeeper为每份日志提供了分布式存储,并且采用了大多数概念,就是说只要集群中大多数机器可用,那么该日志一直有效。

BooKeeper包含四个角色:账本(服务器)、账户(Ledger,账本中存储的一系列记录)、客户端(BooKeeper Client,允许APP在系统上进行操作,包括创建账户,写账户)、元数据存储服务(metadata storage service,存储关于账户和版本的信息)

ACL权限

权限:

  • CREATE:创建子节点

  • READ:获取节点或列出子节点

  • WRITE:为节点设置数据

  • DELETE:删除子节点

  • ADMIN:设置权限

一致性保证

ZK是高可用,可扩展的服务,读写操作都很快,尽管读比写更快。原因是读的时候,ZK可以提供老的数据,这反过来是由于ZK的一致性保证。

  • 连续一致性:

    来自于客户端的更新会应用于他们发送的顺序。

  • 原子性:

    更新要么成功,要么失败,没有中间状态。

  • 简单的系统镜像

    不管他是连接的哪一个服务,客户端看到的都是相同的服务视图。

  • 可靠性:

    一旦更新被提交,它将从那时持续知道客户端覆盖更新。 该保证有两个推论:

    • 如果客户端获取到成功的返回码,更新将会被提交。在一些失败情况下(通讯错误,超时等)客户端会不知道更新是否被提交。我们采取措施减少失败,但是保证只出现成功的返回码(在Paxos中叫单调性条件)。

    • 对于客户端发现的任何更新,尽管读请求或成功更新,在服务失败恢复时将会不再回滚。

  • 时效性:

    系统的客户端视图保证在一定时间内(几十秒)保证最新的绑定。否则系统改变将不会被该该绑定的客户端发现,或者客户端察觉服务终端。

使用这些一致性保证,ZK客户端很容易构建高层的方法,如leader选举,栅栏,队列,只可撤销的读写所。

java API

java中只要有两个包:org.apache.zookeeperorg.apache.zookeeper.data。ZK的其他包用于内部或作为服务实现的一部分。

org.apache.zookeeper.data包被编织为生成类,就像容器一样简单使用。

ZK的java客户端使用的主要类是ZooKeeper,其中两个构造方法是可选session id和password的。zk支持通过进程实例的session回复。java程序可能保存它的session id和密码到稳定的存储中,重启和回复session都会使用程序早先的实例。

ZooKeeper对象呗创建后,会创建两个线程:IO线程和事件线程。所有的IO操作通过IO线程(使用java的NIO),所有的事件回调使用时间线程。Session维护比如重连到ZK服务,维护IO线程上的心跳。同步方法的响应也在IO线程上执行。所有的异步方法的相应和监控时间在时间线程处理。

从该设计中有几件事需要注意:

  • 异步调用和监控回调的所有完成将会按顺序,一次一个。调用者可以做任何处理,但是没有其他回调在这期间会被处理。

  • 回调不会阻塞IO线程的处理或同步调用的处理。

  • 同步调用可能不会按照正确顺序返回。比如,假设客户端做了如下操作:发送了一个异步读节点/a,并且监控设置为true。 然后在读的回调完成中他做了一个同步读/a

    注意:如果在异步读和同步读的时候/a有改变,客户端库在同步读回应之前受到监控时间通知/a已经改变,但是因为完成的回调阻塞在时间队列,在监控事件被处理之前,同步读会返回/a的一个新值。

最后,与关闭相关的规则很简单:一旦ZooKeeper对象关闭或受到失败时间(session过期或者权限失败),ZooKeeper对象就会变为肥大。关闭时,连个线程关闭并且任何进一步的访问不会被定义行为并且应该避免。