分布式锁
使用Zookeeper实现分布式锁,只需要用到节点的两个特性:临时节点和同级节点的唯一性
先创建一个永久节点:/Exclusive_Locks节点
-
获得锁的过程
所有客户端节点都到 /Exclusive_Locks节点下去创建临时节点 /Locks节点,此时只有一个客户端会创建成功。创建成功的这个客户端就相当于获得了锁,其他节点就通过 Watcher机制监听 /Exclusive_Locks节点下的子字节的变化,以做出相应的反应。
-
释放锁的过程
在下列两种情况下会释放锁
- 获得锁的客户端和Zookeeper的连接端口,基于临时节点的特性, /Lock 节点会被自动删除
- 获得锁的客户端在执行玩任务后,主动删除 /Lock 节点
当 /Lock 节点被删除后,Zookeeper服务器会通知所有监听了 /Exclusive_Locks 子节点变化的客户端。这些客户端收到通知后,再次发起创建 /Lock 节点的操作来获得分布式锁。
此时会出现一种情况,当获得分布式锁的客户端正在执行任务时,与Zookeeper服务的连接断开了,/Lock 节点被删除,其他客户端收到通知,就会再去获取分布式锁,此时就出现了两个客户端都获得分布式锁的情况。所以这里应该有一种机制来判断,如当获取到锁的客户端处理玩任务后,应当判断一下当前的 /Lock 锁是否还是自己持有,是则提交处理结果,否则直接放弃本次处理结果,等待后续再次获取锁。
上述通知全部未获取到锁的客户端会出现一个问题,当客户端较多时,网络传输和延迟是一个很大的开销,此即所谓“惊群现象”。为解决这个问题,可以采用下面的方式:
所有客户端都向 /Exclusive_Locks 节点创建临时顺序节点,此时所有客户端都会创建成功,但创建的节点是有顺序的。客户端创建节点成功后,判断自己创建的节点是否为最小节点,如果是最小节点表示获得锁,如果不是最小节点,就对上一个节点添加一个监听。这样当上一个节点释放锁后,就会通知下一个节点,依次往下,每个客户端轮流获得锁。
Master选举
Master选举机制是在一个集群中选择一个节点作为Master节点,其他节点作为备份节点。
使用Zookeeper实现Master选举机制有下面两种方式
- 和上面实现分布式锁的操作一样,所有客户端都向Zookeeper创建一个 /Master_ele 临时节点,只有一个客户端会创建成功。创建成功这个节点即为Master节点,其余节客户端为备份节点,并监听 /Master_ele节点。当Master节点挂掉后,Zookeeper会通知所有备份节点,于是重复之前的过程,选举出一个Master节点。和分布式锁不同的一点是,客户端并不主动删除 /Master_ele 节点。
- 第二种方式和实现分布式锁的第二种方式的操作也是一样的,区别也在于客户端不会主动删除节点。
实现服务注册中心
利用Zookeeper的永久节点、临时节点、Watcher机制,可以实现服务注册中心功能
例如现在有3个服务提供者节点 service-provider, 一个服务消费者节点 service-consumer
以dubbo客户端注册为例,服务提供者节点启动时,在根节点下创建一个 /dubbo 永久节点 ,再创建一个 /dubbo/service/providers永久节点,每个服务提供者客户端再在/dubbo/service/provider节点下创建一个临时节点 dubbo://ip1:20880,dubbo://ip2:20880,dubbo://ip3:20880。
服务调用者启动时在/dubbo/service节点下创建一个 /consumers 永久节点,同时在 /consumers 节点下创建一个 consumer://ip:20880 临时节点。服务调用者在第一次调用服务时,获取 /dubbo/service/providers 节点下的所有子节点,并监听该节点下子节点的变化。此时服务调用者就获取到了服务提供者的列表,调用者可以根据调用策略对服务提供者做负载均衡调用,当有服务提供者掉线时,会通知服务调用者更新服务列表。