129 lines
3.9 KiB
Python
129 lines
3.9 KiB
Python
|
|
"""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)
|