首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Redis创建分布式锁?

如何使用Redis创建分布式锁?
EN

Stack Overflow用户
提问于 2013-12-23 02:01:48
回答 4查看 28.1K关注 0票数 16

在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可以检查存储在键下的旧值是否仍然是过期的时间戳。如果是的话,锁是被取下来的。
  • 如果另一个客户机(例如,C5 )比C4快,并且使用GETSET操作获得锁,则C4 GETSET操作将返回一个未过期的时间戳。C4将从第一步开始重新启动。请注意,即使C4在未来的几秒钟内设置了键,这也不是一个问题。

然而,正如一些用户所评论的,使用UNIX时间戳作为过期需要客户端和服务器的时间完全同步。在Redis中是否有更好的方法来创建全局/分布式锁?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-12-23 09:55:59

使用SET而不是SETNXSET接受以秒和毫秒为单位的过期时间参数,而不是UNIX时间戳值。

基于SETNX的旧模式仅因历史原因而记录在案。

来自SETNX 描述

注意:从Redis 2.6.12开始,可以使用SET命令创建一个简单得多的锁定原语来获取锁,并创建一个简单的Lua脚本来释放锁。模式记录在SET命令页中。

票数 15
EN

Stack Overflow用户

发布于 2013-12-23 10:09:59

使用redis >= 2.6,LUA脚本解决方案将是很棒的。Lua脚本总是以原子方式执行,因此:

代码语言:javascript
复制
--lockscript, parameters: lock_key, lock_timeout
local lock = redis.call('get', KEYS[1])
if not lock then    
    return redis.call('setex', KEYS[1], ARGV[1], "locked");
end
return false

基于SET命令新选项的另一种解决方案

代码语言:javascript
复制
SET lock_key "locked" EX lock_timeout NX 

使用redis < 2.6,可以使用多个模式:

代码语言:javascript
复制
MULTI
SETNX tmp_unique_lock some_value
EXPIRE tmp_unique_lock
RENAMENX tmp_unique_lock real_lock
EXEC
票数 7
EN

Stack Overflow用户

发布于 2014-03-24 12:35:00

设置的新参数足以设置锁,但这些参数仅适用于Redis >= v2.6.12,您还需要考虑锁将如何解除和过期等等。

我在我们的工程博客上写了一篇关于使用Redis的分布式锁的文章。它涵盖了如何可靠地设置和释放锁的脚本,以及验证和死锁预防。我还包括一个用Node.js编写的模块,您可以直接使用它进行锁定。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20736102

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档