436 lines
17 KiB
Markdown
436 lines
17 KiB
Markdown
# 数据库架构
|
||
|
||
<cite>
|
||
**本文引用的文件**
|
||
- [backend/app/database.py](file://backend/app/database.py)
|
||
- [backend/app/config.py](file://backend/app/config.py)
|
||
- [backend/alembic/env.py](file://backend/alembic/env.py)
|
||
- [backend/alembic/versions/488d0bd5ab01_initial_migration.py](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py)
|
||
- [backend/requirements.txt](file://backend/requirements.txt)
|
||
- [backend/app/models/user.py](file://backend/app/models/user.py)
|
||
- [backend/app/models/query.py](file://backend/app/models/query.py)
|
||
- [backend/app/models/citation_record.py](file://backend/app/models/citation_record.py)
|
||
- [backend/app/models/query_task.py](file://backend/app/models/query_task.py)
|
||
- [backend/app/models/subscription.py](file://backend/app/models/subscription.py)
|
||
- [backend/app/models/__init__.py](file://backend/app/models/__init__.py)
|
||
- [backend/app/api/deps.py](file://backend/app/api/deps.py)
|
||
- [backend/app/api/auth.py](file://backend/app/api/auth.py)
|
||
- [backend/app/main.py](file://backend/app/main.py)
|
||
- [docker-compose.yml](file://docker-compose.yml)
|
||
</cite>
|
||
|
||
## 目录
|
||
1. [简介](#简介)
|
||
2. [项目结构](#项目结构)
|
||
3. [核心组件](#核心组件)
|
||
4. [架构总览](#架构总览)
|
||
5. [详细组件分析](#详细组件分析)
|
||
6. [依赖分析](#依赖分析)
|
||
7. [性能考量](#性能考量)
|
||
8. [故障排查指南](#故障排查指南)
|
||
9. [结论](#结论)
|
||
10. [附录](#附录)
|
||
|
||
## 简介
|
||
本文件系统性梳理 GEO 平台的数据库架构,重点覆盖以下方面:
|
||
- 基于 PostgreSQL 的异步数据库连接配置:SQLAlchemy 异步引擎、连接池与会话生命周期管理
|
||
- 连接字符串配置、环境变量管理与安全注意事项
|
||
- 异步数据库操作的优势、性能特征与最佳实践
|
||
- 连接监控、错误处理与故障恢复机制
|
||
- 生产环境配置建议与性能调优指南
|
||
|
||
## 项目结构
|
||
后端采用 FastAPI + SQLAlchemy 2.x 异步 ORM 架构,数据库层由异步引擎与会话工厂构成,配合 Alembic 进行迁移管理;模型定义位于 models 子包中,并通过 API 层注入依赖进行使用。
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "后端应用"
|
||
CFG["配置模块<br/>app/config.py"]
|
||
DB["数据库引擎与会话<br/>app/database.py"]
|
||
MODELS["ORM 模型<br/>app/models/*"]
|
||
ALEMBIC["迁移环境<br/>alembic/env.py"]
|
||
MIGRATE["初始迁移脚本<br/>alembic/versions/*"]
|
||
API_DEPS["API 依赖注入<br/>app/api/deps.py"]
|
||
API_AUTH["认证路由<br/>app/api/auth.py"]
|
||
MAIN["应用入口与生命周期<br/>app/main.py"]
|
||
end
|
||
subgraph "外部服务"
|
||
PG["PostgreSQL 实例"]
|
||
REDIS["Redis 实例"]
|
||
end
|
||
CFG --> DB
|
||
DB --> MODELS
|
||
ALEMBIC --> MIGRATE
|
||
API_DEPS --> DB
|
||
API_AUTH --> DB
|
||
MAIN --> API_AUTH
|
||
MAIN --> API_DEPS
|
||
DB --> PG
|
||
REDIS -. 缓存/任务队列 .-> MAIN
|
||
```
|
||
|
||
图表来源
|
||
- [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29)
|
||
- [backend/app/config.py:1-17](file://backend/app/config.py#L1-L17)
|
||
- [backend/alembic/env.py:1-89](file://backend/alembic/env.py#L1-L89)
|
||
- [backend/alembic/versions/488d0bd5ab01_initial_migration.py:1-128](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L1-L128)
|
||
- [backend/app/api/deps.py:1-43](file://backend/app/api/deps.py#L1-L43)
|
||
- [backend/app/api/auth.py:1-43](file://backend/app/api/auth.py#L1-L43)
|
||
- [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48)
|
||
|
||
章节来源
|
||
- [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29)
|
||
- [backend/app/config.py:1-17](file://backend/app/config.py#L1-L17)
|
||
- [backend/alembic/env.py:1-89](file://backend/alembic/env.py#L1-L89)
|
||
- [backend/alembic/versions/488d0bd5ab01_initial_migration.py:1-128](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L1-L128)
|
||
- [backend/app/api/deps.py:1-43](file://backend/app/api/deps.py#L1-L43)
|
||
- [backend/app/api/auth.py:1-43](file://backend/app/api/auth.py#L1-L43)
|
||
- [backend/app/main.py:1-48](file://backend/app/main.py#L1-L48)
|
||
|
||
## 核心组件
|
||
- 异步引擎与会话工厂
|
||
- 使用 SQLAlchemy 异步引擎创建数据库连接,关闭 echo,启用 future 模式
|
||
- 会话工厂配置为非自动提交、非自动刷新、关闭提交时过期,确保事务边界清晰
|
||
- 提供异步上下文管理的会话生成器,保证在请求结束时正确关闭会话
|
||
- 配置与连接字符串
|
||
- 通过 Pydantic Settings 从 .env 文件加载配置,包含 DATABASE_URL、REDIS_URL、JWT_SECRET 等
|
||
- 默认 DATABASE_URL 指向本地或容器内 PostgreSQL 实例
|
||
- 模型与索引
|
||
- 用户、查询、引用记录、查询任务、订阅等核心实体,均采用 PostgreSQL UUID 主键与 JSONB 字段
|
||
- 在高频查询字段上建立复合索引,提升读取性能
|
||
- 迁移与初始化
|
||
- Alembic 环境支持离线与在线迁移,使用异步引擎执行迁移
|
||
- 初始迁移脚本创建表结构与索引,定义外键约束与默认值
|
||
|
||
章节来源
|
||
- [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29)
|
||
- [backend/app/config.py:1-17](file://backend/app/config.py#L1-L17)
|
||
- [backend/app/models/user.py:1-41](file://backend/app/models/user.py#L1-L41)
|
||
- [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55)
|
||
- [backend/app/models/citation_record.py:1-42](file://backend/app/models/citation_record.py#L1-L42)
|
||
- [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39)
|
||
- [backend/app/models/subscription.py:1-37](file://backend/app/models/subscription.py#L1-L37)
|
||
- [backend/alembic/env.py:64-88](file://backend/alembic/env.py#L64-L88)
|
||
- [backend/alembic/versions/488d0bd5ab01_initial_migration.py:21-128](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L21-L128)
|
||
|
||
## 架构总览
|
||
下图展示异步数据库连接在应用中的整体流转:FastAPI 路由通过依赖注入获取 AsyncSession,执行数据库操作后自动释放;迁移通过 Alembic 异步引擎执行;配置从 .env 加载 DATABASE_URL。
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant Client as "客户端"
|
||
participant API as "FastAPI 路由"
|
||
participant Deps as "依赖注入(get_db)"
|
||
participant Session as "AsyncSession"
|
||
participant Engine as "异步引擎"
|
||
participant PG as "PostgreSQL"
|
||
Client->>API : "HTTP 请求"
|
||
API->>Deps : "解析依赖(获取会话)"
|
||
Deps->>Session : "创建/获取会话"
|
||
Session->>Engine : "执行 SQL"
|
||
Engine->>PG : "发送查询"
|
||
PG-->>Engine : "返回结果"
|
||
Engine-->>Session : "映射为模型"
|
||
Session-->>API : "业务结果"
|
||
API-->>Client : "响应"
|
||
API->>Deps : "请求结束"
|
||
Deps->>Session : "关闭会话"
|
||
```
|
||
|
||
图表来源
|
||
- [backend/app/api/auth.py:13-42](file://backend/app/api/auth.py#L13-L42)
|
||
- [backend/app/api/deps.py:16-42](file://backend/app/api/deps.py#L16-L42)
|
||
- [backend/app/database.py:23-28](file://backend/app/database.py#L23-L28)
|
||
|
||
## 详细组件分析
|
||
|
||
### 异步引擎与会话生命周期
|
||
- 引擎创建
|
||
- 使用异步引擎,echo 关闭,future 启用,避免冗余日志与兼容性问题
|
||
- 会话工厂
|
||
- 非自动提交、非自动刷新、关闭提交时过期,便于显式控制事务
|
||
- 会话生成器
|
||
- 通过上下文管理器确保异常时也能正确关闭会话,避免连接泄漏
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
Start(["进入 get_db"]) --> NewSession["创建 AsyncSessionLocal()"]
|
||
NewSession --> TryBlock["进入 try 块并 yield 会话"]
|
||
TryBlock --> FinallyBlock["finally 块中关闭会话"]
|
||
FinallyBlock --> End(["退出 get_db"])
|
||
```
|
||
|
||
图表来源
|
||
- [backend/app/database.py:23-28](file://backend/app/database.py#L23-L28)
|
||
|
||
章节来源
|
||
- [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29)
|
||
|
||
### 连接字符串与环境变量管理
|
||
- 连接字符串
|
||
- 默认 DATABASE_URL 指向 PostgreSQL 实例,可在 .env 中覆盖
|
||
- 环境变量加载
|
||
- 通过 Pydantic SettingsConfigDict 从 .env 加载,忽略未知字段
|
||
- 安全注意事项
|
||
- 生产环境务必使用强密钥与加密传输
|
||
- 不要在代码中硬编码敏感信息,优先使用环境变量与密钥管理服务
|
||
|
||
章节来源
|
||
- [backend/app/config.py:4-16](file://backend/app/config.py#L4-L16)
|
||
|
||
### 数据模型与索引策略
|
||
- 用户模型
|
||
- UUID 主键、邮箱唯一、密码哈希、计划与配额字段
|
||
- 查询模型
|
||
- 外键关联用户、JSONB 存储平台与别名、多字段索引优化
|
||
- 引用记录模型
|
||
- JSONB 存储竞品品牌与原始响应,按查询与时间、平台建立索引
|
||
- 查询任务模型
|
||
- 状态字段索引,便于任务调度与状态统计
|
||
- 订阅模型
|
||
- 金额与支付信息存储,日期范围与状态管理
|
||
|
||
```mermaid
|
||
erDiagram
|
||
USERS {
|
||
uuid id PK
|
||
string email UK
|
||
string password_hash
|
||
string name
|
||
string plan
|
||
int max_queries
|
||
bool is_active
|
||
timestamptz created_at
|
||
timestamptz updated_at
|
||
}
|
||
QUERIES {
|
||
uuid id PK
|
||
uuid user_id FK
|
||
string keyword
|
||
string target_brand
|
||
jsonb brand_aliases
|
||
jsonb platforms
|
||
string frequency
|
||
string status
|
||
timestamptz last_queried_at
|
||
timestamptz next_query_at
|
||
timestamptz created_at
|
||
timestamptz updated_at
|
||
}
|
||
CITATION_RECORDS {
|
||
uuid id PK
|
||
uuid query_id FK
|
||
string platform
|
||
bool cited
|
||
int citation_position
|
||
text citation_text
|
||
jsonb competitor_brands
|
||
text raw_response
|
||
timestamptz queried_at
|
||
}
|
||
QUERY_TASKS {
|
||
uuid id PK
|
||
uuid query_id FK
|
||
string platform
|
||
string status
|
||
text error_message
|
||
timestamptz scheduled_at
|
||
timestamptz started_at
|
||
timestamptz completed_at
|
||
}
|
||
SUBSCRIPTIONS {
|
||
uuid id PK
|
||
uuid user_id FK
|
||
string plan
|
||
string status
|
||
date start_date
|
||
date end_date
|
||
numeric amount
|
||
string payment_method
|
||
string payment_id
|
||
timestamptz created_at
|
||
}
|
||
USERS ||--o{ QUERIES : "拥有"
|
||
QUERIES ||--o{ CITATION_RECORDS : "产生"
|
||
QUERIES ||--o{ QUERY_TASKS : "驱动"
|
||
USERS ||--o{ SUBSCRIPTIONS : "订阅"
|
||
```
|
||
|
||
图表来源
|
||
- [backend/app/models/user.py:11-41](file://backend/app/models/user.py#L11-L41)
|
||
- [backend/app/models/query.py:11-55](file://backend/app/models/query.py#L11-L55)
|
||
- [backend/app/models/citation_record.py:11-42](file://backend/app/models/citation_record.py#L11-L42)
|
||
- [backend/app/models/query_task.py:11-39](file://backend/app/models/query_task.py#L11-L39)
|
||
- [backend/app/models/subscription.py:11-37](file://backend/app/models/subscription.py#L11-L37)
|
||
|
||
章节来源
|
||
- [backend/app/models/user.py:1-41](file://backend/app/models/user.py#L1-L41)
|
||
- [backend/app/models/query.py:1-55](file://backend/app/models/query.py#L1-L55)
|
||
- [backend/app/models/citation_record.py:1-42](file://backend/app/models/citation_record.py#L1-L42)
|
||
- [backend/app/models/query_task.py:1-39](file://backend/app/models/query_task.py#L1-L39)
|
||
- [backend/app/models/subscription.py:1-37](file://backend/app/models/subscription.py#L1-L37)
|
||
|
||
### 迁移与初始化
|
||
- 离线/在线迁移
|
||
- 离线模式直接使用 DATABASE_URL;在线模式通过异步引擎建立连接并执行迁移
|
||
- 使用 NullPool 避免额外连接池开销
|
||
- 初始迁移
|
||
- 创建 users、queries、citation_records、query_tasks、subscriptions 表
|
||
- 添加必要的外键与索引,确保查询性能与数据一致性
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant CLI as "Alembic CLI"
|
||
participant Env as "env.py"
|
||
participant Engine as "异步引擎"
|
||
participant Conn as "连接"
|
||
participant DB as "PostgreSQL"
|
||
CLI->>Env : "run_migrations_online()"
|
||
Env->>Engine : "create_async_engine(DATABASE_URL, poolclass=NullPool)"
|
||
Engine->>Conn : "connect()"
|
||
Conn->>DB : "执行迁移"
|
||
DB-->>Conn : "返回迁移结果"
|
||
Conn-->>Engine : "完成迁移"
|
||
Engine-->>Env : "dispose()"
|
||
```
|
||
|
||
图表来源
|
||
- [backend/alembic/env.py:64-88](file://backend/alembic/env.py#L64-L88)
|
||
- [backend/alembic/versions/488d0bd5ab01_initial_migration.py:21-128](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L21-L128)
|
||
|
||
章节来源
|
||
- [backend/alembic/env.py:1-89](file://backend/alembic/env.py#L1-L89)
|
||
- [backend/alembic/versions/488d0bd5ab01_initial_migration.py:1-128](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L1-L128)
|
||
|
||
### API 依赖注入与会话使用
|
||
- 依赖注入
|
||
- OAuth2 密钥流用于令牌校验;通过 get_db 获取 AsyncSession
|
||
- 典型流程
|
||
- 注册/登录接口使用 AsyncSession 执行写入与查询
|
||
- 当前用户接口通过令牌解析与数据库查询返回用户信息
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant Client as "客户端"
|
||
participant Auth as "认证路由"
|
||
participant Deps as "get_current_user"
|
||
participant DB as "AsyncSession"
|
||
participant Model as "User 模型"
|
||
Client->>Auth : "POST /api/v1/auth/login"
|
||
Auth->>DB : "执行认证查询"
|
||
DB-->>Auth : "返回用户对象"
|
||
Auth-->>Client : "返回访问令牌与用户信息"
|
||
Client->>Auth : "GET /api/v1/auth/me"
|
||
Auth->>Deps : "校验令牌并解析用户ID"
|
||
Deps->>DB : "查询用户"
|
||
DB-->>Deps : "返回用户"
|
||
Deps-->>Client : "返回当前用户"
|
||
```
|
||
|
||
图表来源
|
||
- [backend/app/api/auth.py:13-42](file://backend/app/api/auth.py#L13-L42)
|
||
- [backend/app/api/deps.py:16-42](file://backend/app/api/deps.py#L16-L42)
|
||
|
||
章节来源
|
||
- [backend/app/api/auth.py:1-43](file://backend/app/api/auth.py#L1-L43)
|
||
- [backend/app/api/deps.py:1-43](file://backend/app/api/deps.py#L1-L43)
|
||
|
||
## 依赖分析
|
||
- 组件耦合
|
||
- API 层通过依赖注入使用数据库会话,降低耦合度
|
||
- 模型与数据库层解耦,仅依赖 Base 与类型注解
|
||
- 外部依赖
|
||
- SQLAlchemy 2.x 异步 ORM、asyncpg、Alembic
|
||
- FastAPI、Pydantic Settings、Redis(缓存/任务)
|
||
|
||
```mermaid
|
||
graph LR
|
||
API_AUTH["app/api/auth.py"] --> DEPS["app/api/deps.py"]
|
||
DEPS --> DB["app/database.py"]
|
||
API_AUTH --> DB
|
||
DB --> CONFIG["app/config.py"]
|
||
DB --> MODELS["app/models/*"]
|
||
ALEMBIC_ENV["alembic/env.py"] --> CONFIG
|
||
ALEMBIC_ENV --> MODELS
|
||
ALEMBIC_MIG["alembic/versions/*"] --> MODELS
|
||
```
|
||
|
||
图表来源
|
||
- [backend/app/api/auth.py:1-43](file://backend/app/api/auth.py#L1-L43)
|
||
- [backend/app/api/deps.py:1-43](file://backend/app/api/deps.py#L1-L43)
|
||
- [backend/app/database.py:1-29](file://backend/app/database.py#L1-L29)
|
||
- [backend/app/config.py:1-17](file://backend/app/config.py#L1-L17)
|
||
- [backend/alembic/env.py:1-89](file://backend/alembic/env.py#L1-L89)
|
||
- [backend/alembic/versions/488d0bd5ab01_initial_migration.py:1-128](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L1-L128)
|
||
|
||
章节来源
|
||
- [backend/requirements.txt:1-35](file://backend/requirements.txt#L1-L35)
|
||
|
||
## 性能考量
|
||
- 异步优势
|
||
- 高并发场景下减少阻塞,提升吞吐量
|
||
- 与 FastAPI 协同,充分利用事件循环
|
||
- 连接池与会话
|
||
- 默认未显式配置连接池参数,建议在生产中根据 QPS 与实例规格调整最大连接数、空闲连接数与超时
|
||
- 索引与查询
|
||
- 已在高频查询字段建立索引,避免全表扫描
|
||
- 对 JSONB 字段的查询建议结合 GIN 索引(如需)
|
||
- 写入优化
|
||
- 批量写入与事务合并可显著降低写入延迟
|
||
- 监控与观测
|
||
- 建议集成数据库性能视图与慢查询日志
|
||
- 结合应用指标(请求耗时、错误率)定位瓶颈
|
||
|
||
## 故障排查指南
|
||
- 连接失败
|
||
- 检查 DATABASE_URL 是否正确,网络连通性与防火墙
|
||
- 确认 PostgreSQL 实例健康状态与认证凭据
|
||
- 迁移失败
|
||
- 离线/在线模式分别检查配置与权限
|
||
- 查看 Alembic 输出与 PostgreSQL 日志
|
||
- 会话泄漏
|
||
- 确保所有分支均能到达 finally 块,避免异常中断导致会话未关闭
|
||
- 错误处理
|
||
- API 层对认证失败与数据库异常进行标准化响应
|
||
- 建议增加重试与熔断策略(如适用)
|
||
|
||
章节来源
|
||
- [backend/app/database.py:23-28](file://backend/app/database.py#L23-L28)
|
||
- [backend/alembic/env.py:64-88](file://backend/alembic/env.py#L64-L88)
|
||
- [backend/app/api/auth.py:13-42](file://backend/app/api/auth.py#L13-L42)
|
||
- [backend/app/api/deps.py:16-42](file://backend/app/api/deps.py#L16-L42)
|
||
|
||
## 结论
|
||
GEO 项目采用 SQLAlchemy 异步 ORM 与 FastAPI 构建了高并发、可维护的数据库层。通过合理的模型设计、索引策略与依赖注入,实现了清晰的职责分离与良好的扩展性。建议在生产环境中完善连接池参数、监控体系与安全策略,持续优化查询与写入路径。
|
||
|
||
## 附录
|
||
|
||
### 生产环境配置建议
|
||
- 连接字符串与环境变量
|
||
- 使用独立 .env 文件管理 DATABASE_URL,避免硬编码
|
||
- 在容器编排中通过环境注入,确保不同环境隔离
|
||
- 连接池与会话
|
||
- 显式配置最大连接数、空闲连接数、连接超时与回收策略
|
||
- 控制会话生命周期,避免长事务与长时间持有连接
|
||
- 安全
|
||
- 使用强口令与 TLS 加密传输
|
||
- 限制数据库用户权限,最小化授权
|
||
- 监控与可观测性
|
||
- 集成数据库性能视图与慢查询日志
|
||
- 应用层记录关键指标(QPS、P95/P99、错误率)
|
||
- 备份与恢复
|
||
- 定期备份策略与演练,确保可快速恢复
|
||
|
||
### 性能调优清单
|
||
- 索引优化
|
||
- 对高频过滤与排序字段建立合适索引
|
||
- 对 JSONB 字段查询考虑 GIN 索引
|
||
- 查询优化
|
||
- 减少 N+1 查询,使用 select_in_load 或 joinedload
|
||
- 合理分页与投影,避免 SELECT *
|
||
- 写入优化
|
||
- 批量插入与事务合并
|
||
- 写入热点拆分与读写分离(如需要)
|
||
- 连接与资源
|
||
- 合理设置连接池大小,避免过度占用
|
||
- 及时关闭会话与释放资源 |