一、zookeeper简介

1. 分布式系统定义及面临的问题

ZooKeeper最主要的使用场景,是作为分布式系统的分布式协同服务。

我们将分布式系统定义为:分布式系统是同时跨越多个物理主机,独立运行的多个软件所组成的系统。类比一下,分布式系统就是一群人一起干活。人多力量大,每个服务器的算力是有限的,但是通过分布式系统,由n个服务器组成起来的集群,算力是可以无线扩张的。

优点显而易见,人多干活快,并且互为备份。但是缺点也很明显。我们可以想象一下,以一个小研发团队开发软件为例,加入我们有一个5人的项目组,要开始一个系统的开发,项目组将面临如下问题:

在这里插入图片描述

实际上要想解决这些问题并没有那么复杂,我们仅需要做⼀件事就可以万事⽆忧—让信息在项⽬组成员中同步。如果能做到信息同步,那么每个⼈在⼲什么,⼤家都是清楚的,⼲到什么程度也是清晰的,⽆论谁离职也不会产⽣问题。分配的⼯作,能够及时清晰的同步给每个组员,确保每个组员收到的任务分配没有冲突。

分布式系统的协调工作就是通过某种方式,让节点的信息能够同步和共享。这依赖于服务进程之间的通信。通信方式有两种:

  • 通过网络进行信息共享

这就像现实中,开发leader在会上把任务传达下去,组员通过听leader命令或者看leader的邮件知道⾃⼰要⼲什么。当任务分配有变化时, leader会单独告诉组员,或者再次召开会议。信息通过⼈与⼈之间的直接沟通,完成传递。

  • 通过共享存储

这就好⽐开发leader按照约定的时间和路径,把任务分配表放到了svn上,组员每天去svn上拉取最新的任务分配表,然后⼲活。其中svn就是共享存储。更好⼀点的做法是,当svn⽂件版本更新时,触发邮件通知,每个组员再去拉取最新的任务分配表。这样做更好,因为每次更新,组员都能第⼀时间得到消息,从⽽让⾃⼰⼿中的任务分配表永远是最新的。此种⽅式依赖于中央存储。整个过程如下图所示:

在这里插入图片描述

2. ZooKeeper如何解决分布式系统面临的问题

ZooKeeper对分布式系统的协调,使用的是第二种方式,共享存储。其实共享存储,分布式应用也需要和存储进行网络通信。

实际上,通过ZooKeeper实现分布式协同的原理,和项目组通过SVN同步工作任务的例子是一样的。ZooKeeper就像是svn,存储了任务的分配、完成情况等共享信息。每个分布式应用的节点就是组员,订阅这些共享信息。当主节点(组leader),对某个从节点的分工信息做出改变时,相关订阅的从节点得到ZooKeeper的通知,取得自己最新的任务分配。完成工作后,把完成情况存储到ZooKeeper。主节点订阅了该任务的完成情况信息,所以将得到ZooKeeper的完工的通知。

在这里插入图片描述

**Slave节点要想获取ZooKeeper的更新通知,需事先在关⼼的数据节点上设置观察点。 **

⼤多数分布式系统中出现的问题,都源于信息的共享出了问题。如果各个节点间信息不能及时共享和同步,那么就会在协作过程中产⽣各种问题。 ZooKeeper解决协同问题的关键,就是在于保证分布式系统信息的⼀致性。

3. ZooKeeper的基本概念

Zookeeper是⼀个开源的分布式协调服务,其设计⽬标是将那些复杂的且容易出错的分布式⼀致性服务封装起来,构成⼀个⾼效可靠的原语集,并以⼀些简单的接⼝提供给⽤户使⽤。 zookeeper是⼀个典型的分布式数据⼀致性的解决⽅案,分布式应⽤程序可以基于它实现诸如数据订阅/发布、负载均衡、命名服务、集群管理、分布式锁和分布式队列等功能

基本概念

3.1 集群角色

通常在分布式系统中,构成一个集群的每一台机器都有自己的角色,最典型的就是Master/Slave模式(主备模式),此情况下把所有能够处理写操作的机器成为Master机器,把所有通过异步复制方式获取最新数据,并提供读服务的机器为Slave机器。

而在ZooKeeper中,这些概念被颠覆了。它没有沿用传统的Master/Slave概念,而是引入了Leader、Follower、Observer三种角色。ZooKeeper集群中所有机器通过Leader选举来选定一台被称为Leader的机器,Leader服务器为客户端提供读和写服务,除Leader外,其他机器包括Flower和Observer都能提供读服务,唯一的区别在于Observer不参与Leader选举过程,不参与写操作的过半成功策略,因此Observer可以在不影响性能的情况下提升集群的性能。(如果服务器过多,写操作的过半成功策略会使得投票时间过长,影响性能)

3.2 会话

Session指客户端会话,一个客户端连接是指客户端和服务端之间的一个TCP长连接,ZooKeeper对外的服务端口默认为2181,客户端启动的时候,首先会与服务器建立一个TCP连接,从第一次连接建立开始,客户端会话的生命周期也开始了,通过这个连接,客户端能够心跳检测与服务器保持有限的会话,也能够向ZooKeeper服务器发送请求并接收响应,同时还能够通过该连接接受来自服务器的Watch事件通知。

3.3 数据节点

在谈到分布式的时候,我们通常说的”节点“是指组成集群的每一台机器,然而,在ZooKeeper中,”节点“分为两类,第一类是指构成集群的机器,我们称之为机器节点;第二类则是指数据模型中的数据单元,我们称之为数据节点——ZNode。ZooKeeper将所有的数据存储在内存中,数据模型是一棵树(ZNode Tree),由斜杠进行分割的路径,就是一个ZNode,例如/app/path1。每个ZNode上都会保存自己的数据内容,同时还会保存一系列属性信息。

3.4 版本

刚刚我们提到,ZooKeeper的每个ZNode上都会存储数据,对于每个ZNode,ZooKeeper都会为其维护一个叫做Stat的数据结构,Stat记录了这个ZNode的三个数据版本,分别是version(当前ZNode的版本),cversion(当前ZNode子节点的版本)、aversion(当前ZNode的ACL版本)。

3.5 Watcher(事件监听器)

Watcher(事件监听器),是ZooKeeper中一个很重要的特性,ZooKeeper允许用户在指定节点上注册一些Watcher,并且在一些特定事件触发的时候,ZooKeeper服务端会将事件通知到感兴趣的客户端,该机制是ZooKeeper实现分布式协调服务的重要特性。

3.6 ACL

Zookeeper采⽤ACL(Access Control Lists)策略来进⾏权限控制,其定义了如下五种权限:

  • CREATE:创建子节点的权限。
  • READ:获取节点数据和子节点列表的权限。
  • WRITE:更新节点数据的权限。
  • DELETE:删除子节点的权限。
  • ADMIN:设置节点ACL的权限

其中需要注意的是,CREATE和DELETE这两种权限都是针对子节点的权限控制。

更多推荐