ZooKeeper经典应用场景


数据发布/订阅(配置中心)

数据发布/订阅(Publish/Subscribe)系统,即所谓的配置中心。发布者将数据发布到Zookeeper的一个节点或一系列节点上,供订阅者进行数据订阅,进而达到动态获取数据的目的,实现配置信息的集中式管理和数据的动态更新。

发布/订阅系统一般有两种设计模式,分别为推(Push)和拉(Pull)模式。

推模式:服务器主动将数据更新发送给所有订阅的客户端。

拉模式:客户端主动发起请求获取最新数据,通常客户端采用定时轮询的方法拉取。

Zookeeper采用是推拉结合的方式:客户端向服务端注册自己需要关注的节点,一旦该节点数据发生变更,服务器会向相应的客户端发送Watcher时间通知,客户端收取到通知后,需要主动到服务器获取最新的数据。

配置存储

首先我们需要将初始化配置存储到Zookeeper上,一般情况下,我们可以在Zookeeper上选取一个数据节点用于配置信息的存储。

#Zookeeper节点路径
/config/dev/
#子节点
/config/dev/customer
#子节点数据
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:127.0.0.1:3306/customer
jdbc.username=test
jdbc.password=123456
....
#子节点
/config/dev/shop
#子节点数据
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:127.0.0.1:3306/shop
jdbc.username=test
jdbc.password=123456

配置获取

集群中每台集群在启动初始化阶段,首先会从上面Zookeeper配置节点上读取配置信息,同时,客户端还需要在改节点上注册一个数据变更的Watcher监听,一旦节点数据发生变更,那么所有订阅的客户端都能够获取到数据变更通知。

配置变更

客户端收到Watcher的数据变更通知,会去拉取最想的配置信息数据。实现自动更新配置。

负载均衡

负载均衡(Load Balance)是一种相当常见的计算机网络技术,用来对多个计算机(计算机集群)、网络连接、CPU、磁盘驱动器或其他资源进行分配负载,以达到优化资源使用、最大化吞吐率、最小化响应时间和避免过载的目的。

动态DNS服务

DNS(Domain Name System,域名系统),DNS系统可以看做是一个超大规模的分布式映射表,用于将域名和IP地址进行一一映射。

域名配置

首先我们需要将初始化域名列表存储到Zookeeper上,一般情况下,我们可以在Zookeeper上选取一个数据节点用于域名列表的存储。

#Zookeeper节点路径
/dns
#Zookeeper子节点,这个为临时节点
/dns/customer.test.com
#节点数据
##单个IP地址
192.168.2.1:8080
##多个IP地址
192.168.1.1:8080,192.168.1.2

域名解析

域名解析的过程中都是每一个应用自己复制的,通常应用都会首先从域名节获取一份IP地址和端口的配置,进行自行解析。同时,每个应用会在域名节点上注册一个数据变更Watcher监听,以便及时收到域名变更的通知。

域名变更

当碰到需要变更域名列表中的IP地址或是端口变更是,只需要对指定的域名节点进行更新操作,Zookeeper会向所有订阅的客户端发送变更通知,应用在收到Watcher通知,拉取域名并重新解析。

命名服务

较为场景的就是一些分布式服务器框架(RPC、RMI)中的服务地址列表,通过使用命名服务,客户端应用能够根据指定名字来获取资源的实体、服务地址和提供者的信息等。

命名配置

首先在Zookeeper节点上创建/name节点,之后的子节点为对应服务在启动的时候在/name节点上创建临时子节点,并获取/name节点下所有的信息,并注册Watcher事件。

#Zookeeper节点路径
/name
#Zookeeper子节点,这个为临时节点,为Customer服务注册的节点
/name/customer
#Customer服务列表 节点为临时节点,且为服务自己创建的节点
#节点数据,如:操作系统、服务器情况等。
/name/customer/192.168.1.1:8080
/name/customer/192.168.1.2:8080

命名变更

当碰到对应服务不可以用,因为是临时节点就会自动删除自己创建的节点,Zookeeper会触发Watcher通知所有注册了的服务器,命名变换,拉取最新的数据。当有服务上线也是同样的操作。这样就可以做到自动更新服务器列表。

分布式协调/通知

对于分布式应用通常需要一个协调者来控制整个系统运行流程,如:分布式事务。引入这样一个协调者,可以将分布式协调的职责从应用中分离处理,从而减少系统之间的耦合性,提供系统的扩展性。

Zookeeper通过Watcher注册与异步通知机制,能够很好地实现分布式环境下不同服务,甚至不同系统之间的协调与通知,从而实现对数据变更的实时处理。

分布式锁

分布式锁是控制分布式系统之间同步访问共享资源的一种方式。如果不同的系统或是同一系统的不同主机之间共享一个或一组资源,那么访问这些资源的时候,往往需要通过一些互斥手段来防止彼此之间的干扰,以保证一致性,在这样情况下,就需要使用分布式锁。

排他锁

排他锁(Exclusive Locks,X锁),又称为独占锁或写锁。

如:事物T1对数据对象O1加上排他锁,那么在整个加锁期间,只允许事物T1对O1进行读取和更新操作,其他任何事物都不能在这个数据进行任何类型操作—直到T1释放了排他锁。

Zookeeper实现排他锁

ZooKeeper会保证在所有的客户端中,最终只有一个客户端能够创建成功。

获取锁

在需要获取排他锁时,所有的客户端都会试图通过调用create()接口,创建/exclusive_lock节点下创建临时子节点/exclusive_lock/lock,创建成功的客户端就认为获得了锁。同时,所有没有获取到锁的客户端就需要到/exclusive_lock节点上注册一个子节点变更的Watcher监听,以便实时监听到lock节点的变换情况。

释放锁

释放锁的情况:

  1. 当前获取锁的客户端机器发送宕机,那么ZooKeeper上的临时节点就会自动移除。
  2. 真诚执行完成业务逻辑后,客户端就会主动删除创建的临时节点。

在释放锁之后,ZooKeeper会通知所有在/exclusive_lock节点上注册了Watcher监听的客户端。这些客户端在收取到通知之后,再次发起分布式锁获取。

共享锁

共享锁(Shared Locks, S锁或读锁),如果事物T1对数据对象O1加上共享锁,那么当前事物只能对O1进行读取操作,其他事物也只能对这个这个对象加共享锁----直到该数据对象上所有共享锁都被释放

ZooKeeper实现共享锁

通过在/shared_lock节点下,创建一系列临时顺序子节点作为共享锁。

获取锁

在需要获取共享锁是,所有客户端都会到/shared_lock这个节点下面创建一个临时顺序节点,如果当前是读请求,那么就创建如:/shared_lock/192.168.1.1-R-00000001的节点;如果是写请求,那么就创建如:/shared_lock/192.168.1.2-W-00000001的节点。

判断读写顺序

根据共享锁的定义,不同的事物都可以同时对同一数据对象进行读取操作,而更新操作必须在当前没有任何事物进行读写操作的情况下进行。

  1. 创建玩节点后,获取/shared_lock节点下所有子节点,并对该节点注册了节点变更的Watcher监听。
  2. 确定自己的节点序号在所有节点中的顺序。
  3. 对于读请求:

如果没有比自己序号小的子节点,或是所有比自己序号小的子节点都是读请求,那么表明自己已经成功获取到了共享锁,同时开始执行读取逻辑。
如果比自己序号小的子节点中有写请求,那么就需要进入等待。
对于写请求
如果自己不是需要最小的子节点,那么就需要进入等待。否则执行写逻辑。

  1. 接受到Watcher通知后,重复步骤1。

释放锁

释放锁的逻辑和排他锁一致。

改进分布式共享锁实现

在/shared_lock注册Watcher通知,会导致每个客户端收到很多不是自己关心的通知。因为每个锁竞争者,只关注比自己序号小的那个节点。

每个锁竞争者,只需要关注比自己序号小的那个节点是否存在即可,

  1. 客户端调用create()接口创建类似与/shared_lock/192.168.1.1-R-00000001的节点。
  2. 客户端调用getChildren()接口来获取/shared_lock所有已创建的子节点列表,这里不需要注册Watcher事件。
  3. 如果无法获取共享锁,那么就调用exist()来对比自己小的那么节点注册Watcher,具体分为:读请求:向比自己序号小的最后一个写请求节点注册Watcher监听。 写请求:向比自己序号小的最后一个节点注册Watcher监听。
  4. 等待Watcher通知,继续进入步骤2。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值