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方案获取了锁,但是机器都发送了时钟漂移,锁瞬间过期了,那么又会有两个进程获取到同一个锁。

相关推荐
Acrel_WPP2 分钟前
分布式光伏智慧平台建设现场 系统集成商如何盈利
分布式
大山同学5 分钟前
DPGO:异步和并行分布式位姿图优化 2020 RA-L best paper
人工智能·分布式·语言模型·去中心化·slam·感知定位
哭哭啼6 分钟前
Redis环境部署(主从模式、哨兵模式、集群模式)
数据库·redis·缓存
咕噜Yuki060919 分钟前
OCP证书如何下载?
数据库·ocp·证书查询
冬瓜3121 小时前
linux-c 使用c语言操作sqlite3数据库-1
数据库·sqlite
夜色呦1 小时前
现代电商解决方案:Spring Boot框架实践
数据库·spring boot·后端
Lyqfor1 小时前
云原生学习
java·分布式·学习·阿里云·云原生
WangYaolove13141 小时前
请解释Python中的装饰器是什么?如何使用它们?
linux·数据库·python
明志致远淡泊宁静1 小时前
记录一次服务器redis被入侵
运维·服务器·redis
我是黄大仙2 小时前
利用飞书多维表格自动发布版本
运维·服务器·数据库·飞书