ZK_03Zookeeper分布式锁和注册中心使用
2023-05-17 10:14:42 4 举报
AI智能生成
登录查看完整内容
Zookeeper分布式锁和注册中心使用
作者其他创作
大纲/内容
来处理跨机器的进程之间的数据同步问题,这种跨机器的锁就是分布式锁
概念
每时每刻,zk集群中任意节点(一个zk server)上的相同znode的数据是一定是相同的
span style=\
所有试图来获取这个锁的客户端,最终只有一个可以成功获得这把锁
zk上的一个znode看作是一把锁,通过create znode的方式来实现
所有客户端都去创建 /distribute_lock 节点,最终成功创建的那个客户端也即拥有了这把锁
保持独占
所有来获取这个锁的客户端,最终都是会被安排执行,只是有个全局时序了
通过创建临时有序节点
控制时序
锁服务可以分为两类,一个是保持独占,另一个是控制时序
特点
db操作性能较差,并且有锁表的风险,一般不考虑
数据库的分布式锁
适用于并发量很大、性能要求很高而可靠性问题可以通过其他方案去弥补的场
Redis的分布式锁
适用于高可靠(高可用),而并发量不是太高的场景
ZooKeeper的分布式锁
主流的方案
创建一个临时节点lock
执行完业务释放锁(断开连接,临时节点失效、)
如果创建成功则获取锁
再去竞争去创建临时节点获取锁
如果创建失败则使用watch机制,检测临时节点失效等于释放锁
如果所有的锁请求者都 watch 锁持有者,当代表锁持有者的 znode 被删除以后,所有的锁请求者都会通知到,但是只有一个锁请求者能拿到锁
问题
思路1
创建一个临时顺序节点lock
将子节点按照序号大小从小到大排序
将节点序号最小的获取锁
阻塞的节点监听比自己小1的节点
其他节点继续阻塞,等待唤醒
当检测到临时节点失效时,则阻塞节点依次唤醒
去获取lock 下的子节点
思路2
ZooKeeper分布式锁(如InterProcessMutex),具备高可用、可重入、阻塞锁特性,可解决失效死锁问题
优点
因为需要频繁的创建和删除节点,性能上不如Redis
在高性能、高并发的应用场景下,不建议使用ZooKeeper的分布式锁
缺点
并发量不是太高的应用场景中,还是推荐使用ZooKeeper的分布式锁
Curator 可重入分布式锁
思路3
Zookeeper分布式锁
将 key 的值设为 value,若给定的 key 已经存在,则 SETNX 不做任何动作
setnx key value
返回(integer) 0
EXISTS job # job这个key不存在
(integer) 1
SETNX job \"programmer\" # 设置job
(integer) 0
SETNX job \"programmer2\" # 重新设置job,失败
\"programmer\"
GET job # job还是第一次设置的值
使用方法
根据setnx的结果来判断是否是获取到锁,是就执行减库存的操作,不是则返回网络错误
try…finally来解决
当在执行删除key的操作前,程序异常退出了,后面的请求永远不会执行到减库存的逻辑
等到过期时间到后key就会被redis销毁掉,不会影响其他的请求
设置过期时间的代码和设置锁值的代码应该使用原子性来执行
除了程序异常退出,还可能机器宕机,这样异常就捕获不到了,这是就需要给key设置一个过期时间
使用思路
setnx
//拿到锁对象RLock redissonLock=redisson.getLock(couponKey);
获得redisson锁
加锁(同时实现加锁,看门狗锁续命的功能)
//解锁redissonLock.unlock();
释放锁
让后面的线程无法删除前面线程
如果业务代码在无异常,并且仍然在执行的情况下,我们加一个可以自动将锁时间延长的功能
锁续命
考虑到业务时间比超时时间长,考虑可以给锁续命的问题
释放锁的时候,如果出现异常续命任务还会继续执行
释放锁如何保持原子性
redisson
redis分布式锁
插入一条数据lock字段作为唯一键
执行完业务释放锁
如果插入成功则可以加锁成功,
如果插入失败则等待,唯一数据删除后才能获取锁
当输入获取到锁的服务宕机了,则无法释放锁,其他服务将一直处于等待状态
数据库分布式锁
实现思路
分布式锁
注册中心 :保存所有服务的名字,服务提供者的ip列表,服务消费者的IP列表
服务提供者: 提供跨进程服务
服务消费者: 寻找到指定命名的服务并消费
RPC框架中有3个重要的角色
让多个服务提供者形成一个集群
让服务消费者通过服务注册表获取具体的服务访问地址(ip+端口)去访问具体的服务提供者
zookeeper可以充当一个服务注册表(Service Registry)
IP
端口
调用方式
协议
序列化方式
该节点承担着最重要的职责,它由服务提供者(发布服务时)创建
以供服务消费者获取节点中的信息,从而定位到服务提供者真正网络拓扑位置以及得知如何调用
在zookeeper中创建了一个znode节点
服务提供者启动时,会将其服务名称,ip地址注册到配置中心
当消费者调用服务时,不会再去请求注册中心,而是直接通过负载均衡算法从IP列表中取一个服务提供者的服务器调用服务
当某个服务的所有服务器都下线了,那么这个服务也就下线了
服务提供方可以根据服务消费者的数量来作为服务下线的依据
过程
服务注册
定时向各个服务提供者发送一个请求(长链接)
如果长期没有响应,服务中心就认为该服务提供者已经“挂了,并将其剔除
服务消费者会去监听相应服务路径
路径上的数据有任务变化(增加或减少)
zookeeper都会通知服务消费方服务提供者地址列表已经发生改变,从而进行更新
zookeeper实现方式
心跳检测功能
感知服务
zookeeper 与生俱来的容错容灾能力(比如leader选举),可以确保服务注册表的高可用性
主要是方便对调用方进行统计、管理
zookeeper 作为注册中心时,客户端订阅服务时会向 zookeeper注册自身
订阅时是否注册 client 不是必要行为,和不同的注册中心实现有关,例如使用 consul 时便没有注册
注册中心
Zookeeper分布式锁和注册中心使用
0 条评论
回复 删除
下一页