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, # 长连接保活,防代理/防火墙断连
|
||
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() |