windardyang
V2EX  ›  Redis

关于 Python redis 的 Lock 有两个疑问

By windardyang at 2018 年 8 月 24 日 · 7198 次点击
set name token nx ex timeout

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

  1. 为什么将两个步骤合二为一呢?是因为 setnx key value 比 set 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
    """
5 条回复  •  2018-08-25 09:36:35 +08:00
seven2016
   1
seven2016  
   2018 年 8 月 24 日
刚好在学习 redis

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