简介

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。 ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。 —百度百科


ZooKeeper集群整体框架

Zookeeper

  • Client:客户端。每个Client都可以去访问这个Zookeeper集群提供的服务。
  • Sever:服务器。为客户端提供服务。

Zookeeper把集群划分为三种角色:Leader,Follower,Observer(Zookeeper3.3引入)

  • Leader:是所有的Follower通过选举产生的的一个主节点,它负责处理客户端所有的事务请求和集群中各服务器的调度。

  • Follower

    • 处理客户端非事务请求并转发事务请求给Leader。
    • 参与Leader发起的事务请求提议的投票。(Leader发起提案,要求Follower进行投票,需要半数以上的Follower节点通过,Leader才会Commit数据)
  • Observer:与Follower一样,不同的是Observer不参与Leader选举,也不参与过半写成功策略。(Obsever的目的是为了在不影响集群写性能的前提下提升集群的读性能)

事务与非事务请求的处理流程

  • 事务:Client–>Sever(Follower)发送一个请求,然后判断是一个事务请求,Follower就会把这个请求转发给Leader进行处理。

  • 非事务:Client–>Sever(Follower)发送一个请求,然后判断是一个非事务请求,Follower就会直接处理给予响应。

综上可以得出Zookeeper适合以查询(读操作)为主的业务场景,并不适合以事务修改(写操作)为主的业务场景。

Zookeeper支持横向扩展,横向扩展只能加强Zookeeper非事务请求的处理,不能加强事务请求的处理,因为无论怎么横向扩展,也只能有一个Leader。


客户端怎么判断向集群中哪个Sever发起请求

  • 客户端自己维护着一份节点列表,它会有一个选择节点的算法,可以随机或者可以按照轮巡这种算法来选择一个节点进行请求。

Zookeeper节点类型

  1. Znode有三种类型,临时的(Ephemeral)持久的(Persistent)和顺序的(Sequence)
  2. 临时Znode的生命周期与客户端会话相关,客户端会话结束时,Zookeeper会将临时Znode删除,临时Znode不可以有子节点
  3. 持久Znode不依赖于客户端会话,只有当客户端明确要删除该持久Znode时,才会被删除。
  4. Znode类型在创建时确定,并且之后不能再修改
  5. 顺序Znode可以分为临时顺序节点和持久顺序节点。
    • 持久顺序节点:客户端与Zookeeper断开连接之后该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号。
    • 临时顺序节点:客户端与Zookeeper断开连接之后该节点会被删除,只是Zookeeper给该节点名称进行顺序编号。

Zookeeper数据模型

Zookeeper数据模型

  • 层次化目录结构,命名符合常规系统规范。

  • 每个节点在Zookeeper种叫做Znode,并且有一个唯一的路径标识。

  • 节点Znode可以包含数据和子节点,但是临时类型的节点不能有子节点。

  • Znode种的数据可以有多个版本,比如某一个路径下有多个数据版本,那么查询这个路径下的数据就要带上版本。


Zookeeper读写机制

  • Zookeeper是一个由多个Sever组成的集群。

  • 集群中只能有一个Leader,可以有多个Follower。

  • 每个Follower保存一份数据副本。

  • 全局数据一直

  • 分布式读写

  • 更新请求转发由Leader实施


Zookeeper 保证

  • Zookeeper集群中的每个节点都维护着一个队列,来自同一个Client的更新请求,暗器发送的顺序依次执行。

  • 数据更新原子性,一次数据更新要么成功,要么失败。

  • 全局唯一数据视图,Client无论连接到哪个Server,数据视图都是一致的。

  • 实时性,在一定时间范围内,Client能读到最新的数据。


Zookeeper的监听机制(Watcher)

Watcher: 在Zookeeper中是一个核心功能,Watcher可以监控目录节点的数据变化,以及子目录的变化。一旦这些状态发生变化,服务器就会通知所有设置在这个目录节点上的Watcher,从而每个客户端都很快知道它所关注的目录节点的状态发生变化,而做出相应的反应。


Zookeeper底层实现数据一致性

主要通过事务日志,和数据快照来实现的。

  • 事务日志

    • 事务日志记录了对Zookeeper的操作,文件以ZXID命名,可以快速定位到需要查询的事务。
    • 事务日志采用磁盘预分配策略,未使用的部分写为0。避免每次追加数据都需要进行磁盘I/O为文件开辟新空间,其每个日志文件大小固定为64M。
  • 数据快照

    • 数据快照是Zokeeper数据存储的另一重要机制,用来记录某一时刻Zookeeper在内存中的全部数据内容,并将其写入指定的磁盘文件中,也是使用ZXID命名。
    • 数据快照没有采用磁盘预分配策略,因此数据快照文件在一定程度上反映了当前Zookeeper的全量数据大小。
  1. 对于每一次的客户端操作,都写入日志文件,同时更新Zookeeper的内存数据。在进行了若干次(SnapCount)操作之后,会将内存中的全量数据dump到本地文件,既数据快照。

  2. 为了避免Zookeeper中所有节点同时进行数据快照,Zookeeper采用过半随机策略。开始快照时,首先关闭当前日志文件,重新创建一个新的日志文件。并从内存中或许Zookeeper的全量数据和校验信息,并序列化写入到本地磁盘文件中,以本次写入的第一个事务的ZXID为后缀。

  3. 数据恢复时,会加载近100个快照文件,之所以有100个是因为,有可能最近的呢可快照文件校验不通过。若校验不通过,则继续向前解析,直到第一个可以正确校验的快照文件截止。

  4. 找到可以通过的校验快照文件之后,开始执行事务日志中的操作,此时即使不是最近的呢一个快照文件,我们也可以从快照文件中找到ZXID,便可以定位到具体事务文件从哪一个开始。


原创首发,如有转载请标明出处。 ——GJ1e