|
@@ -3,6 +3,7 @@ import os |
|
|
from config import conf |
|
|
from config import conf |
|
|
import uuid |
|
|
import uuid |
|
|
import time |
|
|
import time |
|
|
|
|
|
import threading |
|
|
# 定义全局 redis_helper |
|
|
# 定义全局 redis_helper |
|
|
redis_helper = None |
|
|
redis_helper = None |
|
|
|
|
|
|
|
@@ -41,74 +42,63 @@ class RedisHelper: |
|
|
"""更新哈希表中的某个字段""" |
|
|
"""更新哈希表中的某个字段""" |
|
|
self.client.hset(hash_key, field, value) |
|
|
self.client.hset(hash_key, field, value) |
|
|
|
|
|
|
|
|
def acquire_lock(self, lock_key, expire_time=60, timeout=None): |
|
|
|
|
|
|
|
|
# def acquire_lock(self, lock_name, timeout=60): |
|
|
|
|
|
# """ |
|
|
|
|
|
# 尝试获取分布式锁,成功返回 True,失败返回 False |
|
|
|
|
|
# :param lock_name: 锁的名称 |
|
|
|
|
|
# :param timeout: 锁的超时时间(秒) |
|
|
|
|
|
# :return: bool |
|
|
|
|
|
# """ |
|
|
|
|
|
# identifier = str(time.time()) # 使用时间戳作为唯一标识 |
|
|
|
|
|
# end_time = time.time() + timeout |
|
|
|
|
|
# while time.time() < end_time: |
|
|
|
|
|
# if self.client.set(lock_name, identifier, nx=True, ex=timeout): |
|
|
|
|
|
# self.lock_renewal_thread = threading.Thread(target=self.renew_lock, args=(lock_name, identifier, timeout)) |
|
|
|
|
|
# self.lock_renewal_thread.start() |
|
|
|
|
|
# return True |
|
|
|
|
|
# time.sleep(0.1) |
|
|
|
|
|
# return False |
|
|
|
|
|
|
|
|
|
|
|
def acquire_lock(self, lock_name, timeout=60): |
|
|
""" |
|
|
""" |
|
|
获取分布式锁。 |
|
|
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
|
|
lock_key: 锁的键名。 |
|
|
|
|
|
expire_time: 锁的有效时间(秒)。 |
|
|
|
|
|
timeout: 最大等待时间(秒),默认为None表示无限等待。 |
|
|
|
|
|
|
|
|
|
|
|
Returns: |
|
|
|
|
|
成功获取锁返回True,否则返回False。 |
|
|
|
|
|
|
|
|
尝试获取分布式锁,成功返回 True,失败返回 False |
|
|
|
|
|
:param lock_name: 锁的名称 |
|
|
|
|
|
:param timeout: 锁的超时时间(秒) |
|
|
|
|
|
:return: bool |
|
|
""" |
|
|
""" |
|
|
identifier = str(uuid.uuid4()) |
|
|
|
|
|
|
|
|
|
|
|
while True: |
|
|
|
|
|
# 尝试获取锁 |
|
|
|
|
|
if self.client.setnx(lock_key, identifier): |
|
|
|
|
|
self.client.expire(lock_key, expire_time) |
|
|
|
|
|
return True |
|
|
|
|
|
|
|
|
|
|
|
# 检查锁是否存在且未过期 |
|
|
|
|
|
current_value = self.client.get(lock_key) |
|
|
|
|
|
if not current_value: |
|
|
|
|
|
continue # 锁不存在,继续尝试获取 |
|
|
|
|
|
|
|
|
|
|
|
# 检查锁是否已过期 |
|
|
|
|
|
ttl = self.client.ttl(lock_key) |
|
|
|
|
|
if ttl == -2: # 锁已过期 |
|
|
|
|
|
continue |
|
|
|
|
|
|
|
|
|
|
|
# 如果超时时间设置且已经超出,则返回False |
|
|
|
|
|
if timeout is not None: |
|
|
|
|
|
start_time = time.time() |
|
|
|
|
|
while (time.time() - start_time) < timeout: |
|
|
|
|
|
time.sleep(0.1) |
|
|
|
|
|
return self.acquire_lock(lock_key, expire_time, timeout) |
|
|
|
|
|
else: |
|
|
|
|
|
# 超时,放弃获取锁 |
|
|
|
|
|
return False |
|
|
|
|
|
|
|
|
|
|
|
# 等待一段时间后重试 |
|
|
|
|
|
time.sleep(0.1) |
|
|
|
|
|
|
|
|
identifier = str(time.time()) # 使用时间戳作为唯一标识 |
|
|
|
|
|
if self.client.set(lock_name, identifier, nx=True, ex=timeout): |
|
|
|
|
|
self.lock_renewal_thread = threading.Thread(target=self.renew_lock, args=(lock_name, identifier, timeout)) |
|
|
|
|
|
self.lock_renewal_thread.start() |
|
|
|
|
|
return True |
|
|
|
|
|
return False |
|
|
|
|
|
|
|
|
def release_lock(self, lock_key): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def renew_lock(self, lock_name, identifier, timeout): |
|
|
""" |
|
|
""" |
|
|
释放分布式锁。 |
|
|
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
|
|
lock_key: 锁的键名。 |
|
|
|
|
|
|
|
|
|
|
|
Returns: |
|
|
|
|
|
成功释放返回True,否则返回False。 |
|
|
|
|
|
|
|
|
锁的自动续期 |
|
|
|
|
|
:param lock_name: 锁的名称 |
|
|
|
|
|
:param identifier: 锁的唯一标识 |
|
|
|
|
|
:param timeout: 锁的超时时间(秒) |
|
|
""" |
|
|
""" |
|
|
script = """ |
|
|
|
|
|
if redis.call("get", KEYS[1]) == ARGV[1] then |
|
|
|
|
|
return redis.call("del", KEYS[1]) |
|
|
|
|
|
else |
|
|
|
|
|
return 0 |
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
while True: |
|
|
|
|
|
time.sleep(timeout / 2) |
|
|
|
|
|
if self.client.get(lock_name) == identifier.encode(): |
|
|
|
|
|
self.client.expire(lock_name, timeout) |
|
|
|
|
|
else: |
|
|
|
|
|
break |
|
|
|
|
|
|
|
|
|
|
|
def release_lock(self, lock_name, identifier): |
|
|
""" |
|
|
""" |
|
|
current_value = self.client.get(lock_key) |
|
|
|
|
|
if not current_value: |
|
|
|
|
|
return False |
|
|
|
|
|
|
|
|
|
|
|
identifier = str(uuid.uuid4()) # 这里应替换为获取锁时使用的标识符 |
|
|
|
|
|
result = self.client.eval(script, [lock_key], [identifier]) |
|
|
|
|
|
return result == 1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
释放分布式锁 |
|
|
|
|
|
:param lock_name: 锁的名称 |
|
|
|
|
|
:param identifier: 锁的唯一标识 |
|
|
|
|
|
""" |
|
|
|
|
|
if self.client.get(lock_name) == identifier.encode(): |
|
|
|
|
|
self.client.delete(lock_name) |
|
|
|
|
|
if self.lock_renewal_thread: |
|
|
|
|
|
self.lock_renewal_thread.join() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def start(): |
|
|
def start(): |
|
|
global redis_helper |
|
|
global redis_helper |
|
|