2026-01-12 07:49:18 +08:00
|
|
|
|
import asyncio
|
|
|
|
|
|
import logging
|
2026-01-20 08:09:13 +08:00
|
|
|
|
import os
|
2026-01-12 07:49:18 +08:00
|
|
|
|
import uuid
|
|
|
|
|
|
import json
|
|
|
|
|
|
|
|
|
|
|
|
import redis
|
2026-01-20 08:09:13 +08:00
|
|
|
|
from Config.Config import REDIS_HOST, REDIS_PORT, REDIS_DB, REDIS_PASSWORD, REDIS_DECODE_RESPONSES
|
2026-01-12 07:49:18 +08:00
|
|
|
|
# 创建logger实例
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
class RedisKit:
|
|
|
|
|
|
"""
|
|
|
|
|
|
异步Redis工具类,提供所有Redis操作的异步实现
|
|
|
|
|
|
单例模式确保全局只有一个Redis连接池
|
|
|
|
|
|
"""
|
|
|
|
|
|
_instance = None
|
|
|
|
|
|
_lock = asyncio.Lock()
|
|
|
|
|
|
_redis_pool = None
|
|
|
|
|
|
|
|
|
|
|
|
def __new__(cls):
|
|
|
|
|
|
if cls._instance is None:
|
|
|
|
|
|
cls._instance = super().__new__(cls)
|
|
|
|
|
|
return cls._instance
|
|
|
|
|
|
|
2026-01-20 08:09:13 +08:00
|
|
|
|
async def _ensure_pool(self):
|
2026-01-12 07:49:18 +08:00
|
|
|
|
"""
|
|
|
|
|
|
确保Redis连接池已创建
|
|
|
|
|
|
"""
|
2026-01-20 08:09:13 +08:00
|
|
|
|
if RedisKit._redis_pool is None:
|
|
|
|
|
|
async with RedisKit._lock:
|
|
|
|
|
|
if RedisKit._redis_pool is None:
|
2026-01-12 07:49:18 +08:00
|
|
|
|
try:
|
|
|
|
|
|
# 创建同步Redis连接池
|
|
|
|
|
|
sync_pool = redis.ConnectionPool(
|
|
|
|
|
|
host=REDIS_HOST,
|
|
|
|
|
|
port=REDIS_PORT,
|
|
|
|
|
|
db=REDIS_DB,
|
|
|
|
|
|
password=REDIS_PASSWORD,
|
2026-01-20 08:09:13 +08:00
|
|
|
|
decode_responses=REDIS_DECODE_RESPONSES
|
2026-01-12 07:49:18 +08:00
|
|
|
|
)
|
|
|
|
|
|
# 创建Redis连接实例
|
2026-01-20 08:09:13 +08:00
|
|
|
|
RedisKit._redis_pool = redis.Redis(
|
2026-01-12 07:49:18 +08:00
|
|
|
|
connection_pool=sync_pool,
|
|
|
|
|
|
encoding='utf-8',
|
|
|
|
|
|
decode_responses=REDIS_DECODE_RESPONSES
|
|
|
|
|
|
)
|
|
|
|
|
|
# 测试连接
|
2026-01-20 08:09:13 +08:00
|
|
|
|
await asyncio.to_thread(RedisKit._redis_pool.ping)
|
2026-01-12 07:49:18 +08:00
|
|
|
|
logger.info("Redis连接池创建成功")
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"Redis连接池创建失败: {e}")
|
|
|
|
|
|
raise
|
|
|
|
|
|
|
2026-01-20 08:09:13 +08:00
|
|
|
|
async def get_connection(self):
|
2026-01-12 07:49:18 +08:00
|
|
|
|
"""
|
|
|
|
|
|
获取Redis连接实例
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
redis.Redis: Redis连接实例
|
|
|
|
|
|
"""
|
2026-01-20 08:09:13 +08:00
|
|
|
|
await self._ensure_pool()
|
|
|
|
|
|
return RedisKit._redis_pool
|
2026-01-12 07:49:18 +08:00
|
|
|
|
|
|
|
|
|
|
async def get_data(self, key):
|
|
|
|
|
|
"""
|
|
|
|
|
|
异步从Redis中获取数据
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
key (str): Redis键名
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
any: Redis中存储的值,如果键不存在则返回None
|
|
|
|
|
|
"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
await self._ensure_pool()
|
|
|
|
|
|
return await asyncio.to_thread(RedisKit._redis_pool.get, key)
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"从Redis获取数据失败(key={key}): {e}")
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
async def exists(self, key):
|
|
|
|
|
|
"""
|
|
|
|
|
|
异步检查Redis键是否存在
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
key (str): Redis键名
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
bool: 键存在返回True,不存在或失败返回False
|
|
|
|
|
|
"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
await self._ensure_pool()
|
|
|
|
|
|
result = await asyncio.to_thread(RedisKit._redis_pool.exists, key)
|
|
|
|
|
|
return bool(result)
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"检查Redis键是否存在失败(key={key}): {e}")
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
async def set_data(self, key, value, expire=None):
|
2026-01-21 08:41:47 +08:00
|
|
|
|
"""
|
|
|
|
|
|
异步保存数据到Redis
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
key (str): Redis键名
|
|
|
|
|
|
value (any): 要保存的值
|
|
|
|
|
|
expire (int, optional): 过期时间(秒)
|
|
|
|
|
|
"""
|
2026-01-12 07:49:18 +08:00
|
|
|
|
try:
|
|
|
|
|
|
await self._ensure_pool()
|
|
|
|
|
|
if expire:
|
2026-01-20 08:09:13 +08:00
|
|
|
|
await asyncio.to_thread(RedisKit._redis_pool.set, key, value, ex=expire)
|
2026-01-12 07:49:18 +08:00
|
|
|
|
else:
|
2026-01-20 08:09:13 +08:00
|
|
|
|
await asyncio.to_thread(RedisKit._redis_pool.set, key, value)
|
2026-01-12 07:49:18 +08:00
|
|
|
|
return True
|
|
|
|
|
|
except Exception as e:
|
2026-01-20 08:09:13 +08:00
|
|
|
|
logger.error(f"保存数据到Redis失败(key={key}): {e}")
|
2026-01-12 07:49:18 +08:00
|
|
|
|
return False
|
2026-01-21 08:41:47 +08:00
|
|
|
|
|
|
|
|
|
|
async def close(self):
|
|
|
|
|
|
"""
|
|
|
|
|
|
关闭Redis连接池
|
|
|
|
|
|
"""
|
|
|
|
|
|
if RedisKit._redis_pool is not None:
|
|
|
|
|
|
try:
|
|
|
|
|
|
# redis-py 4.x+ supports close()
|
|
|
|
|
|
await asyncio.to_thread(RedisKit._redis_pool.close)
|
|
|
|
|
|
RedisKit._redis_pool = None
|
|
|
|
|
|
logger.info("Redis连接池已关闭")
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"关闭Redis连接池失败: {e}")
|
|
|
|
|
|
|
|
|
|
|
|
async def delete_data(self, key):
|
|
|
|
|
|
"""
|
|
|
|
|
|
异步删除Redis中的数据
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
key (str): Redis键名
|
|
|
|
|
|
"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
await self._ensure_pool()
|
|
|
|
|
|
await asyncio.to_thread(RedisKit._redis_pool.delete, key)
|
|
|
|
|
|
return True
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"从Redis删除数据失败(key={key}): {e}")
|
|
|
|
|
|
return False
|
2026-01-20 08:09:13 +08:00
|
|
|
|
|
2026-01-21 08:41:47 +08:00
|
|
|
|
# ȫ<><C8AB>ʵ<EFBFBD><CAB5>
|
2026-01-20 08:09:13 +08:00
|
|
|
|
redisKit = RedisKit()
|