当前位置: 首页 > 科技观察

举例说明ZooKeeper的典型应用场景,超简单

时间:2023-03-16 12:44:49 科技观察

0简介zookeeper在很多框架中都有使用,比如Dubbo、Hadoop、Kafka等,但只有几个典型的用法。掌握了这些用法后,看zookeeper在相关框架中的应用就很容易了。下一篇文章将详细介绍zookeeper在dubbo中的使用,以便有更深入的了解。本文参考《从Paxos到ZooKeeper》,由于本文的定位是科普文,所以不再对共享锁、分布式队列等具体实现做更详细的描述。在实际工作中需要实现时可以参考本书。zookeeper的数据模型类似于文件系统。每个节点称为一个znode,是zookeeper中最小的数据单元,每个znode可以上报数据和挂载子节点,从而形成一个层次化的属性结构。可以创建以下四种类型的节点(znode)持久化节点:节点创建后,会一直存在于zookeeper服务器上,直到持久化顺序节点被主动删除:每个节点都会为其一级子节点维护一个序列nodes临时节点:临时节点的生命周期与客户端的session一致。当客户端会话失败时,节点自动清理临时顺序节点:临时节点增加一个顺序特征。简单演示常用命令create[-s][-e]pathdataacl-s:创建顺序节点-e:创建临时节点path:pathdata:dataacl:permissioncreate默认创建持久化节点create/level-1123create/level-1/level-1-2456get/level-1(获取节点level-1的值,输出123)ls/level-1(获取节点level-1的子节点,输出[level-1-2])//创建一个时序节点create-s/nodes123(实际是nodes0000000003)create-s/nodes456(实际是nodes0000000004)上面的命令执行后,数据结构如下:这里简单说明一下顺序节点的特征。每创建一个顺序节点,zk会自动在路径后面加上一个10位的数字(计数器),比如0000000001,0000000002,...这个计数器可以保证同一个下唯一父节点。zk内部用一个4字节的有符号整数来表示这个计数器,也就是说,当计数器的大小超过2147483647时,就会发生溢出,每次在父节点下创建一个顺序节点,大小为增加1。如上图3-4所示,zookeeper提供分布式数据发布/订阅,允许客户端向服务端注册一个watcher。当服务端的某些指定事件触发watcher时,会向指定的客户端发送事件通知,实现分布式通知功能。简单给几个watcher事件类型EventType触发条件NodeCreated(节点创建)Watcher监听的对应数据节点创建NodeDeleted(节点删除)Watcher监听的对应数据节点删除NodeDataChanged(节点数据modification)Watcher监听的对应数据节点数据内容发生变化NodeChildrenChanged(childnodechange)Watcher监听的对应数据节点的子节点列表发生变化。所谓配置中心,顾名思义就是发布者向zookeeper的一个或一系列节点发布数据,供订阅者订阅数据,从而达到动态获取数据的目的,实现配置信息和动态数据的集中管理更新。zookeeper采用push和pull相结合的方式实现发布订阅系统:客户端向服务端注册自己需要关注的节点,一旦该节点的数据发生变化,服务端就会发送一个Watcher事件通知给相应的客户端,客户端收到这条消息的通知后,需要主动去服务端获取最新的数据。程序总是需要配置的。如果程序部署在多台机器上,更改配置就变得困难了。好了,现在把这些配置都放到zookeeper上,保存在zookeeper的某个目录节点下,然后所有相关的应用程序都会监控这个目录节点。一旦配置信息发生变化,各个应用都会收到zookeeper的通知,然后从zookeeper中获取新的配置信息应用到系统中。2负载均衡每台服务器在启动时都会在zookeeper的servers节点下注册一个临时节点(注册临时节点是因为当服务不可用时,临时节点就会消失,客户端不会请求服务器),当每个client启动后,会去servers节点获取所有可用的工作服务器列表,通过一定的负载均衡算法计算出请求应该发送到哪个服务器。3在过去的单数据库列表中生成分布式唯一ID在表型系统中,通常可以利用数据库字段的auto_increment属性为每条记录自动生成一个唯一ID。但是数据库分表后,就不能再依赖数据库的auto_increment属性来唯一标识一条记录了。此时,我们可以使用zookeeper在分布式环境中生成一个全局唯一的ID。方法如下:每次要生成新的ID时,创建一个持久化的时序节点,创建操作返回的节点序号为新的ID,然后删除比自己节点小的节点。4Master选举Master选举是分布式系统中非常常见的一个应用场景。在分布式系统中,Master经常用来协调系统中的其他系统单元,拥有改变分布式系统状态的决定权。例如,在一些使用读写分离的应用场景中,客户端的写请求往往由Master来处理,而在其他场景中,Master往往负责处理复杂的逻辑,并将处理结果同步到集群中。其他系统单位。选主可以说是zookeeper最典型的应用场景。利用zookeeper的强一致性可以很好的保证分布式高并发情况下创建节点必须保证全局唯一性,即zookeeper会保证客户端不能重复创建一个已经存在的数据节点。也就是说,如果多个客户端同时请求创建同一个节点,最后一定只有一个客户端能够创建成功。利用这个特性,可以很容易地在分布式环境中进行Master选举。客户端集群在zookeeper上创建一个/master临时节点。在这个过程中,只有一个client能够成功创建这个节点,那么这个client就成为了master。同时,其他在zookeeper上没有成功创建节点的client会在node/master上注册一个changedwatcher来监听当前master机器是否存活。一旦发现当前master挂了,剩下的clients会重新选举master。5.分布式锁在同一个JVM中。为了保证对资源的有序访问,比如将数据写入文件,可以使用synchronized或者ReentrantLock来实现对资源的互斥访问。如果两个程序在不同的JVM中,并且必须向同一个文件写入数据,如何保证互斥访问?这时候就需要分布式锁了。目前主流的分布式锁有两种实现方式:使用redissetnex(keyvalue)key不存在则返回0,key存在则返回1Zookeeper实现独占锁、共享锁(读锁)这里是排它锁的实现简单介绍实现原理和master选举类似。所有客户端在/exclusive_lock节点下创建一个临时子节点/exclusive_lock/lock。Zookeeper会保证在所有的client中,只有一个client能够创建成功,所以该client被认为已经获取到锁,其他没有获取到锁的client需要去/exclusive_lock节点注册一个watcher监听子节点变化,从而实时监控锁节点的变化。释放锁有两种情况:正在获取锁如果客户端宕机,zookeeper上的临时节点会被删除。业务逻辑正常执行后,客户端会主动删除自己创建的临时节点。整个独占锁的获取和释放过程可以用下图来表示:6分布式队列如下图,创建/queue为一个队列,然后每次创建一个顺序节点,将其视为一个消息(节点存储的数据就是消息内容),生产者每次创建一个新的节点作为消息发送和消费运营者监听队列子节点的变化(或者定时轮询),取每次作为消费消息的最小节点,处理后删除该节点。相当于实现了一个FIFO(先进先出)队列。注意:zookeeper强调的是CP(一致性),不是为高并发、高性能的场景设计的。如果是高并发,qps高,需要适当考虑分布式队列。