在redis文档中,我发现可以通过SETNX实现原始锁:
http://redis.io/commands/setnx
C4发送SETNX lock.foo以获取锁定崩溃的客户端C3仍然保留它,因此Redis将回复0到C4 . C4发送GET lock.foo以检查锁是否过期 . 如果不是,它会睡一段时间并从头开始重试 . 相反,如果锁定已到期,因为lock.foo上的Unix时间早于当前的Unix时间,C4会尝试执行:GETSET lock.foo由于GETSET语义,C4可以检查存储在key中的旧值是否仍然存在过期的时间戳 . 如果是,则获取锁定 . 如果另一个客户端(例如C5)比C4快并且通过GETSET操作获得锁定,则C4 GETSET操作将返回未过期的时间戳 . C4将从第一步开始重新启动 . 请注意,即使C4将来设置密钥几秒钟,这也不是问题 .
但是,正如一些用户所评论的那样,使用UNIX时间戳作为过期时间需要客户端和服务器的时间完全同步 . 在Redis中创建全局/分布式锁是否有更好的选择?
6 回答
使用
SET
而不是SETNX
.SET
接受过期时间的参数,以秒和毫秒为单位,而不是UNIX时间戳值 .仅基于历史原因记录旧的基于SETNX的模式 .
来自
SETNX
description:使用 redis >= 2.6 LUA脚本解决方案会很棒 . Lua脚本总是原子地执行所以:
另一种解决方案基于
SET
命令的新选项使用 redis < 2.6 可以使用带有multi的模式:
点击链接
解释锁定的好项目
http://redis.io/topics/distlock
https://github.com/mrniko/redisson
SET的新参数足以设置锁定,但这些仅适用于Redis> = v2.6.12,您还需要考虑锁定将如何取消设置和到期等 .
我在工程博客上发了一篇关于distributed locks using Redis的帖子 . 它涵盖了如何可靠地设置和释放锁定的脚本,以及防止验证和死锁 . 我还包括一个用Node.js编写的模块,你可以用它直接开箱即用 .
我掏出了一个很酷的宝石提到的
SET EX NX
解决方案 - simple_redis_lock代码很简单,看起来像这样:
关于Redis锁的好文章:“How to do distributed locking” .
Taooka修复所有描述的问题 . 它隔离了损坏的客户端,在破碎的客户端访问不断变化的数据之前,没有人可以锁定 .