关于 Python redis 的 Lock 有两个疑问

2018-08-24 19:15:48 +08:00
 windardyang
set name token nx ex timeout

python 中的 redis Lock 实际上就是以上函数来实现锁。但是原生的 Lock 是先 setnx 在 expire,LuaLock 是使用 lua 脚本先 setnx 在 expire,所以有两个问题。

  1. 为什么将两个步骤合二为一呢?是因为 setnx key valueset key value nx 高级一些么?
  2. 使用要使用 lua 脚本,就比原生执行高级一些么?

函数在 redis/lock.py

原生的 Lock

    def do_acquire(self, token):
        if self.redis.setnx(self.name, token):
            if self.timeout:
                # convert to milliseconds
                timeout = int(self.timeout * 1000)
                self.redis.pexpire(self.name, timeout)
            return True
        return False

使用 LuaLock

    # KEYS[1] - lock name
    # ARGV[1] - token
    # ARGV[2] - timeout in milliseconds
    # return 1 if lock was acquired, otherwise 0
    LUA_ACQUIRE_SCRIPT = """
        if redis.call('setnx', KEYS[1], ARGV[1]) == 1 then
            if ARGV[2] ~= '' then
                redis.call('pexpire', KEYS[1], ARGV[2])
            end
            return 1
        end
        return 0
    """
5855 次点击
所在节点    Redis
5 条回复
seven2016
2018-08-24 20:50:47 +08:00
刚好在学习 redis

- set key value nx 是分布式锁的奥义所在,两个步骤合成一个原子操作不会有并发问题
- Redis 服务器内部可以直接执行 Lua 代码,恩,有这样一句话,学好 redis,必会 Lua。(逃
scriptB0y
2018-08-24 21:15:55 +08:00
你所说的 “原生的 lock ” “ python 中的 redis lock ” “ lualock ” 分别指什么? 为什么“原生的 lock ”是一段 Python 代码?
windardyang
2018-08-24 23:39:58 +08:00
@scriptB0y #2 指的是 `redis/lock.py` 代码里的两个 Lock 类,只截取了获得锁的部分代码,完整的类请看源代码。
windardyang
2018-08-24 23:41:15 +08:00
@seven2016 #1 我的意思也是 `set key value nx` 较现有方式好一些,可是现在它并不是这样实现。
helloSpringBoot
2018-08-25 09:36:35 +08:00
`set name token nx ex timeout ` 是客户端用的,跟服务端实现不一样很正常。
假设客户端实现也是先加锁,在设置超时:加完锁,客户端挂掉了怎么办? 这样锁不就释放不了了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/482990

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX