在zookeeper的介绍中,我们经常会看到这样一句话,ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务。可以看出,zookeeper主要是在分布式系统中,对各个子系统起到协调的作用,主要解决分布式环境各个系统数据的一致性问题。
ZooKeeper 实现诸如配置管理,注册中心,数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。
目前在比较流行的应用或框架中都有被用到,像Hadoop、solr、kafka、dubbo中都有用到,可见其在当下环境中,构建集群或微服务环境都是起着举足轻重的作用。
- 下载及安装
直接在官网下载,地址https://www.apache.org/dyn/closer.cgi/zookeeper/,我们选择下载.tar.gz版本的,这样直接解压就可以使用了。
首先修改下config/zoo_sample.cfg,将其拷贝一份,命名为zoo.cfg即可。一般情况下,我们会修改下数据与日志的存放路径:
dataDir=../data
dataLogDir=../data/log
然后在bin目录下,双击zkServer.cmd,即可启动,如下:
和大多数应用一样,zookeeper也为我们提供了cli方式进行操作。
- 介绍(【参考】)
从中摘取了部分内容,上面提到,zookeeper主要帮助我们保证分布式环境中,协调各个子系统可靠的工作,而zookeeper提供的主要还是数据的存取与监听服务,在这些基础服务的基础上,在各种应用场景下,让它帮助我们完成了更多的功能,比如保证数据的一致性,完成服务的注册发现等,那么这些设计的前提必须要满足几点:
1. 一致性:client不论连接到哪个Server,展示给它都是同一个视图,这是ZooKeeper最重要的性能。
2. 可靠性:具有简单、健壮、良好的性能,如果消息m被到一台服务器接受,那么它将被所有的服务器接受。
3. 实时性:ZooKeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。但由于网络延时等原因,ZooKeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口。
4. 等待无关(wait-free):慢的或者失效的client不得干预快速的client的请求,使得每个client都能有效的等待。
5. 原子性:更新只能成功或者失败,没有中间状态。
6. 顺序性:包括全局有序和偏序两种:全局有序是指如果在一台服务器上消息a在消息b前发布,则在所有Server上消息a都将在消息b前被发布;偏序是指如果一个消息b在消息a后被同一个发送者发布,a必将排在b前面。
zookeeper是存储结构非常类似于文件系统,每一个目录对应了一个节点(znode),数据都存储在各个节点上,对节点的访问必须是绝对路径,因为每个节点都是唯一的,同时每个节点可以设置访问控制ACL,或者设置watch来监听节点关联数据的变化,节点主要有stat、data、children三个属性,其中stat:
从节点的性质看,一共分为四种类型:
1、临时无序 断开连接则删除,其实是session断开或关闭
2、临时有序 同上,只不过节点由zookeeper进行顺序编号
3、持久无序 持久化的节点在连接断开后依然存在
4、持久有序 同上,只不过节点由zookeeper进行顺序编号
-注意:
临时节点不能有子节点
数据存在节点上,而数据都有版本号的
节点都可以被客户端监听,当出现节点上数据修改、子节点变化,都会进行通知
对节点的操作前提是有对应的ACL权限,在建立节点时,可以设置对该节点有那哪些操作权限,一共有以下这些可选值:
CREATE: 创建子节点的权限。(对子节点)
READ: 获取节点数据和子节点列表的权限。
WRITE:更新节点数据的权限。
DELETE: 删除子节点的权限。(对子节点)
ADMIN: 设置节点ACL的权限。
zookeeper中服务器与客户端间是通过tcp长连接进行通信,在连接成功后会建立两者间的会话(session),之后的请求都是依赖于此,而维持会话的则是通过心跳检查机制。session有以下几个状态:CONNECTING、CONNECTED、RECONNECTING、RECONNECTED、CLOSE等。在每次请求过程中,都会重新激活会话,当然,如果客户端长时间没有与服务器通信,则会在1/3超时时间时通过PING命令维持会话。【参考】
一般不会在单机下使用zookeeper,那样可靠性就没了保证,那么在集群环境中,zookeeper是如何保证数据的一致性呢?
首先需要了解,zookeeper集群中会将各个机器分为三个角色:
1、Leader:系统故障时完成数据恢复;保证并维持多台机器的状态一致;发起投票与决策。
维持服务器间的心跳连接,并接受处理其发送的请求,讲多请求的有序化,保证请求的有序与原子性。
2、Fllower:与Leader通信保存连接;Leader故障参与选举;与客户端通信与数据交互。
向Leader发送命令(PING消息、REQUEST消息、ACK消息、REVALIDATE消息),处理Leader的命令。
处理客户端请求,写则交由Leader完成。
3、Observer:类似Fllower,但不参与集群选举与投票。
对集群的扩展
消息类型:
PING消息: 心跳消息;
PROPOSAL消息:Leader发起的提案,要求Follower投票;
COMMIT消息:服务器端最新一次提案的信息;
UPTODATE消息:表明同步完成;
REVALIDATE消息:根据Leader的REVALIDATE结果,关闭待revalidate的session还是允许其接受消息;
SYNC消息:返回SYNC结果到客户端,这个消息最初由客户端发起,用来强制得到最新的更新。
-
那么zookeeper的具体原理又是怎样的呢?
1、zookeeper保证数据一致性的关键是ZAB协议,该协议主要完成两点功能,恢复、广播。当Leader出现故障导致崩溃时,出现新的选举,当选举完新的Leader后,会进行状态恢复;而广播模式让Leader与Learner保持状态一致。
2、为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数
3、每个Server在工作过程中有三种状态:
LOOKING:当前Server不知道leader是谁,正在搜寻
LEADING:当前Server即为选举出来的leader
FOLLOWING:leader已经选举出来,当前Server与之同步
--选举【参考】
当系统启动或者leader崩溃后,就会开始leader的选举。
1.状态变更。服务器启动的时候每个server的状态时Looking,如果是leader挂掉后进入选举,那么余下的非Observer的Server就会将自己的服务器状态变更为Looking,然后开始进入Leader的选举状态;
2.发起投票。每个server会产生一个(sid,zxid)的投票,系统初始化的时候zxid都是0,如果是运行期间,每个server的zxid可能都不同,这取决于最后一次更新的数据。将投票发送给集群中的所有机器;
3.接收并检查投票。server收到投票后,会先检查是否是本轮投票,是否来自looking状态的server;
4.处理投票。对自己的投票和接收到的投票进行PK:
先检查zxid,较大的优先为leader;
如果zxid一样,sid较大的为leader;
根据PK结果更新自己的投票,在次发送自己的投票;
5.统计投票。每次投票后,服务器统计投票信息,如果有过半机器接收到相同的投票,那么leader产生,如果否,那么进行下一轮投票;
6.改变server状态。一旦确定了Leader,server会更新自己的状态为Following或者是Leading。
7.选举结束。
说明:
在步骤2发送投票的时候,投票的信息除了sid和zxid,还有:
electionEpoch:逻辑时钟,用来判断多个投票是否在同一轮选举周期中,该值在服务端是一个自增序列,每次进入新一轮的投票后,都会对该值进行加1操作。
peerEpoch:被推举的Leader的epoch。
state:当前服务器的状态。
为了能够相互投票,每两台服务器之间都会建立网络连接,为避免重复建立TCP连接,zk的server只允许sid大于自己的服务器与自己建立连接,否则断开当前连接,并主动和对方建立连接。
--请求流程
1.在Client向Follwer发出一个写的请求
2.Follwer把请求发送给Leader
3.Leader接收到以后开始发起投票并通知Follwer进行投票
4.Follwer把投票结果发送给Leader
5.Leader将结果汇总后如果需要写入,则开始写入同时把写入操作通知给Leader,然后commit;
6.Follwer把请求结果返回给Client
--事务一致
更新请求顺序进行,来自同一个client的更新请求按其发送顺序依次执行。
数据更新原子性,一次数据更新要么成功,要么失败。
全局唯一数据视图,client无论连接到哪个server,数据视图都是一致的。
实时性,在一定事件范围内,client能读到最新数据。
--
- 应用场景(【参考】)
1、命名服务
2、配置管理
3、集群管理
4、分布式锁
5、队列管理
6、发布订阅
- 常用命令
conf 输出相关服务配置的详细信息。
cons 列出所有连接到服务器的客户端的完全的连接 / 会话的详细信息。包括“接受 / 发送”的包数量、会话 id 、操作延迟、最后的操作执行等等信息。
dump 列出未经处理的会话和临时节点。
envi 输出关于服务环境的详细信息(区别于 conf 命令)。
reqs 列出未经处理的请求
ruok 测试服务是否处于正确状态。如果确实如此,那么服务返回“imok ”,否则不做任何相应。
stat 输出关于性能和连接的客户端的列表。
wchs 列出服务器 watch 的详细信息。
wchc 通过 session 列出服务器 watch 的详细信息,它的输出是一个与watch 相关的会话的列表。
wchp 通过路径列出服务器 watch 的详细信息。它输出一个与 session相关的路径。
- ZAB协议与Paxos算法
略