58 lines
1.7 KiB
Python
58 lines
1.7 KiB
Python
import uuid
|
|
import logging
|
|
from django.conf import settings
|
|
from django.core.cache import cache
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# Redis客户端(延迟初始化)
|
|
_redis_client = None
|
|
|
|
def _get_redis_client():
|
|
global _redis_client
|
|
if _redis_client is None:
|
|
import redis
|
|
_redis_client = redis.Redis(
|
|
host=settings.REDIS_HOST,
|
|
port=settings.REDIS_PORT,
|
|
password=settings.REDIS_PASSWORD,
|
|
db=settings.REDIS_DB_CELERY,
|
|
decode_responses=True,
|
|
)
|
|
return _redis_client
|
|
|
|
|
|
def acquire_lock(lock_key, timeout=10):
|
|
"""获取分布式锁,返回锁标识符,失败返回None"""
|
|
client = _get_redis_client()
|
|
identifier = str(uuid.uuid4())
|
|
result = client.set(lock_key, identifier, nx=True, ex=timeout)
|
|
if result:
|
|
logger.debug(f"获取锁成功: {lock_key}, 标识: {identifier}")
|
|
return identifier
|
|
return None
|
|
|
|
|
|
def release_lock(lock_key, identifier):
|
|
"""释放分布式锁(仅当标识符匹配时才释放)"""
|
|
if identifier is None:
|
|
return False
|
|
client = _get_redis_client()
|
|
lua_script = """
|
|
if redis.call('get', KEYS[1]) == ARGV[1] then
|
|
return redis.call('del', KEYS[1])
|
|
else
|
|
return 0
|
|
end
|
|
"""
|
|
try:
|
|
result = client.eval(lua_script, 1, lock_key, identifier)
|
|
if result:
|
|
logger.debug(f"释放锁成功: {lock_key}")
|
|
else:
|
|
logger.warning(f"释放锁失败(标识不匹配或锁已过期): {lock_key}")
|
|
return bool(result)
|
|
except Exception as e:
|
|
logger.error(f"释放锁异常: {lock_key}, 错误: {e}")
|
|
return False
|