漫谈大数据分布式协调服务框架——Zookeeper(你会懂的)

1.Zookeeper是什么?

       Zookeeper是一个开源的、分布式的,为分布式应用提供协调服务的大数据框架。

       它的诞生是源于雅虎对Google Chubby(分布式锁服务)的开源实现,后来托管到Apache Software Foundation(专为支持开源软件项目而创建的一个非盈利性组织),并于2010年11月成为Apache的顶级项目,同时也是Apache Hadoop的子项目之一。
在这里插入图片描述

       配置信息维护、统一命名、数据分布式同步还有分组这些服务,是分布式应用程序所必须使用的,但又往往比较复杂、经常发生冲突报错,给分布式应用的管理维护带来了很大的麻烦。Zookeeper就是为了解决这些问题而产生的一个集中的服务,一经推出就广受好评。在集群的管理中起着重要作用,如Hadoop集群NameNode的管理、Hbase集群Master Election、Server之间状态同步等。

2. Zookeeper的目标以及实现方法

       大部分新事物产生的直接诱因都是问题的驱动,zookeeper也不例外。

       Apache Zookeeper有着自己的使命,它致力于开发和维护一个开源的,为分布式应用提供高性能、高可用且具有严格顺序访问控制能力的分布式协调服务。

2.1高性能

       Zookeeper的数据全部维系在内存中,并直接服务于客户端的所有非事务请求,尤其适用于以读为主的应用场景,查询速度快。

       PS:Zookeeper中的事务操作指的是能够改变zookeeper服务端状态的操作,包括数据节点的创建与修改,数据内容的更新和客户端对话创建与失效等操作。

2.2高可用

       维持一个系统的高可用,我们一般采用冗余实现,Zookeeper也不例外。Zookeeper通常以集群的形式向外提供服务,一般3台服务器即可搭建一个完整的Zookeeper集群,各个服务器都会在内存中维系自己的状态,相互之间保持着通信,这主要得益于Zookeeper所选用的ZAB协议。

2.3严格顺序访问控制

       Zookeeper会为每一个事务分配一个全局递增的事务ID,所以Zookeeper中的每一步操作都有顺序。
在这里插入图片描述

3. Zookeeper的数据结构

       Zookeeper会维护一个具有层次关系的数据结构,它非常类似于一个标准的文件系统。
在这里插入图片描述

       它本身是一个树状结构——Znode树,每个节点称为Znode。
       Znode通过路径引用,类似于Unix中的文件路径,根节点的路径是/。路径本身必须满足两个特点:

  • 绝对的,所以每个Znode都是以/开头;
  • 唯一的,每一个Znode的路径必须是唯一的,因此这些路径不能改变。

       在Zookeeper中路径使用Unicode编码,由Unicode字符串组成,并且本身有一些限制。字符串“/Zookeeper”用以保存管理信息,比如一些关键的配额信息。

4.Zookeeper的节点

(1)组成及特点

       Znode本身兼具文件和目录的特点,既可以像文件一样维护着数据、元信息、ACL(访问控制列表)、时间戳等数据结构,又像目录一样作为路径标识的一部分。

       每个Znode整体上来说是由三部分组成的:stat、data、children。

  • stat:状态信息,主要含有该节点的事务ID、版本、权限信息等。
  • data:与该znode相关联的数据,或者说是存储的数据。
  • children:该znode下的子节点

       需要注意的是Znode虽然可以关联一些数据,但是Zookeeper作为一款协调服务框架而不是存储框架,决定了其关联的数据基本上是一些分布式应用中的配置文件、元数据等信息,这类数据有个共同点就是小,一般是以KB为单位,Zookeeper的客户端和服务端都被严格设置为每个Znode最多关联1M的数据,但在实际应用中应该远小于此值。

(2)节点类型

       Znode总共分为两种类型,一种是持久节点(persistent Node),一种是临时节点(ephemeral Node),所有节点一经创建,类型便不可更改。

  • 持久节点:客户端与服务器断开连接后,依然存在;临时节点不可以有子节点。

  • 临时节点:客户端与服务器断开连接后,变回删除。

       当创建Znode时,用户可以请求在Zookeeper的路径结尾加一个递增的计数,这个计数对于该节点的父节点来说是唯一的,当客户端请求创建这个节点后,Zookeeper会根据该节点父节点的Zxid状态编写一个全目录唯一的编号,且这个编号只会一直增长,我们称这样的节点为顺序节点。

       临时节点和持久节点都可以成为顺序节点,也由此产生了四种形式的目录节点,值得注意的是,我们创建一个节点,如果不指定什么,默认的是持久目录节点。顺序号的引入并不会改变临时和持久这两个根本的节点属性。

  • 持久目录节点:客户端与 zookeeper断开连接后,该节点依旧存在

  • 持久顺序目录节点:客户端与zookeeper 断开连接后,该节点依旧存在,只是zookeeper给该节点名称进行顺序编号;

  • 临时目录节点:客户端与zookeeper 断开连接后,该节点被删除。

  • 临时顺序目录节点:客户端与zookeeper 断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号。

       PS:顺序号由父节点进行维护,是一个单调递增的计数器;顺序号的存在,在分布式系统中可以用于对全局所有事件进行排序,这样客户端就可以通过顺序号推断时间的顺序。
在这里插入图片描述

(3)节点的数据访问控制

       为了有效保障ZooKeeper中数据的安全,避免因误操作而带来数据随意变更导致分布式系统异常,ZooKeeper提供了一套完善的ACL(Access Contro List)权限控制机制来保障数据的安全。

       可以从三个方面理解ACL机制,分别是:权限模式(Scheme)、授权对象(ID)和权限(Permission),通常使用”scheme🆔permission”来标识一个有效的ACL信息。
在这里插入图片描述

       节点的执行操作权限有5种,CREATE、READ、WRITE、DELETE、ADMIN 也就是 增、删、改、查、管理权限,这5种权限简写为crwda(即:每个单词的首字符缩写)

       :这5种权限中,delete是指对子节点的删除权限,其它4种权限指对自身节点的操作权限。

设置访问控制
       方式一:(推荐)

       1)增加一个认证用户

addauth digest 用户名:密码明文

eg. addauth digest user1:password1

       2)设置权限

setAcl /path auth:用户名:密码明文:权限

eg. setAcl /test auth:user1:password1:cdrwa

       3)查看Acl设置

getAcl /path

       方式二:

setAcl /path digest:用户名:密码密文:权限

:这里的加密规则是SHA1加密,然后base64编码。

(4)节点的相关操作命令

在这里插入图片描述在这里插入图片描述在这里插入图片描述

       :了解一个节点的stat信息,可以帮助我们更好的掌握节点的状态。

       如:get -s /node01 的节点数据
在这里插入图片描述

       Znode的stat信息很多,这里主要讲解几个重要的点。

 (1)Zxid

       集群范围内全局单调唯一递增。

       Zxid 是一个64位的数字,它的高32位是epoch用来标注leader关系是否发生改变,每次新的leader产生都会有一个新的epoch,低32位是递增计数的。
在这里插入图片描述

       当有新的Leader产生时,Leader周期epoch加1,计数器从0开始;

       每当处理一个事务请求,计数器加1。

       每次Znode变化,都会使Znode接收到一个Zxid形式的时间戳,这个时间戳是全局有序的。也就是说每次对应的节点变化都会使该节点产生一个唯一的、有序的Zxid,Zxid小的一定是先发生的时间。Znode维护两个Zxid值,分别是cZxid和mZxid。

  • cZxid 代表的是节点全局分配的创建事务ID,一经定义不会改变;

  • mZxid 修改的事务ID—记录自己本身的修改

       至于pZxid反应的是znode最后更新的子节点zxid

 (2)version

        版本号是用来记录节点数据或节点的子节点列表或权限信息的修改次数,Znode维护两三个version值,分别是dataVersion、cversion以及aclVersion。

  • dataVersion 数据版本,记录当前节点的数据修改次数

  • cversion记录子节点的修改次数

  • aclVersion 记录当前节点acl修改次数

 (3)其他

       ephemeralOwner -如果当前节点不是临时节点,那么这个属性的值为0; 如果是临时节点,那么这个属性的值记录的是当前临时节点的session id。

       dataLength Znode的数据长度

       numChildren 当前节点的子节点个数

5.Zookeeprer集群中各节点(集群单机部署节点)状态

       分布式中常出现的冲突问题:死锁、活锁,促使了管理节点的引入;管理节点的单点问题,促使了冗余策略(集群化)的引入;集群机制本身的特性需要引入一个管理节点leader进行统一调度协调;leader的选举又促进了一套选举算法的诞生。(请移步我的另一篇博文-随记:ZAB协议下的zookeeper投票和选举)

       在Zookeeper集群中,节点的状态有四种,分别是:

  • looking:选举状态

  • leader 领导者

  • follower 参与者

  • observer 观察者

       Looking状态是选举中的状态,这个时候zookeeper集群不对外提供服务;

       Leader、follower、observer的共同点是都会执行操作;
       Leader、follower参与选举和投票,observer不参与,所以集群的运行状态与observer无关;
       Leader主要职责是接收客户端的请求,发起投票与决议;

       Follower会转发客户端的请求给leader,并接收leader的决议指令;参与投票选举;

       Observer也会转发客户端的请求给leader,然后接收leader决议执行操作;不参与投票,它的存在主要是为了扩展系统,提高读取速度,适用于网络不稳定的情况。

6.Zookeeper重要特性watcher机制

(1)概述

       Zookeeper中的watcher机制允许客户端在指定节点上注册一些watcher监听器,当数据节点发生变化时(也可以自己指定一些特定触发事件),watcher会将这个变化通知给客户端,客户端可以基于这种特性做一些触发性的操作。
在这里插入图片描述

Zookeeper中的很多功能性服务都是基于watcher这个特性,比如发布订阅。

(2)具体实现
       Watcher机制的实现主要分为三步:客户端注册watcher、服务端处理watcher、客户端回调watcher。

  • 客户端注册watcher

    创造一个zookeeper客户端实例对象,向构造方法中传入watcher,这个watcher将作为整个zookeeper会话期间的唯一watcher,然后客户端会向服务器去注册watcher。值得注意的是,注册watcher并不是真的把watcher对象传递给服务器,而仅仅是在请求中使用一个boolean值去标记象征,其目的是为了降低网络开销以及内存存储开销。

  • 服务端处理watcher

    服务端执行数据变更,当watcher监听的数据节点发生数据变更时,服务端会将这个watcher提取出来,并将其从管理列表中删除(说明watcher在服务端中是一次性的,触发一次便失效),watcher被触发会去通知客户端。

  • 客户端回调watcher

    客户端获取通知,识别出事件类型并去执行操作,然后将该watcher从存储中删除(说明watcher在客户端也是一次性的,触发便会失效)

(3)总结归纳

       一致性:无论是客户端还是服务端,watcher一旦被触发就会被删除,都是一次性的,因此开发人员需要不断去重复注册,以达到减轻服务器压力的目的。

       顺序性:客户端回调watcher是串行执行的,保证了watcher触发事件的顺序性。

       轻量性:客户端在想服务端注册watcher时不传输真正的watcher对象,而仅仅在请求中以布尔值标记,减少网络开销和服务器内存开销。

7. Zookeeper提供的具体服务有哪些?

(1)统一命名服务
        所谓统一命名服务就是给一组资源或服务地址、信息命名,我们可以直接通过访问这个名字来获取我们想要的资源等信息。

       这就要求我们访问的这个名字对于这些资源信息来说必须是唯一的,并且不能随意更改的。同时最好满足访问这个名字(其实相当于目录名字)进行写入操作时有一定的顺序性。

        Zookeeper的树状结构完美解决了这个问题,Znode树的节点Znode本身兼具文件和目录的双重特点,其中目录的特点赋予了它可以做为路径标识的一部分,并且Znode的特性决定了该路径是绝对唯一的,一旦创建便具有唯一的path路径。按照zookeeper的结构设计,该命名节点的子节点会被该节点维护每一份时序。

       这就像域名和IP的对应关系,我们平常访问一个域名,最终指向的是一台台服务器的IP地址,IP可以增减变化,但是域名通常是唯一的。对应到zookeeper的统一命名服务中,域名即为节点名字,IP为我们需要的资源。如下图所示:
在这里插入图片描述

(2)配置信息维护

       在分布式环境下,集群的配置信息维护一直是一个大问题,就比如Hadoop集群,每台机器的配置信息是一样的,我们在设计系统时,既要保证配置信息的同步一致性,又要提高整体效率,不能一台台的去改。

       Zookeeper的watcher监听机制帮助我们完美的解决了这个问题。我们可以将配置信息维系在Zookeeper中的一个节点中(由于配置信息本身就很小,所以并不会占用多少内存),然后启用watcher机制,让客户端去服务端含有配置信息的节点中注册一个watcher,一旦配置信息发生变动,触发watcher,客户端就可以知道配置信息发生变化,相应的去读取更新最新的配置数据。
在这里插入图片描述

(3)集群管理

       分布式环境下,集群的管理很重要,实时掌握集群中每个节点的状态,可以大大减少集群的节点冲突、节点宕机等带来的不利影响,同时对每个节点的状态掌控也可以快速提升我们的容错应变能力,实现高可用的目标。

       Zookeeper很好的帮助我们实现了集群的管理,这主要得益于zookeeper本身的树状结构特性以及watcher监听机制。

       我们可以专门创建一个集群服务的Znode,当集群启动时,让及集群中的每个节点在该Znode下注册一个临时子节点,该节点自动维护所有子节点的顺序性。同时启动watcher机制监控这个Znode。当某一个集群节点宕机了或是不能提供服务了,直接反应的是会话结束,临时节点失效,这时候watcher机制就会通知其他的节点,让我们作出相应的改进。同时,当有新的节点加入时,各节点也会受到通知。除此之外,由于每个节点都有顺序,那么我们可以规定第一个节点为master,这样就解决了主从机制的集群中的选举问题。

       典型应用:Hbase中Master的状态监控与选举。
在这里插入图片描述

(4)实现分布式锁

       分布式锁是个大命题,zookeeper只是实现分布式锁的一种方式。

       实现分布式锁的目的其实就是实现共享数据或服务的原子性操作,避免并发操作共享数据而产生的死锁、脏数据等问题。当有一个进程在访问操作一个共享区时,其他进程都得排队等候,必须等上个进程执行完,下一个进程才能依次的去执行。

       举个例子:一个公司只有一个厕所,一个厕所就一个坑(每次只能进去一个人),并且这个厕所必须是刷卡才能进去,巧的是这个公司只有一张卡,卡放在指定的位置,所以每次大家都得排队上,A先拿卡进去了,上完厕所,出来必须得把卡放在放卡的地方,然后下一个人再去拿卡进去刷,以此类推,每次都得拿卡进去,上完再放回来,下个人接上。这就是分布式锁的实现原理。

       单机时代下,我们用不上分布式锁,但其实就是多线程冲突问题,问你的解决方法通常是用Synocronized或lock等;但是进入分布式系统时代,已经超过了线程级别,因为这些冲突线程可能位于不同的系统节点上,这就需要分布式锁。

       Zookeeper实现分布式锁的大概实现步骤是这样的:在Zookeeper上创建一个Znode lock(名字随意),这个Znode就相当于是一把锁,然后所有的进程都会来抢夺这把锁,如何抢呢?每个进程都会争着在这个锁节点下创建属于自己的临时顺序节点,由于顺序节点的特性,每个进程会按照先来后到的顺序进行编号,编号在第一个的会优先获取锁,当该进程执行结束后,就会释放锁,接着下一个第一个在来获取锁执行,这样以此类推。

       至于如何具体实现,我就不赘述了,请参考这篇文章,写的很可以文章链接

(5)其他
       当然zookeeper的功能服务有很多,但是不论服务怎么变,主要还是围绕着Zookeeper本身的树状类文件系统的数据结构以及watcher监听机制进行的,这也给我们一点启示,我们学习技术的时候,虽然有时候原理很枯燥,看似没有什么大的意义,但是所有的功能服务都是由原理发散而来的,学习技术原理会让我们事半功倍。

8. Zookeeper的Session会话

       Session会话对于我们学习编程的同学并不陌生,在zookeeper中集群一次会话就是客户端连接服务端到断开(异常断开)的过程,是客户端与服务端之间的一次TCP长连接。

(1)会话状态

        在会话的整个生命周期中,会话会有多种不同的状态

Session状态说明
Connecting客户端开始创建Zookeeper对象时,状态就会变为Connecting
Connected当客户端成功连接上服务器时,状态会变为Connected
Reconnecting由于网络波动等原因,客户端与服务器异常断开,此时客户端会自动尝试重新连接,状态就会变为Reconnecting
Reconnected客户端重新连接上服务器,状态会变为Reconnected
Close正常断开,如会话超时、权限检查失败或客户端主动退出等出情况,状态会变为Close。

(2)Session属性

       Session是zookeeper中的会话实体,代表了一个客户你会话,包含四个属性:

Session属性说明
sessionID唯一标识一个会话,每次客户端创建一个会话,zookeeper都会为其分配一个全局唯一的sessionID
Timeout会话超时时间,客户端创建连接时传递
TickTime下次会话超时时间点,其值接近于当前时间+TimeOut,是一个13位的long类型数据
IsClosing标记会话是否已关闭

(3)其他

  • 心跳检测

    为了保证客户端会话的有效性,客户端会在会话有效时间内向服务器发送ping请求来保持会话的有效性,这也就是心跳检测。

  • 会话清理

    服务器的超级线程会在指定时间内去检查有无失效过期的会话,若有则会进行清理。

  • 重连

    对于非正常断开连接的会话,客户端会自动进行重连,直到连接上zookeeper集群中一台服务器。

    在这个自动不断尝试连接的过程中,会发生两种情况,一种是在会话有效时间内连上,这种就是成功连接会话;一种是连接上的时候,该回话就已经过期了,那么这个时候,该会话为非法会话,无效。

9.Zookeepr的特性归纳

  • 一致性

              无论客户端连接到哪个server,所获取到的数据是一致的;

  • 顺序性
           Zookeeper集群中每一个事务操作都会分配有一个递增有序的事务ID,顺序执行;事务ID的大小代表了事件执行的先后顺序。

  • 原子性
           所有的server操作,客户端请求,要么都失败,要么都成功。绝不会出现单一服务器与整个集群其他server不同的情况;

  • 可靠性
           Zookeeper的数据一定是可靠的;节点server的可靠主要得益于ZAB协议下的投票选举制;

  • 实时性
           在网络较好的情况下,数据状态更改后,zookeeper可以保证在一定时间内,client读取到最新的数据;同时可以对其子节点进行实时监控;

  • 过半性
           分为请求过半性、操作过半性、对外服务过半性(服务过半性杜绝了脑裂现象的发生)
           所谓过半性,就是无论是客户端请求、操作、集群对外服务都必须至少有超过一半的节点同意方能对外提供服务

10.Zookeeper的安装以及配置文件

       关于这部分由于篇幅原因,我另外写了一篇博文,详情请查看:倾述-zookeeper集群的安装。

11.zookeeper官网相关说明

       有条件还是建议直接去看技术英文原文档,毕竟中文的各自有各自的理解。

       Zookeeper官网:https://zookeeper.apache.org/


附录:

这是Apache Zookeeper的官网原文释义:

Apache ZooKeeper(由apachezookeeper委员会管理的项目)
Apache ZooKeeper致力于开发和维护一个开源服务器,该服务器支持高度可靠的分布式协调。

项目基础数据:
一个分布式计算平台。
类别:数据库
网址:https://zookeeper.apache.org/
项目状态:活动
项目数据文件:DOAP RDF Source(生成的json)
项目数据维护者:Apache ZooKeeper社区

发展:
编程语言:Java
错误跟踪:https://issues.apache.org/jira/browse/ZOOKEEPER
邮件列表:https://zookeeper.apache.org/list
s.html
Git存储库:https://gitbox.apache.org/repos/asf/zookeeper.Git

发布(来自DOAP):
下载:https://www.apache.org/dyn/closer.cgi/zookeeper/

本文参考文章:1.https://blog.csdn.net/lipinganq/article/details/81029499#commentBox

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值