文档

java体系技术文档


zookeeper

<h2>1 zookeeper概览</h2> <ol> <li>ZooKeeper 是一个开源的分布式协调服务,它的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,并以一系列简单易用的接口提供给用户使用。</li> <li>ZooKeeper 是一个典型的分布式数据一致性解决方案,分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。 一个最常用的使用场景就是用于担任服务生产者和服务消费者的注册中心(提供发布订阅服务)。</li> </ol> <h2>2 zookeeper的一些重要概念</h2> <h3>2.1 重要概念总结</h3> <ul> <li>zookeeper本身就是一个分布式程序(只要保持半数以上的节点存活,zookeeper就能正常服务)。</li> <li>为了保证高可用,最好集群部署zookeeper,这样只要集群中的大部分机器是可用的(就能容忍一定的机器故障),那么zookeeper就仍能正常提供服务。</li> <li>zookeeper将数据保存在内存中,这保证了高吞吐量和低延迟(但是内存限制了能够存储的容量,此限制也是保持znode中存储的数据量较小的进一步原因)。</li> <li>zookeeper是高性能的,在“读”多于“写”的应用程序中尤其的高性能,因为“写”操作会导致所有的服务器间同步状态。(“读”多于“写”是协调服务的典型应用场景)。</li> <li>zookeeper有临时节点的概念,当创建临时节点的客户端会话一直保持活动,瞬时节点就一直保持存在。而当会话终结时,瞬时节点被删除。持久节点是指,一旦这个zNode被创建,除非主动的进行在zNode的移除操作,否则这个zNode将一直保持在zookeeper上。</li> <li>zookeeper底层其实只提供了两个功能:1.管理(存储、读取)用户程序提交的数据;2.为用户程序提供数据节点监听服务。</li> </ul> <h3>2.2 会话(Session)</h3> <p>Session是指zookeeper服务器与客户端会话。在zookeeper中,一个客户端连接是指客户端和服务器间的一个tcp长连接。 客户端启动时,首先与服务端建立一个tcp连接。通过这个连接,客户端能够通过心跳检测与服务器保持有效的会话, 也能够向zookeeper服务器发送请求并接受响应,同时还能通过该连接接收来自服务器的watch事件通知。 Session的sessionTimeout值用来设置一个客户端的超时时间。若客户端连接断开,只要在sessionTimeout规定的时间内 重新连接上集群中的任意一台服务器,之前创建的会话就还有效;在为客户端创建会话之前,服务端会为每个客户端创建 一个sessionId,sessionId要保证全局唯一性。</p> <h3>2.3 Znode</h3> <ul> <li>在谈到分布式的时候,我们谈的节点是指组成集群的每一台机器,然而,在zookeeper中,节点分为两类:一是指构成集群的机器,我们称之为机器节点;二是指数据模型中的数据单元,我们称之为数据节点---Znode。Zookeeper将所有数据存储在内存中,数据模型是一棵树(Znode Tree),由斜杠(/)的进行分割的路径,就是一个Znode,例如/foo/path1。每个上都会保存自己的数据内容,同时还会保存一系列属性信息。</li> <li>zookeeper数据模型:ZNode(数据节点)是 ZooKeeper 中数据的最小单元,每个ZNode上都可以保存数据,同时还是可以有子节点(这就像树结构一样),提到数据模型,就有必要说一下事务ID。</li> <li>在Zookeeper中,事务是指能够改变 ZooKeeper 服务器状态的操作,我们也称之为事务操作或更新操作,一般包括数据节点创建与删除、数据节点内容更新和客户端会话创建与失效等操作。对于每一个事务请求,ZooKeeper 都会为其分配一个全局唯一的事务ID,用 ZXID 来表示,通常是一个64位的数字。每一个ZXID对应一次更新操作,从这些 ZXID 中可以间接地识别出Zookeeper处理这些更新操作请求的全局顺序。</li> <li>每个Znode节点由两部分组成:1.stat,状态信息;2.data,数据内容</li> <li>Znode可以分为持久节点和临时节点两类。所谓持久节点是指一旦这个ZNode被创建了,除非主动进行ZNode的移除操作,否则这个ZNode将一直保存在Zookeeper上。而临时节点就不一样了,它的生命周期和客户端会话绑定,一旦客户端会话失效,那么这个客户端创建的所有临时节点都会被移除。</li> </ul> <h3>2.4 版本</h3> <p>Zookeeper 的每个 ZNode 上都会存储数据,对应于每个ZNode,Zookeeper 都会为其维护一个叫作 Stat 的数据结构,Stat 中记录了这个 ZNode 的三个数据版本, 分别是version(当前ZNode的版本)、cversion(当前ZNode子节点的版本)和 aversion(当前ZNode的ACL版本)。</p> <h3>2.5 Watcher</h3> <p>Watcher(事件监听器),是Zookeeper中的一个很重要的特性。Zookeeper允许用户在指定节点上注册一些Watcher,并且在一些特定事件触发的时候, ZooKeeper服务端会将事件通知到感兴趣的客户端上去,该机制是Zookeeper实现分布式协调服务的重要特性。</p> <h3>2.6 ACL</h3> <p>Zookeeper采用ACL(AccessControlLists)策略来进行权限控制,类似于 UNIX 文件系统的权限控制。Zookeeper 定义了5种权限。 1.CREATE:创建子节点的权限;2.READ:获取节点数据和子节点列表的权限;3.WRITE:更新节点数据的权限;4.DELETE:删除子节点的权限;5.ADMIN:设置节点ACL的权限。 使用[scheme:id:permissions]来表示acl权限。</p> <h2>3 zookeeper的特点</h2> <ul> <li>顺序一致性:从同一客户端发起的事务请求,最终将会严格的按照顺序被应用到zookeeper中去。</li> <li>原子性:所有事务请求的处理结果在整个集群的所有机器上的应用情况是一致的,也就是说,要么整个集群中的所有机器都成功应用了某一个事务请求,要么都没有应用成功。</li> <li>单一系统映象:无论客户端连接到哪一个zookeeper服务器上,其看到的服务端数据模型都是一致的。</li> <li>一旦一次更改请求被应用,更改的结果就会持久化,直到下一次更改覆盖。</li> </ul> <h2>4 zookeeper的设计目标</h2> <ul> <li>简单的数据模型,ZooKeeper 允许分布式进程通过共享的层次结构命名空间进行相互协调,这与标准文件系统类似。名称空间由 ZooKeeper 中的数据寄存器组成 - 称为znode,这些类似于文件和目录。ZooKeeper数据保存在内存中。</li> <li>可构建集群,为了保证高可用,最好是以集群形态来部署 ZooKeeper,这样只要集群中大部分机器是可用的(能够容忍一定的机器故障),那么zookeeper本身仍然是可用的。</li> <li>顺序访问,对于来自客户端的每个更新请求,ZooKeeper 都会分配一个全局唯一的递增编号,这个编号反应了所有事务操作的先后顺序,应用程序可以使用 ZooKeeper 这个特性来实现更高层次的同步原语。 这个编号也叫做时间戳——zxid(Zookeeper Transaction Id)。</li> <li>高性能,ZooKeeper 是高性能的。 在“读”多于“写”的应用程序中尤其地高性能,因为“写”会导致所有的服务器间同步状态。(“读”多于“写”是协调服务的典型场景。)</li> </ul> <h2>5 zookeeper集群角色介绍</h2> <ul> <li>最典型的模式:master/slave模式(主备模式),在这种模式中,通常master服务器作为主服务器提供写服务,其它的slave从服务器通过异步复制的方式获取master服务器的最新数据提供读服务。</li> <li>在zookeeper中没有选择传统的主备模式,而是引入了leader、follower、observer三种角色。ZooKeeper 集群中的所有机器通过一个 Leader 选举过程来选定一台称为 “Leader” 的机器,Leader 既可以为客户端提供写服务又能提供读服务。除了 Leader 外,Follower 和 Observer 都只能提供读服务。Follower 和 Observer 唯一的区别在于 Observer 机器不参与 Leader 的选举过程,也不参与写操作的“过半写成功”策略,因此 Observer 机器可以在不影响写性能的情况下提升集群的读性能。</li> <li>leader的选举过程 <ol> <li>Leader election(选举阶段):节点在一开始都处于选举阶段,只要有一个节点得到超半数节点的票数,它就可以当选准 leader。</li> <li>Discovery(发现阶段):在这个阶段,followers 跟准 leader 进行通信,同步 followers 最近接收的事务提议。</li> <li>Synchronization(同步阶段):同步阶段主要是利用 leader 前一阶段获得的最新提议历史,同步集群中所有的副本。同步完成之后 准 leader 才会成为真正的 leader。</li> <li>Broadcast(广播阶段) 到了这个阶段,Zookeeper 集群才能正式对外提供事务服务,并且 leader 可以进行消息广播。同时如果有新的节点加入,还需要对新节点进行同步。</li> </ol></li> </ul> <h2>6 ZAB协议</h2> <ul> <li>ZAB(ZooKeeper Atomic Broadcast 原子广播) 协议是为分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的原子广播协议。 在 ZooKeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性,基于该协议,ZooKeeper 实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性。</li> <li>协议两种基本的模式:崩溃恢复和消息广播。 <ol> <li>当整个服务框架在启动过程中,或是当 Leader 服务器出现网络中断、崩溃退出与重启等异常情况时,ZAB 协议就会进人恢复模式并选举产生新的Leader服务器。当选举产生了新的 Leader 服务器,同时集群中已经有过半的机器与该Leader服务器完成了状态同步之后,ZAB协议就会退出恢复模式。其中,所谓的状态同步是指数据同步,用来保证集群中存在过半的机器能够和Leader服务器的数据状态保持一致。</li> <li>当集群中已经有过半的Follower服务器完成了和Leader服务器的状态同步,那么整个服务框架就可以进人消息广播模式了。当一台同样遵守ZAB协议的服务器启动后加人到集群中时,如果此时集群中已经存在一个Leader服务器在负责进行消息广播,那么新加人的服务器就会自觉地进人数据恢复模式:找到Leader所在的服务器,并与其进行数据同步,然后一起参与到消息广播流程中去。正如上文介绍中所说的,ZooKeeper设计成只允许唯一的一个Leader服务器来进行事务请求的处理。Leader服务器在接收到客户端的事务请求后,会生成对应的事务提案并发起一轮广播协议;而如果集群中的其他机器接收到客户端的事务请求,那么这些非Leader服务器会首先将这个事务请求转发给Leader服务器。</li> </ol></li> </ul> <h2>7 zookeeper作为注册中心</h2> <p>简单来讲,zookeeper可以充当一个服务注册表(Service Registry),让多个服务提供者形成一个集群,让服务消费者通过服务注册表获取具体的服务访问地址(ip+端口)去访问具体的服务提供者。具体来说,</p> <ol> <li>每当一个服务提供者部署后都要将自己的服务注册到zookeeper的某一路径上: /{service}/{version}/{ip:port}。</li> <li>zookeeper提供了“心跳检测”功能,它会定时向各个服务提供者发送一个请求(实际上建立的是一个 Socket 长连接),如果长期没有响应,服务中心就认为该服务提供者已经“挂了”,并将其剔除。</li> <li>服务消费者会去监听相应路径(/{service}/{version}),一旦路径上的数据有任务变化(增加或减少),zookeeper都会通知服务消费方服务提供者地址列表已经发生改变,从而进行更新。</li> <li>更为重要的是zookeeper与生俱来的容错容灾能力(比如leader选举),可以确保服务注册表的高可用性。</li> </ol> <h2>8 zookeeper基础命令</h2> <ul> <li>stat path: 获得节点的更新信息,与get命令类似</li> <li>set path data: 修改节点</li> <li>ls path: 查看path路径下的节点</li> <li>ls2 path: 查看path路径下的节点,并获取节点数据和更新信息,相当于执行ls和stat两条命令</li> <li>delete path: 删除节点</li> <li>get path: 获取节点数据和更新信息</li> <li>create [-s] [-e] path data acl: 创建节点,-e表示创建临时节点,-s表示创建顺序节点,acl表示创建节点时设置ACL权限。</li> <li>getAcl path: 获取节点的ACL权限。</li> <li>setAcl path [权限]: 设置节点ACL的权限。</li> <li>close:</li> <li>connect host:port :</li> </ul> <h2>9 watcher通知机制</h2> <p>watcher机制大体的理解可以为,当每个节点发生变化,都会触发watcher事件,类似于mysql的触发器。子节点创建和删除时触发watch事件,子节点修改不会触发该事件。</p> <h2>10 zookeeper应用场景</h2> <ul> <li>分布式协调</li> <li>分布式锁</li> <li>元数据/配置信息管理(配置中心)</li> <li>HA高可用性</li> </ul> <h3>10.1 分布式协调</h3> <p>这个其实是 zookeeper 很经典的一个用法,简单来说,就好比,你 A 系统发送个请求到 mq,然后 B 系统消息消费之后处理了。那 A 系统如何知道 B 系统的处理结果? 用 zookeeper 就可以实现分布式系统之间的协调工作。A 系统发送请求之后可以在 zookeeper 上对某个节点的值注册个监听器,一旦 B 系统处理完了就修改 zookeeper 那个节点的值, A 系统立马就可以收到通知,完美解决。 <img src="https://s2.ax1x.com/2019/12/17/QomIeg.png" alt="分布式协调" /></p> <h3>10.2 分布式锁</h3> <p>举个栗子。对某一个数据连续发出两个修改操作,两台机器同时收到了请求,但是只能一台机器先执行完另外一个机器再执行。那么此时就可以使用 zookeeper 分布式锁, 一个机器接收到了请求之后先获取 zookeeper 上的一把分布式锁,就是可以去创建一个 znode,接着执行操作;然后另外一个机器也尝试去创建那个 znode, 结果发现自己创建不了,因为被别人创建了,那只能等着,等第一个机器执行完了自己再执行。 <img src="https://s2.ax1x.com/2019/12/17/Qom4OS.png" alt="HA高可用" /></p> <h3>10.3 配置中心</h3> <p>zookeeper 可以用作很多系统的配置信息的管理,比如 kafka、storm 等等很多分布式系统都会选用 zookeeper 来做一些元数据、配置信息的管理, 包括 dubbo 注册中心不也支持 zookeeper 么? <img src="https://s2.ax1x.com/2019/12/17/Qomhy8.png" alt="分布式锁" /></p> <h3>10.4 HA高可用</h3> <p>这个应该是很常见的,比如 hadoop、hdfs、yarn 等很多大数据系统,都选择基于 zookeeper 来开发 HA 高可用机制,就是一个重要进程一般会做主备两个, 主进程挂了立马通过 zookeeper 感知到切换到备用进程。 <img src="https://s2.ax1x.com/2019/12/17/QomfQf.png" alt="配置信息管理" /></p> <h2>11 zookeeper集群搭建</h2> <ul> <li>解压:tar -zxvf zookeeper-3.4.9.tar.gz</li> <li>创建配置文件:cp ./conf/zoo_sample.cfg ./conf/zoo.cfg</li> <li> <p>编辑配置文件:</p> <pre><code class="language-text">dataDir=../data dataLogDir=../logs server.1=ip1:2888:3888 server.2=ip2:2888:3888 server.3=ip3:2888:3888 #server.1 这个1是服务器的标识也可以是其他的数字, 表示这个是第几号服务器,用来标识服务器,这个标识要写到快照目录下面myid文件里 #第一个端口是master和slave之间的通信端口,默认是2888,第二个端口是leader选举的端口,集群刚启动的时候选举或者leader挂掉之后进行新的选举的端口默认是3888 </code></pre> </li> <li>在dataDir目录下创建 myid 文件,文件内容填写服务器的标识,如:1,2,3。创建命令:vi data/myid</li> <li>启动zookeeper,命令:bin/zkServer.sh start</li> <li>查看集群状态,命令:bin/zkServer.sh status</li> </ul>

页面列表

ITEM_HTML