perf: Cache config

This commit is contained in:
fit2cloud-chenyw
2025-07-24 16:15:33 +08:00
parent 19c0f946e3
commit e739284db9
5 changed files with 36 additions and 16 deletions
+3
View File
@@ -21,6 +21,9 @@ LOG_DIR="/opt/sqlbot/logs"
LOG_FORMAT="%(asctime)s - %(name)s - %(levelname)s:%(lineno)d - %(message)s"
SQL_DEBUG=False
CACHE_TYPE="memory"
CACHE_REDIS_URL="redis://127.0.0.1:6379"
# Postgres
POSTGRES_SERVER=localhost
POSTGRES_PORT=5432
+3
View File
@@ -61,6 +61,9 @@ class Settings(BaseSettings):
DEFAULT_PWD: str = "SQLBot@123456"
ASSISTANT_TOKEN_KEY: str = "X-SQLBOT-ASSISTANT-TOKEN"
CACHE_TYPE: Literal["redis", "memory", "None"] = "memory"
CACHE_REDIS_URL: str | None = None # Redis URL, e.g., "redis://[[username]:[password]]@localhost:6379/0"
LOG_LEVEL: str = "INFO" # DEBUG, INFO, WARNING, ERROR
LOG_DIR: str = "logs"
LOG_FORMAT: str = "%(asctime)s - %(name)s - %(levelname)s:%(lineno)d - %(message)s"
+27 -13
View File
@@ -7,11 +7,9 @@ from contextlib import asynccontextmanager
import asyncio
import random
from collections import defaultdict
from apps.system.schemas.auth import CacheName
from apps.system.schemas.system_schema import UserInfoDTO
from common.core.config import settings
from common.utils.utils import SQLBotLogUtil
from fastapi_cache.backends.inmemory import InMemoryBackend
# 使用contextvar来跟踪当前线程已持有的锁
_held_locks = contextvars.ContextVar('held_locks', default=set())
# 高效锁管理器
@@ -105,6 +103,8 @@ def cache(
@wraps(func)
async def wrapper(*args, **kwargs):
if not settings.CACHE_TYPE or settings.CACHE_TYPE.lower() == "none":
return await func(*args, **kwargs)
# 生成缓存键
cache_key = used_key_builder(
func=func,
@@ -116,13 +116,9 @@ def cache(
# 防击穿锁
async with _get_cache_lock(cache_key):
backend = FastAPICache.get_backend()
# 双重检查
if (cached := await backend.get(cache_key)) is not None:
SQLBotLogUtil.debug(f"Cache hit: {cache_key}")
if CacheName.USER_INFO.value in cache_key:
user = UserInfoDTO.model_validate(cached)
SQLBotLogUtil.info(f"User cache hit: [uid: {user.id}, account: {user.account}, oid: {user.oid}]")
return cached
# 执行函数并缓存结果
@@ -134,9 +130,6 @@ def cache(
await backend.set(cache_key, result, actual_expire)
SQLBotLogUtil.debug(f"Cache set: {cache_key} (expire: {actual_expire}s)")
if CacheName.USER_INFO.value in cache_key:
user = UserInfoDTO.model_validate(result)
SQLBotLogUtil.info(f"User cache set: [uid: {user.id}, account: {user.account}, oid: {user.oid}]")
return result
return wrapper
@@ -152,6 +145,8 @@ def clear_cache(
def decorator(func):
@wraps(func)
async def wrapper(*args, **kwargs):
if not settings.CACHE_TYPE or settings.CACHE_TYPE.lower() == "none":
return await func(*args, **kwargs)
cache_key = custom_key_builder(
func=func,
namespace=namespace,
@@ -170,8 +165,27 @@ def clear_cache(
result = await func(*args, **kwargs)
if await backend.get(cache_key):
await backend.clear(cache_key)
SQLBotLogUtil.info(f"Cache cleared: {cache_key}")
SQLBotLogUtil.debug(f"Cache cleared: {cache_key}")
return result
return wrapper
return decorator
return decorator
def init_sqlbot_cache():
cache_type: str = settings.CACHE_TYPE
if cache_type == "memory":
FastAPICache.init(InMemoryBackend())
SQLBotLogUtil.info("SQLBot 使用内存缓存, 仅支持单进程模式")
elif cache_type == "redis":
from fastapi_cache.backends.redis import RedisBackend
import redis.asyncio as redis
from redis.asyncio.connection import ConnectionPool
redis_url = settings.CACHE_REDIS_URL or "redis://localhost:6379/0"
pool = ConnectionPool.from_url(url=redis_url)
redis_client = redis.Redis(connection_pool=pool)
FastAPICache.init(RedisBackend(redis_client), prefix="sqlbot-cache")
SQLBotLogUtil.info(f"SQLBot 使用Redis缓存, 可使用多进程模式")
else:
SQLBotLogUtil.warning("SQLBot 未启用缓存, 可使用多进程模式")
+2 -3
View File
@@ -14,10 +14,9 @@ from alembic import command
from fastapi_mcp import FastApiMCP
from fastapi.staticfiles import StaticFiles
import sqlbot_xpack
from fastapi_cache import FastAPICache
from fastapi_cache.backends.inmemory import InMemoryBackend
from common.utils.utils import SQLBotLogUtil
from common.core.sqlbot_cache import init_sqlbot_cache
def run_migrations():
alembic_cfg = Config("alembic.ini")
@@ -27,7 +26,7 @@ def run_migrations():
@asynccontextmanager
async def lifespan(app: FastAPI):
run_migrations()
FastAPICache.init(InMemoryBackend())
init_sqlbot_cache()
init_dynamic_cors(app)
SQLBotLogUtil.info("✅ SQLBot 初始化完成")
yield
+1
View File
@@ -39,6 +39,7 @@ dependencies = [
"sqlbot-xpack==0.0.3.7",
"fastapi-cache2>=0.2.2",
"sqlparse>=0.5.3",
"redis>=6.2.0",
]
[[tool.uv.index]]
name = "default"