ZooKeeper 是一个开源的分布式协调服务。它是一个为分布式应用提供一致性服务的软件,分布式应用程序可以基于 Zookeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。

ZooKeeper 的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。

Zookeeper 保证了如下分布式一致性特性:

(1)顺序一致性

(2)原子性

(3)单一视图

(4)可靠性

(5)实时性(最终一致性)

客户端的读请求可以被集群中的任意一台机器处理,如果读请求在节点上注册了监听器,这个监听器也是由所连接的 zookeeper 机器来处理。对于写请求,这些请求会同时发给其他 zookeeper 机器并且达成一致后,请求才会返回成功。因此,随着 zookeeper 的集群机器增多,读请求的吞吐会提高但是写请求的吞吐会下降。

有序性是 zookeeper 中非常重要的一个特性,所有的更新都是全局有序的,每个更新都有一个唯一的时间戳,这个时间戳称为 zxid(Zookeeper Transaction Id)。而读请求只会相对于更新有序,也就是读请求的返回结果中会带有这个zookeeper 最新的 zxid。

Zookeeper由来


Zookeeper最早起源于雅虎研究院的一个研究小组。在当时,研究人员发现,在雅虎内部很多大型系统基本都需要依赖一个类似的系统来进行分布式协调,但是这些系统往往都存在分布式单点问题。所以,雅虎的开发人员就试图开发一个通用的无单点问题的分布式协调框架,以便让开发人员将精力集中在处理业务逻辑上。

关于“ZooKeeper”这个项目的名字,其实也有一段趣闻。在立项初期,考虑到之前内部很多项目都是使用动物的名字来命名的(例如著名的Pig项目),雅虎的工程师希望给这个项目也取一个动物的名字。时任研究院的首席科学家RaghuRamakrishnan开玩笑地说:“在这样下去,我们这儿就变成动物园了!”此话一出,大家纷纷表示就叫动物园管理员吧一一一因为各个以动物命名的分布式组件放在一起,雅虎的整个分布式系统看上去就像一个大型的动物园了,而Zookeeper正好要用来进行分布式环境的协调一一于是,Zookeeper的名字也就由此诞生了。

Zookeeper从设计模式角度来理解:是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper就将负责通知已经在Zookeeper上注册的那些观察者做出相应的反应,从而实现集群中类似Master/Slave管理模式

设计目标

1.简单的数据结构

共享的树形结构,类似文件系统,数据存储于内存(Zookeeper其实也是一个NoSQL数据库,既然是NoSQL,存储格式一定就是Key Value格式的),ZooKeeper数据保存在内存中,这意味着ZooKeeper可以实现高吞吐量和低延迟。
image.png
2.可以构建集群

避免单点故障,3-5台机器就可以组成集群,超过半数正常工作就能对外提供服务;
为了保证高可用,最好是以集群形态来部署 ZooKeeper,这样只要集群中大部分机器是可用的(能够容忍一定的机器故障),那么zookeeper本身仍然是可用的。 客户端在使用 ZooKeeper 时,需要知道集群机器列表,通过与集群中的某一台机器建立 TCP 连接来使用服务,客户端使用这个TCP链接来发送请求、获取结果、获取监听事件以及发送心跳包。如果这个连接异常断开了,客户端可以连接到另外的机器上。
组成 ZooKeeper 服务的服务器都会在内存中维护当前的服务器状态,并且每台服务器之间都互相保持着通信。集群间通过 Zab 协议(Zookeeper Atomic Broadcast)来保持数据的一致性。

ZooKeeper 官方提供的架构图:
image.png

上图中每一个 Server 代表一个安装 Zookeeper 服务的服务器。组成 ZooKeeper 服务的服务器都会在内存中维护当前的服务器状态,并且每台服务器之间都互相保持着通信。集群间通过 Zab 协议(Zookeeper Atomic Broadcast)来保持数据的一致性。

3.顺序访问
对于每个读请求,zk会分配一个全局唯一的递增编号,利用这个特性可以实现高级协调服务,也可以利用这个特性实现分布式锁,去做其它的一些服务;

4.高性能
基于内存操作(本来就是一个NoSQL),服务于非事务请求,适用于读操作为主的业务场景(因为“写”会导致所有的服务器间同步状态。)。3台zk集群能达到13w QPS;

其他

  1. 最终一致性:client 不论连接到哪个 Server,展示给它都是同一个视图,这是 zookeeper 最重要的性能。
  2. 可靠性:具有简单、健壮、良好的性能,如果消息被推送到一台服务器接收,那么它将被所有的服务器接收。
  3. 实时性:zookeeper 保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息,但由于网络延时等原因,zookeeper 不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用 sync 接口。
  4. 等待无关 (wait-free):慢的或者失效的 client 不得干预快速的 client 的请求,使得每个 client 都能有效的等待。
  5. 原子性:更新只能成功或者失败,没有中间状态。
  6. 顺序性:包括全局有序和偏序两种,全局有序是指如果在一台服务器上消息 a 在消息 b 之前发布,则所有的 Server 上消息 a 都将消息 b 之前发布;偏序是指如果一个消息 b 在消息 a 后被同一个发送者发布,a 必将排在 b 前面

掌握Zookeeper需要掌握到什么地步呢?


zookeeper的基础需要掌握:
1. watch机制
2. 数据模型

zookeeper的进阶知识:

1. 客户端 curotor 和zkClient的其中之一
2. 分布式锁
3. 服务注册与发现

zookeeper的高级知识:

1. 一致性协议 zab
2. ZK集群部署


以上都会了基本面试是没什么太大关系了.

重要概念

  1. ZooKeeper 本身就是一个分布式程序(只要半数以上节点存活,ZooKeeper 就能正常服务)。
    2. 为了保证高可用,最好是以集群形态来部署 ZooKeeper,这样只要集群中大部分机器是可用的(能够容忍一定的机器故障),那么 ZooKeeper 本身仍然是可用的
    3. ZooKeeper 将数据保存在内存中,这也就保证了 高吞吐量和低延迟(但是内存限制了能够存储的容量不太大,此限制也是保持znode中存储的数据量较小的进一步原因)。
    4. ZooKeeper 是高性能的。 在“读”多于“写”的应用程序中尤其地高性能,因为“写”会导致所有的服务器间同步状态。(“读”多于“写”是协调服务的典型场景。)
    5. ZooKeeper有临时节点的概念。 当创建临时节点的客户端会话一直保持活动,瞬时节点就一直存在。而当会话终结时,瞬时节点被删除。持久节点是指一旦这个ZNode被创建了,除非主动进行ZNode的移除操作,否则这个ZNode将一直保存在Zookeeper上。
    6. ZooKeeper 底层其实只提供了两个功能:①管理(存储、读取)用户程序提交的数据;②为用户程序提供数据节点监听服务。

    ZooKeeper 特点


    1.Zookeeper:一个领导者(leader),多个跟随者(follower)组成的集群。
    2.Leader负责进行投票的发起和决议,更新系统状态
    3.Follower用于接收客户请求并向客户端返回结果,在选举Leader过程中参与投票
    4. 集群中只要有半数以上节点存活,Zookeeper集群就能正常服务。
    5. 全局数据一致:每个server保存一份相同的数据副本,client无论连接到哪个server,数据都是一致的。.要么内容全部都是A ,要么内容全部都是B,不可能出现一部分机器内容是A,一部分机器内容是B
    6.更新请求顺序进行,来自同一个client的更新请求按其发送顺序依次执行。
    7.数据更新原子性,一次数据更新要么成功,要么失败。
    8.实时性,在一定时间范围内,client能读到最新数据。在某一段特定的时间内,客户端可以读取到zookeeper服务端的最新数据,所谓的时间可能有十几秒到二十几秒的区间
    9.原子性: 所有事务请求的处理结果在整个集群中所有机器上的应用情况是一致的,也就是说,要么整个集群中所有的机器都成功应用了某一个事务,要么都没有应用。 不会出现整个集群,一部分机器是成功的,一部分机器是失败的.
    10.可靠性: 一旦一次更改请求被应用,更改的结果就会被持久化,直到被下一次更改覆盖。

文件系统

Zookeeper提供一个多层级的节点命名空间(节点称为 znode)。与文件系统不同的是,这些节点都可以设置关联的数据,而文件系统中只有文件节点可以存放数据而目录节点不行。

Zookeeper为了保证高吞吐和低延迟,在内存中维护了这个树状的目录结构,这种特性使得 Zookeeper不能用于存放大量的数据,每个节点的存放数据上限为1M。

Zookeeper不是强一致性

zookeeper是顺序最终一致性
前段时间面试,面试官问我一个问题,听说你看过zookeeper源码,那你能告诉我zookeeper是不是强一致性的,如果是,又怎么保证数据强一致性的吗? 针对这个问题, 我从下面几个角度进行了分析和解答。
什么是一致性
一致性就是指数据在多个副本节点之间是一致的,也就是说,你在一个副本节点上修改了数据,其他副本节点也会相应的修改数据。
接下来再说一下什么是强一致性,强一致性指的是你在一个副本节点修改了数据,那么在其他副本节点都能立刻读到最新修改的数据。
zookeeper是强一致性吗
zookeeper使用的ZAB协议进行主从数据同步,ZAB协议认为只要是过半数节点写入成为,数据就算写成功了,然后会告诉客户端A数据写入成功,如果这个时候客户端B恰好访问到还没同步最新数据的zookeeper节点,那么读到的数据就是不一致性的,因此zookeeper无法保证写数据的强一致性,只能保证最终一致性,而且可以保证同一客户端的顺序一致性。
在zookeeper官方网站上专门有一段文档对此进行了说明,有兴趣的可以进去看一下(https://zookeeper.apache.org/doc/r3.5.8/zookeeperProgrammers.html
如何保证强一致性?

zookeeper既然不是强一致性的,那我们如何能保证两个客户端读到的数据是一致性的呢,那就是sync方法,zookeeper原生客户端API和Curator客户端都提供了该sync()方法,调用sync()方法之后,zookeeper集群会保证集群所有节点数据都是一致性的,此时客户端再去任意节点读取数据,都能读取最新的数据。
zookeeper不保证强一致性的原因,我认为是在性能和可用性(A)和一致性之间(C)做了取舍。
1.如果节点之间存在网络延迟,而又要所有节点都同步数据才算成功,那么写性能非常的差;
2.如果有一个节点挂了,无法同步数据,那么此时整个集群就无法提供写服务,无法保证可用性.

有哪些开源的分布式系统中使用了zookeeper

1.分布式的Java业务系统,分布式的电商平台, 因为这些平台基本都用dubbo或者springcloud , 会用到zookeeper

2.开源的分布式系统

  1. dubbo hbase hdfs kafka canal storm Maxwell solr ,

还有就是分布式协调通知(Dubbo用zookeeper来实现注册中心)

hdfs用zookeeper来做master选举来实现HA的架构

kafka也是用zookeeper来作为分布式集群中的集中式元数据存储,分布式协调和通知

canal 用zookeeper作为分布式集中的元数据存储,也用zookeeper实现master选举的ha架构

何时引入zookeeper

如果你自己去研发类似的一些分布式系统:

1.是否需要一个地方去集中的存储分布式集群元数据,

2.你是否需要一个东西辅助你进行master选举

3.你是不需要一个东西帮你进行分布式协调通知?(监听一个数据的变化,如果数据变化了就及时通知,zookeeper的 watch机制)

如果你有上面的场景之一就可以考虑引用zookeeper.

Zookeeper 和 Dubbo 的关系


Zookeeper的作用:

zookeeper用来注册服务和进行负载均衡,哪一个服务由哪一个机器来提供必需让调用者知道,简单来说就是ip地址和服务名称的对应关系。当然也可以通过硬编码的方式把这种对应关系在调用方业务代码中实现,但是如果提供服务的机器挂掉调用者无法知晓,如果不更改代码会继续请求挂掉的机器提供服务。zookeeper通过心跳机制可以检测挂掉的机器并将挂掉机器的ip和服务对应关系从列表中删除。至于支持高并发,简单来说就是横向扩展,在不更改代码的情况通过添加机器来提高运算能力。通过添加新的机器向zookeeper注册服务,服务的提供者多了能服务的客户就多了。

dubbo:

是管理中间层的工具,在业务层到数据仓库间有非常多服务的接入和服务提供者需要调度,dubbo提供一个框架解决这个问题。
注意这里的dubbo只是一个框架,至于你架子上放什么是完全取决于你的,就像一个汽车骨架,你需要配你的轮子引擎。这个框架中要完成调度必须要有一个分布式的注册中心,储存所有服务的元数据,你可以用zk,也可以用别的,只是大家都用zk。

zookeeper和dubbo的关系:

Dubbo 的将注册中心进行抽象,它可以外接不同的存储媒介给注册中心提供服务,有 ZooKeeper,Memcached,Redis 等。

引入了 ZooKeeper 作为存储媒介,也就把 ZooKeeper 的特性引进来。首先是负载均衡,单注册中心的承载能力是有限的,在流量达到一定程度的时 候就需要分流,负载均衡就是为了分流而存在的,一个 ZooKeeper 群配合相应的 Web 应用就可以很容易达到负载均衡;资源同步,单单有负载均衡还不 够,节点之间的数据和资源需要同步,ZooKeeper 集群就天然具备有这样的功能;命名服务,将树状结构用于维护全局的服务地址列表,服务提供者在启动 的时候,向 ZooKeeper 上的指定节点 /dubbo/${serviceName}/providers 目录下写入自己的 URL 地址,这个操作就完成了服务的发布。 其他特性还有 Mast 选举,分布式锁等。

Zookeeper概念 - 图3

ZK的watch机制是否永久

否。

ZK的常见客户端有哪些

java客户端:zk自带的zkclient及Apache开源的Curator

Zk默认的通信框架是什么

Nio,可以改成netty

说几个 zookeeper 常用的命令。

常用命令:ls get set create delete 等。