263 lines
7.6 KiB
Markdown
263 lines
7.6 KiB
Markdown
# 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 服务
|