feat(redis): refactor Redis configuration to use multiple logical databases
- Updated default REDIS_URL to remove explicit /0 suffix - Added dedicated Redis clients: - db0: general cache (redis_client) - db1: message cache (redis_message_client) - db2: binary storage (redis_binary_client) - db3: rate limiting (redis_rate_limit_client) - Updated configuration, Docker files, and main startup lifecycle accordingly - Replaced `get_redis()` usage in notification server with `redis_message_client`
This commit is contained in:
@@ -6,7 +6,7 @@ MYSQL_DATABASE="osu_api"
|
|||||||
MYSQL_USER="osu_api"
|
MYSQL_USER="osu_api"
|
||||||
MYSQL_PASSWORD="password"
|
MYSQL_PASSWORD="password"
|
||||||
MYSQL_ROOT_PASSWORD="password"
|
MYSQL_ROOT_PASSWORD="password"
|
||||||
REDIS_URL="redis://127.0.0.1:6379/0"
|
REDIS_URL="redis://127.0.0.1:6379"
|
||||||
|
|
||||||
# JWT Settings
|
# JWT Settings
|
||||||
# Use `openssl rand -hex 32` to generate a secure key
|
# Use `openssl rand -hex 32` to generate a secure key
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ STORAGE_SETTINGS='{
|
|||||||
]
|
]
|
||||||
redis_url: Annotated[
|
redis_url: Annotated[
|
||||||
str,
|
str,
|
||||||
Field(default="redis://127.0.0.1:6379/0", description="Redis 连接 URL"),
|
Field(default="redis://127.0.0.1:6379", description="Redis 连接 URL"),
|
||||||
"数据库设置",
|
"数据库设置",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -35,13 +35,16 @@ engine = create_async_engine(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Redis 连接
|
# Redis 连接
|
||||||
redis_client = redis.from_url(settings.redis_url, decode_responses=True)
|
redis_client = redis.from_url(settings.redis_url, decode_responses=True, db=0)
|
||||||
|
|
||||||
# Redis 二进制数据连接 (不自动解码响应,用于存储音频等二进制数据)
|
|
||||||
redis_binary_client = redis.from_url(settings.redis_url, decode_responses=False)
|
|
||||||
|
|
||||||
# Redis 消息缓存连接 (db1)
|
# Redis 消息缓存连接 (db1)
|
||||||
redis_message_client: redis.Redis = redis.from_url(settings.redis_url, decode_responses=True, db=1)
|
redis_message_client = redis.from_url(settings.redis_url, decode_responses=True, db=1)
|
||||||
|
|
||||||
|
# Redis 二进制数据连接 (不自动解码响应,用于存储音频等二进制数据,db2)
|
||||||
|
redis_binary_client = redis.from_url(settings.redis_url, decode_responses=False, db=2)
|
||||||
|
|
||||||
|
# Redis 限流连接 (db3)
|
||||||
|
redis_rate_limit_client = redis.from_url(settings.redis_url, decode_responses=True, db=3)
|
||||||
|
|
||||||
|
|
||||||
# 数据库依赖
|
# 数据库依赖
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from app.dependencies.database import (
|
|||||||
DBFactory,
|
DBFactory,
|
||||||
Redis,
|
Redis,
|
||||||
get_db_factory,
|
get_db_factory,
|
||||||
get_redis,
|
redis_message_client,
|
||||||
with_db,
|
with_db,
|
||||||
)
|
)
|
||||||
from app.dependencies.user import get_current_user_and_token
|
from app.dependencies.user import get_current_user_and_token
|
||||||
@@ -31,7 +31,7 @@ class ChatServer:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.connect_client: dict[int, WebSocket] = {}
|
self.connect_client: dict[int, WebSocket] = {}
|
||||||
self.channels: dict[int, list[int]] = {}
|
self.channels: dict[int, list[int]] = {}
|
||||||
self.redis: Redis = get_redis()
|
self.redis: Redis = redis_message_client
|
||||||
|
|
||||||
self.tasks: set[asyncio.Task] = set()
|
self.tasks: set[asyncio.Task] = set()
|
||||||
self.ChatSubscriber = ChatSubscriber()
|
self.ChatSubscriber = ChatSubscriber()
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- MYSQL_HOST=mysql
|
- MYSQL_HOST=mysql
|
||||||
- MYSQL_PORT=3306
|
- MYSQL_PORT=3306
|
||||||
- REDIS_URL=redis://redis:6379/0
|
- REDIS_URL=redis://redis:6379
|
||||||
- ENABLE_OSU_RX=true
|
- ENABLE_OSU_RX=true
|
||||||
- ENABLE_OSU_AP=true
|
- ENABLE_OSU_AP=true
|
||||||
- ENABLE_ALL_MODS_PP=true
|
- ENABLE_ALL_MODS_PP=true
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- MYSQL_HOST=mysql
|
- MYSQL_HOST=mysql
|
||||||
- MYSQL_PORT=3306
|
- MYSQL_PORT=3306
|
||||||
- REDIS_URL=redis://redis:6379/0
|
- REDIS_URL=redis://redis:6379
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|||||||
55
main.py
55
main.py
@@ -4,7 +4,14 @@ from pathlib import Path
|
|||||||
|
|
||||||
from app.config import settings
|
from app.config import settings
|
||||||
from app.database import User
|
from app.database import User
|
||||||
from app.dependencies.database import Database, engine, get_redis, redis_client
|
from app.dependencies.database import (
|
||||||
|
Database,
|
||||||
|
engine,
|
||||||
|
redis_binary_client,
|
||||||
|
redis_client,
|
||||||
|
redis_message_client,
|
||||||
|
redis_rate_limit_client,
|
||||||
|
)
|
||||||
from app.dependencies.fetcher import get_fetcher
|
from app.dependencies.fetcher import get_fetcher
|
||||||
from app.dependencies.scheduler import start_scheduler, stop_scheduler
|
from app.dependencies.scheduler import start_scheduler, stop_scheduler
|
||||||
from app.log import system_logger
|
from app.log import system_logger
|
||||||
@@ -50,39 +57,55 @@ import sentry_sdk
|
|||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(app: FastAPI): # noqa: ARG001
|
async def lifespan(app: FastAPI): # noqa: ARG001
|
||||||
# on startup
|
# === on startup ===
|
||||||
|
# init mods and achievements
|
||||||
init_mods()
|
init_mods()
|
||||||
init_ranked_mods()
|
init_ranked_mods()
|
||||||
await FastAPILimiter.init(get_redis())
|
load_achievements()
|
||||||
fetcher = await get_fetcher() # 初始化 fetcher
|
|
||||||
await init_geoip() # 初始化 GeoIP 数据库
|
# init rate limiter
|
||||||
|
await FastAPILimiter.init(redis_rate_limit_client)
|
||||||
|
|
||||||
|
# init fetcher
|
||||||
|
fetcher = await get_fetcher()
|
||||||
|
# init GeoIP
|
||||||
|
await init_geoip()
|
||||||
|
|
||||||
|
# init game server
|
||||||
await create_rx_statistics()
|
await create_rx_statistics()
|
||||||
await calculate_user_rank(True)
|
await calculate_user_rank(True)
|
||||||
await daily_challenge_job()
|
await daily_challenge_job()
|
||||||
await process_daily_challenge_top()
|
await process_daily_challenge_top()
|
||||||
await create_banchobot()
|
await create_banchobot()
|
||||||
await start_email_processor() # 启动邮件队列处理器
|
|
||||||
await download_service.start_health_check() # 启动下载服务健康检查
|
# services
|
||||||
await start_cache_tasks() # 启动缓存调度器
|
await start_email_processor()
|
||||||
|
await download_service.start_health_check()
|
||||||
|
await start_cache_tasks()
|
||||||
init_beatmapset_update_service(fetcher) # 初始化谱面集更新服务
|
init_beatmapset_update_service(fetcher) # 初始化谱面集更新服务
|
||||||
redis_message_system.start() # 启动 Redis 消息系统
|
redis_message_system.start()
|
||||||
load_achievements()
|
|
||||||
start_scheduler()
|
start_scheduler()
|
||||||
|
|
||||||
# 显示资源代理状态
|
# show the status of AssetProxy
|
||||||
if settings.enable_asset_proxy:
|
if settings.enable_asset_proxy:
|
||||||
system_logger("AssetProxy").info(f"Asset Proxy enabled - Domain: {settings.custom_asset_domain}")
|
system_logger("AssetProxy").info(f"Asset Proxy enabled - Domain: {settings.custom_asset_domain}")
|
||||||
|
|
||||||
# on shutdown
|
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
# === on shutdown ===
|
||||||
|
# stop services
|
||||||
bg_tasks.stop()
|
bg_tasks.stop()
|
||||||
redis_message_system.stop() # 停止 Redis 消息系统
|
await stop_cache_tasks()
|
||||||
await stop_cache_tasks() # 停止缓存调度器
|
|
||||||
stop_scheduler()
|
stop_scheduler()
|
||||||
await download_service.stop_health_check() # 停止下载服务健康检查
|
await download_service.stop_health_check()
|
||||||
await stop_email_processor() # 停止邮件队列处理器
|
await stop_email_processor()
|
||||||
|
|
||||||
|
# close database & redis
|
||||||
await engine.dispose()
|
await engine.dispose()
|
||||||
await redis_client.aclose()
|
await redis_client.aclose()
|
||||||
|
await redis_binary_client.aclose()
|
||||||
|
await redis_message_client.aclose()
|
||||||
|
await redis_rate_limit_client.aclose()
|
||||||
|
|
||||||
|
|
||||||
desc = f"""osu! API 模拟服务器,支持 osu! API v1, v2 和 osu!lazer 的绝大部分功能。
|
desc = f"""osu! API 模拟服务器,支持 osu! API v1, v2 和 osu!lazer 的绝大部分功能。
|
||||||
|
|||||||
Reference in New Issue
Block a user