docs: 创建 analysis-storage-refactor Design Doc

refactor3.0
Lxy 2 weeks ago
parent 819e36a8eb
commit 82de2f98c0

@ -0,0 +1,188 @@
---
comet_change: analysis-storage-refactor
role: technical-design
canonical_spec: openspec
---
# Analysis Storage Refactor - Technical Design
## 1. 架构概览
### 1.1 目标架构
```
┌─────────────────────────────────────────────────────────────┐
│ 应用层 │
│ app/api/futures_analysis.py ←→ app/services/cache.py │
│ ↓ │
│ StorageManager │
│ (storage_manager.py) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────┼─────────────────────┐
↓ ↓ ↓
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Redis │ │ MySQL │ │ SQLite │
│ (缓存) │ │(持久化) │ │ (兜底) │
└─────────┘ └─────────┘ └─────────┘
```
### 1.2 核心组件
| 组件 | 职责 |
|------|------|
| `StorageManager` | 封装三级存储逻辑,提供统一读写接口 |
| `analysis_db.py` | Analysis 数据库连接管理,降级逻辑 |
| `analysis_models.py` | ORM 模型定义(不变) |
| `analysis_migration.py` | SQLite → MySQL 数据迁移 |
### 1.3 表清单
| 表名 | 用途 | 缓存 TTL |
|------|------|----------|
| `futures_analysis` | 期货分析报告 | 5 分钟 |
| `watched_symbols` | 用户关注品种 | 10 分钟 |
| `ai_model_configs` | AI 模型配置 | 10 分钟 |
| `analysis_settings` | 分析设置 | 10 分钟 |
| `ai_analysis_cache` | AI 分析缓存 | 5 分钟 |
| `review_dates` | 复盘日期 | 1 小时 |
| `symbol_rankings` | 品种排名 | 1 小时 |
| `trading_plans` | 交易计划 | 1 小时 |
| `symbol_scores_v2` | V2 品种评分 | 1 小时 |
| `trading_plans_v2` | V2 交易计划 | 1 小时 |
| `sector_heat` | 板块热度 | 1 小时 |
| `review_plans_v2` | V2 复盘计划 | 1 小时 |
| `trade_records` | 交易记录 | 不缓存 |
| `trade_import_batches` | 交易导入批次 | 不缓存 |
## 2. 降级策略
### 2.1 读取流程
```
读取请求
检查 Redis 缓存
↓ 命中
返回数据
↓ 未命中
检查 MySQL 可用性
↓ 可用
查询 MySQL → 回填 Redis → 返回
↓ 不可用
降级到 SQLite → 返回
```
### 2.2 写入流程
```
写入请求
删除 Redis 缓存
写入 MySQL事务
↓ 成功
回填 Redis → 返回
↓ 失败
写入 SQLite → 返回
```
### 2.3 降级状态检测
- 惰性检测30 秒间隔
- Redis 不可用时跳过缓存层
- MySQL 不可用时降级到 SQLite
## 3. 数据迁移
### 3.1 迁移时机
应用启动时(`lifespan`),在 MySQL 表结构初始化后执行。
### 3.2 迁移逻辑
```python
def migrate_analysis_sqlite_to_mysql():
"""将 SQLite analysis 数据迁移到 MySQL"""
# 1. 检测 MySQL 表是否已有数据
mysql_count = count_mysql_analysis_tables()
if mysql_count > 0:
logger.info("MySQL analysis 表已有数据,跳过迁移")
return
# 2. 从 SQLite 读取数据
sqlite_data = read_sqlite_analysis_data()
# 3. 批量写入 MySQL
write_mysql_analysis_data(sqlite_data)
logger.info("Analysis 数据迁移完成")
```
### 3.3 幂等性
- 检测 MySQL 表是否已有数据
- 有数据则跳过迁移
- 迁移失败不影响应用启动
## 4. 缓存策略
### 4.1 缓存键设计
```
analysis:{table_name}:{id}
analysis:{table_name}:list:{query_hash}
```
### 4.2 缓存失效
- 写入时删除相关缓存
- TTL 过期自动失效
### 4.3 缓存回填
- 读取时未命中,查询 MySQL 后回填
- TTL 与表类型对应
## 5. 兼容性
### 5.1 ORM 模型
- 保持不变
- 使用 `AnalysisBase` 作为基类
### 5.2 API 接口
- 保持不变
- 通过 `get_analysis_db()` 依赖注入
### 5.3 SQLite 文件
- 保留 `data/futures_analysis.db`
- 降级时使用
## 6. 测试策略
### 6.1 单元测试
| 场景 | 测试方法 |
|------|----------|
| Redis 缓存命中 | Mock Redis验证不查询 MySQL |
| Redis 缓存未命中 | Mock Redis 返回 None验证查询 MySQL |
| MySQL 降级到 SQLite | Mock MySQL 不可用,验证查询 SQLite |
| 数据迁移 | 验证 SQLite 数据完整迁移到 MySQL |
### 6.2 集成测试
- 启动应用,验证 MySQL 表创建
- 执行迁移,验证数据完整性
- 调用 API验证功能正常
## 7. 风险与缓解
| 风险 | 缓解措施 |
|------|----------|
| 数据迁移失败 | 保留 SQLite 作为降级方案,迁移失败时自动降级 |
| Redis 缓存不一致 | 写入时先删缓存,再写 MySQL最后回填缓存 |
| 表结构不兼容 | 复用现有 ORM 模型MySQL 自动创建表结构 |
| 性能下降 | Redis 缓存减少 MySQL 查询压力 |

@ -1,5 +1,5 @@
workflow: full workflow: full
phase: design phase: build
context_compression: off context_compression: off
build_mode: null build_mode: null
build_pause: null build_pause: null
@ -10,7 +10,7 @@ isolation: null
verify_mode: null verify_mode: null
auto_transition: true auto_transition: true
base_ref: 62a95ca base_ref: 62a95ca
design_doc: null design_doc: docs/superpowers/specs/2026-07-04-analysis-storage-refactor-design.md
plan: null plan: null
verify_result: null verify_result: null
verification_report: null verification_report: null

@ -0,0 +1,42 @@
# Brainstorm Summary
- Change: analysis-storage-refactor
- Date: 2026-07-04
## 确认的技术方案
`futures_analysis.db`14 张表)迁移到 MySQL `buffer_platform` 数据库,并引入 Redis 缓存层与行情数据存储策略保持一致Redis→MySQL→SQLite 三级降级)。
### 核心设计
1. **复用现有连接**:使用 `storage_manager.py` 中的 `mysql_engine``redis_client`
2. **扩展 StorageManager**:新增 analysis 表读写方法
3. **降级策略**Redis 缓存 → MySQL 持久化 → SQLite 兜底
4. **数据迁移**:启动时自动迁移现有 SQLite 数据到 MySQL
### 缓存策略
| 表类型 | 缓存 TTL | 说明 |
|--------|----------|------|
| AI 分析结果 | 5 分钟 | 频繁读取,短期缓存 |
| 复盘计划 | 1 小时 | 每日更新,中期缓存 |
| 交易记录 | 不缓存 | 写入后不再修改 |
| 配置表 | 10 分钟 | 低频读取 |
## 关键取舍与风险
| 取舍/风险 | 决策/缓解 |
|-----------|-----------|
| 表名前缀 | 保持原名,通过 ORM 模型区分 |
| 数据迁移失败 | 保留 SQLite 作为降级方案 |
| Redis 缓存一致性 | 写入时先删缓存,再写 MySQL最后回填 |
## 测试策略
1. 单元测试:三级降级场景
2. 集成测试:数据迁移完整性
3. 功能测试现有功能AI 分析、复盘计划、交易记录)正常工作
## Spec Patch
无(复用已有 delta spec 结构)
Loading…
Cancel
Save