# Redis 缓存优化分析 ## 当前缓存情况 ### 1. 内存缓存(进程内) - **交易对信息缓存** (`_symbol_info_cache`): 缓存交易对的精度、最小数量等信息 - **价格缓存** (`_price_cache`): 缓存 WebSocket 价格数据,TTL 60秒 - **配置缓存**: 数据库配置的内存缓存 ### 2. 频繁的 API 调用 - `get_symbol_info()`: 每次下单前调用,获取交易对精度信息 - `get_ticker_24h()`: 频繁获取价格信息 - `get_klines()`: 每次扫描时获取 K 线数据用于技术指标计算 - `futures_exchange_info()`: 获取交易对信息 ## Redis 缓存优化方案 ### 高优先级(显著提升性能) #### 1. 交易对信息缓存 ⭐⭐⭐⭐⭐ **当前问题:** - 每次下单前都要调用 `get_symbol_info()` 获取精度信息 - 交易对信息变化频率低,但每次都要 API 请求 **Redis 缓存方案:** ```python # 缓存键: symbol_info:{symbol} # TTL: 1小时(交易对信息很少变化) # 数据结构: Hash { "quantityPrecision": 3, "pricePrecision": 2, "minQty": 0.001, "stepSize": 0.001, "minNotional": 5.0 } ``` **性能提升:** - 减少 API 调用:从每次下单 1 次 API 调用 → 0 次(缓存命中) - 降低延迟:从 ~100ms → ~1ms(Redis 本地访问) - 降低 API 频率限制风险 #### 2. K 线数据缓存 ⭐⭐⭐⭐ **当前问题:** - 每次市场扫描都要获取 50 根 K 线数据 - 相同时间周期的 K 线数据在短时间内不会变化 - 扫描多个交易对时重复获取相同数据 **Redis 缓存方案:** ```python # 缓存键: klines:{symbol}:{interval}:{limit} # TTL: 根据 interval 动态设置(1m=10秒, 5m=30秒, 1h=5分钟) # 数据结构: List (JSON 序列化) ``` **性能提升:** - 减少 API 调用:扫描 10 个交易对,从 10 次 → 0-2 次(缓存命中) - 加速市场扫描:从 ~5-10 秒 → ~1-2 秒 - 降低 API 频率限制风险 #### 3. 24小时行情数据缓存 ⭐⭐⭐⭐ **当前问题:** - `get_all_tickers_24h()` 每次扫描都调用 - 数据更新频率相对较低(24小时统计) **Redis 缓存方案:** ```python # 缓存键: ticker_24h:{symbol} 或 ticker_24h:all # TTL: 30秒(24小时统计数据更新不频繁) # 数据结构: Hash 或 String (JSON) ``` **性能提升:** - 减少 API 调用:从每次扫描 1 次批量请求 → 0 次(缓存命中) - 加速市场扫描:从 ~2-3 秒 → ~0.1 秒 - 降低 API 频率限制风险 ### 中优先级(适度提升性能) #### 4. 配置信息缓存 ⭐⭐⭐ **当前问题:** - 每次获取配置都要查询数据库 - 配置变化频率低 **Redis 缓存方案:** ```python # 缓存键: config:{key} # TTL: 5分钟(配置可能通过前端修改) # 数据结构: String ``` **性能提升:** - 减少数据库查询:从每次获取配置 1 次查询 → 0 次(缓存命中) - 降低数据库负载 #### 5. 市场扫描结果缓存 ⭐⭐ **当前问题:** - 扫描结果可以短期缓存,避免重复扫描 **Redis 缓存方案:** ```python # 缓存键: scan_result:top_symbols # TTL: 30秒(扫描间隔内可以复用) # 数据结构: List (JSON) ``` **性能提升:** - 减少重复计算:在扫描间隔内可以复用结果 ### 低优先级(提升有限) #### 6. 价格缓存(已有 WebSocket) **当前情况:** - 已有 WebSocket 实时价格推送 - 内存缓存已足够 **建议:** - 保持现有内存缓存 - Redis 可以作为 WebSocket 的备份(如果 WebSocket 断开) ## 性能提升评估 ### 预期提升 | 场景 | 当前延迟 | Redis 缓存后 | 提升 | |------|---------|-------------|------| | 下单前获取交易对信息 | ~100ms | ~1ms | **99%** | | 市场扫描(10个交易对) | ~5-10秒 | ~1-2秒 | **70-80%** | | 获取 K 线数据 | ~200ms/次 | ~1ms/次 | **99.5%** | | 获取 24h 行情 | ~2-3秒 | ~0.1秒 | **95%** | ### API 调用减少 | API 端点 | 当前频率 | Redis 缓存后 | 减少 | |---------|---------|-------------|------| | `futures_exchange_info` | 每次下单 | 每小时 1 次 | **99%+** | | `futures_klines` | 每次扫描 | 每 5 分钟 1 次 | **90%+** | | `futures_ticker` | 每次扫描 | 每 30 秒 1 次 | **95%+** | ### 风险降低 1. **API 频率限制风险**:显著降低 2. **网络延迟影响**:大幅减少 3. **系统响应速度**:明显提升 ## 实现建议 ### 1. 使用 `aioredis` 库(异步 Redis 客户端) ```python pip install aioredis ``` ### 2. 创建 Redis 缓存管理器 ```python # trading_system/redis_cache.py import aioredis import json from typing import Optional, Dict, Any import logging logger = logging.getLogger(__name__) class RedisCache: def __init__(self, redis_url: str = "redis://localhost:6379"): self.redis_url = redis_url self.redis: Optional[aioredis.Redis] = None async def connect(self): """连接 Redis""" try: self.redis = await aioredis.from_url(self.redis_url) await self.redis.ping() logger.info("✓ Redis 连接成功") except Exception as e: logger.warning(f"Redis 连接失败: {e},将使用内存缓存") self.redis = None async def get(self, key: str) -> Optional[Any]: """获取缓存""" if not self.redis: return None try: data = await self.redis.get(key) if data: return json.loads(data) except Exception as e: logger.debug(f"Redis 获取失败 {key}: {e}") return None async def set(self, key: str, value: Any, ttl: int = 3600): """设置缓存""" if not self.redis: return False try: await self.redis.setex(key, ttl, json.dumps(value)) return True except Exception as e: logger.debug(f"Redis 设置失败 {key}: {e}") return False async def close(self): """关闭连接""" if self.redis: await self.redis.close() ``` ### 3. 集成到现有代码 **修改 `binance_client.py`:** ```python from .redis_cache import RedisCache class BinanceClient: def __init__(self, ...): # ... 现有代码 ... self.redis_cache = RedisCache() async def connect(self, ...): # ... 现有代码 ... await self.redis_cache.connect() async def get_symbol_info(self, symbol: str): # 先查 Redis 缓存 cache_key = f"symbol_info:{symbol}" cached = await self.redis_cache.get(cache_key) if cached: return cached # 缓存未命中,调用 API info = await self._fetch_symbol_info(symbol) # 写入 Redis 缓存(TTL: 1小时) if info: await self.redis_cache.set(cache_key, info, ttl=3600) return info ``` ## 总结 ### 推荐实施优先级 1. **交易对信息缓存** ⭐⭐⭐⭐⭐ - 立即实施,效果最明显 2. **K 线数据缓存** ⭐⭐⭐⭐ - 高优先级,显著提升扫描速度 3. **24小时行情缓存** ⭐⭐⭐⭐ - 高优先级,减少批量请求 4. **配置信息缓存** ⭐⭐⭐ - 中优先级,适度提升 5. **市场扫描结果缓存** ⭐⭐ - 低优先级,提升有限 ### 预期效果 - **API 调用减少**: 70-90% - **系统响应速度**: 提升 70-80% - **API 频率限制风险**: 显著降低 - **系统稳定性**: 提升(减少网络依赖) ### 注意事项 1. **缓存一致性**: 需要合理设置 TTL,确保数据及时更新 2. **Redis 可用性**: 需要处理 Redis 不可用的情况(降级到内存缓存) 3. **内存使用**: Redis 内存使用需要监控 4. **部署复杂度**: 需要部署和维护 Redis 服务