43 lines
1.4 KiB
Python
43 lines
1.4 KiB
Python
"""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,
|
|
)
|
|
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() |