Redis分布式锁

Redis分布式锁

文章目录

分布式锁是什么

锁我们可以理解为对某项资源使用权限的管理,通常使用锁来控制共享资源,比如一个进程内多个线程竞争一个资源的使用权限,解决方式其中就含有加锁。

而分布式锁,就是分布式场景下的锁,多台不同的机器上的进程去竞争同一个资源,需要加分布式锁。

分布式锁的特性

1.互斥性:只让一个竞争者持有锁

2.安全性:避免锁因为异常永久不被释放,使用过期时间兜底

3.对称性:同一个锁,必须由同一个竞争者加锁和释放锁

4.可靠性:一定程度的异常处理能力、容灾能力

Redis实现分布式锁

版本一:easy版本

  • setnx key value

利用Redis的setnx命令,将key设置为value,并且返回1;如果key存在,不会创建锁,返回0

流程:通过setnx加锁,加锁之后其他服务无法加锁,用完之后再通过delete解锁

版本二:支持过期时间

如果获取锁的服务挂了,那么锁就一直不被释放,后面的服务无法获取被锁着的资源,所以我们加一个超时时间来兜底。

使用Redis命令,给键加上过期时间即可。

set key value nx ex seconds

ex:增加了过期时间,seconds:设置的过期时间是多久

但是这又有一个新的问题,如果服务A的业务时间比较长,此时锁过期后,服务B获取了锁,然后服务A业务结束后释放了该锁(服务B业务此时还没结束)。

基于这个场景,我们又可以进一步优化分布式锁。

版本三:支持owner

分布式锁需要满足,谁申请的锁谁释放的原则。

同样的,使用Redis命令:set key 业务id nx ex second

在释放锁前,get锁进行判断即可。

另一个方法,也可以启动一个看门狗(go启动一个 gorountine),过期前去刷新过期时间即可。

版本四:lua

其实完整的流程是对的,但是现在还有一个问题:原子性

检查锁,再释放锁,这些操作不是原子的;可能锁获取时还是自己的,删除时已经是别人的了(比如你持有的锁过期了,被别人获取到了)。

使用Redis特性,整合原子操作的lua;Redis+Lua,可以专门解决原子性问题。

有了Lua,Redis才能真正的在分布式锁场景下被使用。

到了版本四,我们已经满足了分布式锁的前三个特性:对称性、安全性、互斥性。

可靠性如何保证

之前都是基于单机的,但是如果Redis挂了,那么就不能获取锁了。

解决方法:主从容灾和多级部署

主从容灾

给Redis配置从节点,当主节点挂掉,可以用从节点暂时顶包。

但是主从切换需要人工参与,提高了人力成本。但是Redis已经有了解决方案,使用哨兵模式,节点灵活自动切换,不需要人工参与。

尽管这种方法一定的程度上解决了单点的容灾问题,但是由于同步时延,Slave会损失部分数据,分布式锁可能会失效,可能会导致短暂的多个机器获取到执行权限。

所以有一个更可靠的办法。

多机部署

对一致性要求更高可以使用多机部署,使用Redis的RedLock。

大概的思路是:通常是N个机器(N一般为奇数),达到一半以上同意加锁才算加锁成功。

加锁流程一般为(以N=5为例):

1.向5个Redis申请加锁

2.超过一半(3个)同意,就可以获取到锁;反之,向每个Redis发送解锁命令

3.由于向5个Redis发送请求,会有一定的时耗,所以锁持有时间应该需要减去请求时间。如果剩余时间为0,那就是获取锁失败

4.使用完锁后,向5个Redis发送解锁请求

这种方案是一般比较成熟的方法了,最后我们再给每个Redis配上哨兵模式就增强了可靠性。

但是这就一定能保证可靠性吗?

不足分析

NPC问题

1.网络时延(Network Delay):RedLock的锁剩余持有时间,需要减去请求时间,可以一定程度的解决网络延迟问题。

2.进程暂停(Process Pause):如果进程获取锁后发生了GC,但是锁已经过期了,那么就会有两个进程获取到同一个锁。

3.时钟漂移(Clock Drift):如果服务A通过RedLock方案获取了锁,但是机器都发送了时钟漂移,锁瞬间过期了,那么又会有两个进程获取到同一个锁。

相关推荐
zpjing~.~32 分钟前
Mongo 分页判断是否有下一页
数据库
2401_8576009533 分钟前
技术与教育的融合:构建现代成绩管理系统
数据库·oracle
秋恬意1 小时前
Mybatis能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别
java·数据库·mybatis
潇湘秦1 小时前
一文了解Oracle数据库如何连接(1)
数据库·oracle
雅冰石1 小时前
oracle怎样使用logmnr恢复误删除的数据
数据库·oracle
web前端神器1 小时前
mongodb给不同的库设置不同的密码进行连接
数据库·mongodb
从以前1 小时前
Berlandesk 注册系统算法实现与解析
数据库·oracle
Muko_0x7d21 小时前
Mongodb
数据库·mongodb
Ren_xixi1 小时前
redis和mysql的区别
数据库·redis·mysql
攻心的子乐2 小时前
Kafka可视化工具 Offset Explorer (以前叫Kafka Tool)
分布式·kafka