"""Redis 服务""" import json from typing import Any, Optional, Union import redis.asyncio as redis from redis.asyncio import Redis from app.config import settings class RedisService: """Redis 服务类""" _client: Optional[Redis] = None @classmethod async def init(cls) -> None: """初始化 Redis 连接""" cls._client = redis.Redis( host=settings.REDIS_HOST, port=settings.REDIS_PORT, password=settings.REDIS_PASSWORD or None, db=settings.REDIS_DB, decode_responses=True ) @classmethod async def close(cls) -> None: """关闭 Redis 连接""" if cls._client: await cls._client.close() cls._client = None @classmethod def get_client(cls) -> Redis: """获取 Redis 客户端""" if not cls._client: raise RuntimeError("Redis 未初始化,请先调用 init()") return cls._client # ==================== String 操作 ==================== @classmethod async def get(cls, key: str) -> Optional[str]: """获取值""" return await cls.get_client().get(key) @classmethod async def set(cls, key: str, value: Union[str, int, float], expire: Optional[int] = None) -> bool: """设置值""" return await cls.get_client().set(key, value, ex=expire) @classmethod async def delete(cls, *keys: str) -> int: """删除键""" return await cls.get_client().delete(*keys) @classmethod async def exists(cls, key: str) -> bool: """判断键是否存在""" return await cls.get_client().exists(key) > 0 @classmethod async def expire(cls, key: str, seconds: int) -> bool: """设置过期时间""" return await cls.get_client().expire(key, seconds) @classmethod async def ttl(cls, key: str) -> int: """获取剩余过期时间""" return await cls.get_client().ttl(key) # ==================== JSON 操作 ==================== @classmethod async def get_json(cls, key: str) -> Optional[Any]: """获取 JSON 值""" value = await cls.get(key) return json.loads(value) if value else None @classmethod async def set_json(cls, key: str, value: Any, expire: Optional[int] = None) -> bool: """设置 JSON 值""" return await cls.set(key, json.dumps(value, ensure_ascii=False), expire) # ==================== Hash 操作 ==================== @classmethod async def hget(cls, name: str, key: str) -> Optional[str]: """获取 Hash 字段值""" return await cls.get_client().hget(name, key) @classmethod async def hset(cls, name: str, key: str, value: str) -> int: """设置 Hash 字段值""" return await cls.get_client().hset(name, key, value) @classmethod async def hgetall(cls, name: str) -> dict: """获取 Hash 所有字段""" return await cls.get_client().hgetall(name) @classmethod async def hdel(cls, name: str, *keys: str) -> int: """删除 Hash 字段""" return await cls.get_client().hdel(name, *keys) # ==================== List 操作 ==================== @classmethod async def lpush(cls, key: str, *values: str) -> int: """左侧插入列表""" return await cls.get_client().lpush(key, *values) @classmethod async def rpush(cls, key: str, *values: str) -> int: """右侧插入列表""" return await cls.get_client().rpush(key, *values) @classmethod async def lrange(cls, key: str, start: int = 0, end: int = -1) -> list: """获取列表范围""" return await cls.get_client().lrange(key, start, end) @classmethod async def llen(cls, key: str) -> int: """获取列表长度""" return await cls.get_client().llen(key)