zookeeper分布式锁

本文探讨了数据库锁(依赖唯一索引和乐观锁)、Redis缓存锁(包括setnx、expire和RedLock算法)以及Zookeeper分布式锁的实现与问题。特别强调了RedisRedLock算法的可靠性及其局限性,以及Zookeeper在分布式环境中的优势和挑战。
摘要由CSDN通过智能技术生成

一、数据库锁

  • 基于MySQL锁表

完全依靠数据库唯一索引来实现,当想要获得锁时,即向数据库中插入一条记录,释放锁时就删除这条记录

这种方式存在以下问题:

  • 锁没有失效时间,解锁失败会导致死锁,其他线程无法再获取到锁,因为唯一索引insert都会返回失败

  • 只能是非阻塞锁,insert失败直接就报错了,无法进入队列进行重试

  • 不可重入,同一线程在没有释放锁之前无法再获取到锁

  • 采用乐观锁

增加版本号,根据版本号来判断更新之前有没有其他线程更新过,如果被更新过,则获取锁失败

二、缓存锁

这里主要是几种基于redis的

  • 基于setnxexpire

基于setnx(set if not exist)的特点,当缓存里key不存在时,才会去set,否则直接返回false

如果返回true则获取到锁,否则获取锁失败,为了防止死锁,我们再用expire命令对这个key设置一个超时时间来避免。

但是这里看似完美,实则有缺陷,当我们setnx成功后,线程发生异常中断,expire还没来的及设置,那么就会产生死锁。

解决上述问题有两种方案

  • 采用redis2.6.12版本以后的set,它提供了一系列选项

EX seconds – 设置键key的过期时间,单位时秒

PX milliseconds – 设置键key的过期时间,单位时毫秒

NX – 只有键key不存在的时候才会设置key的值

XX – 只有键key存在的时候才会设置key的值

  • 第二种采用setnx(),get(),getset()

(1) 线程Asetnx,值为超时的时间戳(t1),如果返回true,获得锁。

(2) 线程B用get 命令获取t1,与当前时间戳比较,判断是否超时,没超时false,如果已超时执行步骤3

(3) 计算新的超时时间t2,使用getset命令返回t3(这个值可能其他线程已经修改过),如果t1==t3,获得锁,如果t1!=t3说明锁被其他线程获取了

(4) 获取锁后,处理完业务逻辑,再去判断锁是否超时,如果没超时删除锁,如果已超时,不用处理(防止删除其他线程的锁)

  • RedLock算法

redlock算法是redis作者推荐的一种分布式锁实现方式

(1) 获取当前时间;

(2) 尝试从5个相互独立redis客户端获取锁

(3) 计算获取所有锁消耗的时间,当且仅当客户端从多数节点获取锁,并且获取锁的时间小于锁的有效时间,认为获得锁

(4) 重新计算有效期时间,原有效时间减去获取锁消耗的时间

(5) 删除所有实例的锁

redlock算法相对于单节点redis锁可靠性要更高,但是实现起来条件也较为苛刻

(1) 必须部署5个节点才能让Redlock的可靠性更强

(2) 需要请求5个节点才能获取到锁,通过Future的方式,先并发向5个节点请求,再一起获得响应结果,能缩短响应时间,不过还是比单节点redis锁要耗费更多时间

然后由于必须获取到5个节点中的3个以上,所以可能出现获取锁冲突,即大家都获得了1-2把锁,结果谁也不能获取到锁,这个问题,redis作者借鉴了raft算法的精髓,通过冲突后在随机时间开始,可以大大降低冲突时间,但是这问题并不能很好的避免,特别是在第一次获取锁的时候,所以获取锁的时间成本增加了

如果5个节点有2个宕机,此时锁的可用性会极大降低,首先必须等待这两个宕机节点的结果超时才能返回,另外只有3个节点,客户端必须获取到这全部3个节点的锁才能拥有锁,难度也加大了

如果出现网络分区,那么可能出现客户端永远也无法获取锁的情况

介于这种情况,下面我们来看一种更可靠的分布式锁zookeeper锁

zookeeper分布式锁

=============

zookeeper是一个为分布式应用提供一致性服务的软件,它内部是一个分层的文件系统目录树结构,规定统一个目录下只能有一个唯一文件名

数据模型


  • 永久节点

节点创建后,不会因为会话失效而消失

  • 临时节点

与永久节点相反,如果客户端连接失效,则立即删除节点

  • 顺序节点

与上述两个节点特性类似,如果指定创建这类节点时,zk会自动在节点名后加一个数字后缀,并且是有序的

监视器(watcher):


当创建一个节点时,可以注册一个该节点的监视器,当节点状态发生改变时,watch被触发时,ZooKeeper将会向客户端发送且仅发送一条通知,因为watch只能被触发一次

根据zookeeper的这些特性来实现分布式锁

  1. 创建一个锁目录lock

  2. 希望获得锁的线程A就在lock目录下,创建临时顺序节点
    先自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以扫码领取!

img

分享

首先分享一份学习大纲,内容较多,涵盖了互联网行业所有的流行以及核心技术,以截图形式分享:

(亿级流量性能调优实战+一线大厂分布式实战+架构师筑基必备技能+设计思想开源框架解读+性能直线提升架构技术+高效存储让项目性能起飞+分布式扩展到微服务架构…实在是太多了)

其次分享一些技术知识,以截图形式分享一部分:

Tomcat架构解析:

算法训练+高分宝典:

Spring Cloud+Docker微服务实战:

最后分享一波面试资料:

切莫死记硬背,小心面试官直接让你出门右拐

1000道互联网Java面试题:

Java高级架构面试知识整理:

[外链图片转存中…(img-Z91qBmcy-1711463679640)]

最后分享一波面试资料:

切莫死记硬背,小心面试官直接让你出门右拐

1000道互联网Java面试题:

[外链图片转存中…(img-OSkCJYJj-1711463679640)]

Java高级架构面试知识整理:

[外链图片转存中…(img-ARjvxTgP-1711463679640)]

需要更多Java资料的小伙伴可以帮忙点赞+关注,点击传送门,即可免费领取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值