利用Redis的SetNx一步步实现分布式锁并改进
import redis
import time
import uuid
class RedisLock:
def __init__(self, host='localhost', port=6379, db=0):
self.redis_conn = redis.Redis(host=host, port=port, db=db)
def acquire_lock(self, lock_name, acquire_timeout=10, lock_timeout=10):
identifier = str(uuid.uuid4())
end = time.time() + acquire_timeout
while time.time() < end:
if self.redis_conn.setnx(lock_name, identifier):
self.redis_conn.expire(lock_name, lock_timeout)
return identifier
time.sleep(0.001)
return False
def release_lock(self, lock_name, identifier):
pipe = self.redis_conn.pipeline(True)
while True:
try:
pipe.watch(lock_name)
if pipe.get(lock_name) == identifier:
pipe.multi()
pipe.delete(lock_name)
pipe.execute()
return True
pipe.unwatch()
break
except redis.exceptions.WatchError:
pass
return False
# 使用示例
redis_lock = RedisLock()
lock_name = 'my_lock'
lock_timeout = 10
identifier = redis_lock.acquire_lock(lock_name, lock_timeout)
if identifier:
print(f'Lock acquired with identifier: {identifier}')
# 执行互斥区的代码
# ...
if redis_lock.release_lock(lock_name, identifier):
print('Lock released successfully.')
else:
print('Failed to release lock.')
else:
print('Failed to acquire lock.')
这段代码实现了基本的Redis分布式锁功能,并在原有基础上做了一些改进:
- 使用UUID作为唯一标识,避免了原始版本中的键值冲突问题。
- 在获取锁的方法中增加了获取锁的最长等待时间参数
acquire_timeout
,避免了无限等待的问题。 - 在释放锁的方法中使用了Redis的事务机制,以确保在释放锁时的安全性。
评论已关闭