封装redisLock 分布式锁
时间: 2023-10-16 12:09:41 浏览: 41
好的,下面是一个简单的Redis分布式锁的封装示例:
```python
import redis
import time
class RedisLock:
def __init__(self, redis_client, key, expire=60, retry_interval=0.1, retry_times=3):
self.redis_client = redis_client
self.key = key
self.expire = expire
self.retry_interval = retry_interval
self.retry_times = retry_times
self.value = None
def __enter__(self):
for i in range(self.retry_times):
value = str(time.time() + self.expire + 1)
if self.redis_client.set(self.key, value, nx=True, ex=self.expire):
self.value = value
return self
time.sleep(self.retry_interval)
raise Exception("Failed to acquire lock after retries")
def __exit__(self, exc_type, exc_val, exc_tb):
if self.value is not None:
self.redis_client.eval(
"if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end",
1, self.key, self.value)
```
使用方法:
```python
redis_client = redis.Redis(host='localhost', port=6379, db=0)
key = 'my_lock'
with RedisLock(redis_client, key):
# 这里是需要加锁保护的代码块
print("Do something with lock")
# 锁已经自动释放
```
该示例中,`RedisLock`类实现了`__enter__`和`__exit__`方法,使其可以使用Python的`with`语句进行锁的自动管理。在`__enter__`方法中,通过Redis的`set`命令尝试获取锁,如果获取失败,则等待一段时间后重新尝试,最多尝试`retry_times`次。如果在规定的重试次数内仍无法获取到锁,则抛出异常。在获取到锁后,将锁的超时时间设置为`expire`秒,并将锁的值保存在实例中。在`__exit__`方法中,通过调用Redis的`eval`命令,判断锁的值是否为当前实例的值,如果是,则释放锁。
需要注意的是,Redis分布式锁并不是完美的解决方案,仍然存在一些问题,例如死锁、误解锁等。因此,在实际使用时,需要根据具体场景进行设计和优化。