auto_trade_sys/docs/REDIS_CACHE_ANALYSIS.md
薇薇安 86b85c2609 a
2026-01-25 11:19:39 +08:00

263 lines
7.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 → ~1msRedis 本地访问)
- 降低 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 服务