"""Redis 分布式锁(SET NX EX)。""" import secrets import time import redis.asyncio as aioredis from app.config import settings class Lock: def __init__(self, redis: aioredis.Redis, name: str, timeout: int = settings.lock_timeout): self.redis = redis self.name = name self.timeout = timeout self._token = secrets.token_hex(8) async def acquire(self) -> bool: ok = await self.redis.set(self.name, self._token, nx=True, ex=self.timeout) return bool(ok) async def release(self) -> None: # 仅在持有相同 token 时释放,避免误删他人锁 val = await self.redis.get(self.name) if val == self._token: await self.redis.delete(self.name) async def guarded(self, fn): """上下文封装:获取锁执行,释放锁。""" if not await self.acquire(): return False try: await fn() return True finally: await self.release()