You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

89 lines
3.0 KiB

# Design: Analysis Storage Refactor
## 架构决策
### 决策 1复用现有连接
**决策**:复用 `storage_manager.py` 中的 `mysql_engine``redis_client`,不创建新的连接。
**理由**
- 避免重复创建连接池
- 保持配置一致性
- 简化降级逻辑
### 决策 2扩展 StorageManager
**决策**:在 `StorageManager` 中新增 analysis 表读写方法,与行情数据共用同一套降级逻辑。
**理由**
- 统一降级策略
- 减少代码重复
- 便于维护
### 决策 3表名前缀
**决策**analysis 表在 MySQL 中保持原名,不添加前缀。
**理由**
- 表名已通过 ORM 模型定义
- 避免与行情数据表冲突(行情表:`market_data`, `symbol_timestamps`, `scheduled_tasks`
## 数据流
```
┌─────────────────────────────────────────────────────────────┐
│ 应用层 │
│ app/api/futures_analysis.py ←→ app/services/cache.py │
│ ↓ │
│ StorageManager │
│ (storage_manager.py) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────┼─────────────────────┐
↓ ↓ ↓
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Redis │ │ MySQL │ │ SQLite │
│ (缓存) │ │(持久化) │ │ (兜底) │
└─────────┘ └─────────┘ └─────────┘
```
## 降级策略
### 读取流程
1. 检查 Redis 缓存,命中则返回
2. Redis 未命中,检查 MySQL 可用性
3. MySQL 可用则查询,结果回填 Redis
4. MySQL 不可用,降级到 SQLite
### 写入流程
1. 删除 Redis 缓存
2. 写入 MySQL事务
3. MySQL 成功后回填 Redis
4. MySQL 失败则写入 SQLite
## 数据迁移
启动时执行一次性迁移:
1. 检测 MySQL analysis 表是否为空
2. 为空则从 SQLite 读取全部数据
3. 批量写入 MySQL
4. 迁移完成后记录日志
## 缓存策略
| 表类型 | 缓存 TTL | 说明 |
|--------|----------|------|
| AI 分析结果 | 5 分钟 | 频繁读取,短期缓存 |
| 复盘计划 | 1 小时 | 每日更新,中期缓存 |
| 交易记录 | 不缓存 | 写入后不再修改 |
| 配置表 | 10 分钟 | 低频读取 |
## 兼容性
- ORM 模型定义不变
- API 接口签名不变
- SQLite 文件保留,降级时使用