答案:
Redis可以通过setnx(SET if Not eXists)命令和expire命令实现分布式锁。
使用setnx命令尝试获取锁,如果返回值为1,则表示获取到了锁。
如果获取到了锁,就需要设置一个过期时间,以免锁被长时间占用。
如果获取锁失败,则需要等待一段时间后重新尝试获取锁,可以使用睡眠函数进行等待。
释放锁时需要使用del命令将锁删除。
以下是一个示例代码:
def acquire_lock(conn, lockname, acquire_timeout=10, lock_timeout=10):
identifier = str(uuid.uuid4())
lock_key = 'lock:' + lockname
end = time.time() + acquire_timeout
while time.time() < end:
if conn.setnx(lock_key, identifier):
conn.expire(lock_key, lock_timeout)
return identifier
elif not conn.ttl(lock_key):
conn.expire(lock_key, lock_timeout)
time.sleep(0.001)
return False
def release_lock(conn, lockname, identifier):
lock_key = 'lock:' + lockname
while True:
conn.watch(lock_key)
if conn.get(lock_key) == identifier:
conn.multi()
conn.delete(lock_key)
if conn.execute():
return True
conn.unwatch()
break
return False
注意点:
为了避免误删其他线程获取的锁,释放锁时需要检查锁的值是否为自己的标识符。
在设置锁的过期时间时,需要保证锁的过期时间大于锁的执行时间,以避免锁被意外释放。
为了避免死锁,需要设置获取锁的超时时间,超时后自动放弃获取锁。