今天来说说高并发服务编程中的redis分布式锁。
这里罗列出3种redis实现的分布式锁,并分别对比说明各自特点。
开始之前,记得点赞收藏加关注哦 ,需要下载PDF版本和获取更多知识点、面试题的朋友可以点一点下方链接免费领取
链接:点这里!!! 暗号:CSDN
Redis单实例分布式锁
实现一: SETNX实现的分布式锁
setnx用法参考redis官方文档
语法
SETNX key value
将key设置值为value,如果key不存在,这种情况下等同SET命令。 当key存在时,什么也不做。SETNX是”SET if Not eXists”的简写。
返回值:
- 1 设置key成功
- 0 设置key失败
加锁步骤
SETNX lock.foo <current Unix time + lock timeout + 1>
- 如果客户端获得锁,SETNX返回1,加锁成功。
- 如果SETNX返回0,那么该键已经被其他的客户端锁定。
接上一步,SETNX返回0加锁失败,此时,调用GET lock.foo获取时间戳检查该锁是否已经过期:
- 如果没有过期,则休眠一会重试。
- 如果已经过期,则可以获取该锁。具体的:调用GETSET lock.foo <current Unix timestamp + lock timeout + 1>基于当前时间设置新的过期时间。
注意: 这里设置的时候因为在SETNX与GETSET之间有个窗口期,在这期间锁可能已被其他客户端抢去,所以这里需要判断GETSET的返回值,他的返回值是SET之前旧的时间戳:
- 若旧的时间戳已过期,则表示加锁成功。
- 若旧的时间戳还未过期(说明被其他客户端抢去并设置了时间戳),代表加锁失败,需要等待重试。
解锁步骤
解锁相对简单,只需GET lock.foo时间戳,判断是否过期,过期就调用删除DEL lock.foo
实现二:SET实现的分布式锁
set用法参考官方文档
语法
SET key value [EX seconds|PX milliseconds] [NX|XX]
将键key设定为指定的“字符串”值。如果 key 已经保存了一个值,那么这个操作会直接覆盖原来的值,并且忽略原始类型。当set命令执行成功之后,之前设置的过期时间都将失效。
从2.6.12版本开始,redis为SET命令增加了一系列选项:
- EXseconds – Set the specified expire time, in seconds.
- PXmilliseconds – Set the specified expire time, in milliseconds.
- NX – Only set the key if it does not already exist.
- XX – Only set the key if it already exist.
- EXs