# 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 文件保留,降级时使用