"""Redis 会话:内置连接池的 asyncio 客户端单例。""" import redis.asyncio as aioredis from redis.backoff import FullJitterBackoff from redis.retry import Retry from config.settings import settings _client: aioredis.Redis | None = None def client() -> aioredis.Redis: global _client if _client is None: _client = aioredis.Redis( host=settings.redis.host, port=settings.redis.port, db=settings.redis.db, password=settings.redis.password, socket_connect_timeout=settings.redis.socket_connect_timeout, socket_timeout=settings.redis.socket_timeout, socket_keepalive=True, # 长连接保活,防代理/防火墙断连 retry_on_timeout=True, # 读超时自动重试,吸收瞬时抖动 health_check_interval=settings.redis.health_check_interval, retry=Retry(FullJitterBackoff(base=1, cap=10), retries=3), max_connections=settings.redis.max_connections, decode_responses=True, protocol=2, # redis-py 8 默认 RESP3(HELLO 3),Redis < 6.0 不支持 ) return _client async def init_db() -> None: await client() # 构造是同步懒加载,启动时只需确保单例被建出 async def dispose() -> None: global _client if _client is not None: await _client.aclose() _client = None async def check_health() -> None: assert await client().ping()