Zookeeper 锁
Zookeeper实现分布式锁
1.0版本
使用一个临时节点利用及诶单的特性同时只有一个客户端可以对节点操作
实现分布式锁
Step.1 用zookeepr中的一个临时节点代表锁 如 创建一个/exlusive_lock下创建临 时znode /exlusive_locak/lock 这个操作
Step.2 当所有的客户端区争抢执行 创建此节点 同时只有一个客户端执行操作
Step.3 创建成功 代表当前客户端获取锁成功 当前客户端执行业务逻辑
Step.4 为创建成功的客户端 监听 /exlusive_lock 变更
Step.5 获取锁的客户端执行完成后删除 /exlusive_lock/lock 表示锁被释放
Step.6 锁被释放之后 其他客户端监听得到通知 再次争抢
这与java的sync锁机制相类似,锁的获取顺序与客户端的争抢顺序不同,但是可能存在同一个客户端多次获取,所以1.0版本的临时节点锁不是一个公平锁
当同时争抢的客户端太多会浪费过多的资源到锁的争抢过程中
2.0版本
为了避免1.0中出现的资源浪费和不公平锁的存在,我们引入 之前使用的有序节点,让每个客户端执行 在/exlusive_lock 中创建临时节点为有序节点,这样每个客户端都会在/exlusive_lock下有自己的对应锁节点 这样让每一个成功执行的客户端有一个简单的执行序列,当序号在前面的znode代表对应的客户端获取锁成功,后面的znode监听前面的znode执行完成之后得到通知自己在执行。
Step.1 每个客户端 /exlusive_lock 下创建对应的临时节点 /exlusive_lock/lock_0 创建成功之后 /exlusive_lock 下面会有每个客户端对应的节点 例 /exlusive_lock/lock_000000001
Step.2 客户端获取 /exlusive_lock下子节点 判断自己创建节点位置
Step.3 客户端判断为第一位 代表获取锁成功 此客户端执行业务逻辑
Step.4 判断不是第一位 监听前一位所节点执行情况
Stpe.5 前一个锁执行完毕释放锁,后一个锁监听机制触发开始执行业务逻辑
Stpe.6 后续锁对象客户端重复进行判断执行
Zookeeper框架Curator
实现的思路与之前2.0版本的思路相同
Step.1 创建临时节点
Step.2 触发 [尝试获取锁逻辑] 如果自己是节点第一个获取锁
Step.3 如果自己不是第一个 则监听前一个锁节点
Step.4 当前锁节点变更时通过watcher 恢复线程 再次到Step2 尝试获取锁逻辑
分布式锁应用场景
(1)解决单点故障
通常分布式系统采用主从模式,一个主控机连接多个处理节点,主节点负责发布任务,从节点负责处理任务,我们主节点发生故障整个系统瘫痪
解决方案
【方案一】采用备用节点,备用节点定期给主节点发送ping包,主节点收到ping包回复Ack,备用节点收到确认主节点存活继续工作
同理主节点崩溃之后备用节点收不到Ack回复,自己寻找从节点成为主节点
在分布式前提下可能会因为网络原因导致收不到Ack但是原来主节点存活,备用节点收不到Ack自然处理成为备用节点 双Master
(1)master启动
启动两个主节点 A和B 启动之后都向Zookeeper注册一个节点,注册完成之后进入选举,编号最小的成为主节点
(2)master故障
如果主节点A故障这是 A注册的节点自动删除,Zookeeper会自动感知节点变化,然后再次选举在存活的节点中选举 B获胜 代替A成为主节点
(3)Master恢复
如果主节点恢复之后会在你向zookeeper注册节点成为一个新的节点C 然后会继续进入选举阶段 主节点成为B 原来的A节点成为备用节点