auto_trade_sys/docs/common/内存优化_修复K线缓存.md
薇薇安 13a0e7d580 delete: 移除过时的文档与代码文件
删除了多个不再使用的文档和代码文件,包括交易更新推送、条件订单推送、REST API 文档、WebSocket API 文档及相关的策略分析文档。这些文件的移除有助于清理代码库,确保项目的整洁性与可维护性。
2026-02-20 17:49:00 +08:00

117 lines
3.8 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.

# 内存优化:修复 K 线缓存仍占用进程内存的问题
## 问题
即使配置了 RedisK 线数据仍然在进程内存中累积,导致内存持续增长。
## 根本原因
`kline_stream.py``_handle_message_async` 中,即使有 Redis代码仍然**先更新进程内存 `_kline_cache`**,然后再批量写入 Redis。这导致
1. **数据双重存储**:进程内存和 Redis 都有数据
2. **批量写入延迟**:在批量写入之前(最多 2 秒),数据一直留在进程内存
3. **写入失败时数据残留**:如果 Redis 写入失败,数据不会从进程内存删除
## 修复方案
### 1. 修改 K 线处理逻辑
**文件**: `trading_system/kline_stream.py`
**修改前**
- 先更新 `_kline_cache`(进程内存)
- 然后标记需要写入 Redis
- 批量写入 Redis 后删除进程内存中的 key
**修改后**
- **有 Redis 时**:直接从 Redis 读取当前数据,更新后写回 Redis**完全不写进程内存**
- **无 Redis 时**:才写进程内存(降级)
### 2. 限制 Redis 写入队列大小
`_redis_write_pending` 字典可能无限增长,添加了大小限制:
- 最多保留 **100 个**待写入项
- 超出时删除最旧的项
### 3. 删除重复定义
修复了代码中重复定义的变量(复制粘贴错误)。
## 修改详情
### `_handle_message_async` 方法
```python
# 修改前:总是先写进程内存
if key not in _kline_cache:
_kline_cache[key] = []
cache_list = _kline_cache[key]
# ... 更新 cache_list ...
# 然后标记写入 Redis
# 修改后:有 Redis 时只写 Redis
if self._redis_cache:
# 从 Redis 读取
existing = await self._redis_cache.get(rkey)
cache_list = list(existing) if existing else []
# 更新 cache_list
# 标记写入 Redis不写进程内存
else:
# 无 Redis 时才写进程内存
...
```
## 预期效果
- **进程内存占用大幅降低**:有 Redis 时K 线数据不再存储在进程内存中
- **内存增长停止**:不再有数据在进程内存中累积
## 需要重启服务
**重要**:修改后需要重启交易服务才能生效。
```bash
# 重启交易服务
pkill -f "python.*trading_system.main"
# 然后重新启动
```
## 验证
重启后,检查内存使用:
```bash
# 查看进程内存
ps aux | grep "trading_system.main" | awk '{print "MEM:", $4"%", "RSS:", $6/1024"MB"}'
# 或使用诊断脚本
cd backend
./检查内存问题.sh
```
正常情况下,有 Redis 时:
- K 线缓存进程内存应该**接近 0**(只有降级时的少量数据)
- 内存占用应该**稳定**,不再持续增长
## 补充Ticker24h / BookTicker 进程内存(本次一并修复)
**原因**Leader 进程里 `_ticker_24h_cache`、`_book_ticker_cache` 一直随 WS 消息更新,全市场 200+ 交易对常驻进程内存,且每次写 Redis 前还 `dict(_ticker_24h_cache)` 做完整拷贝,加重内存和分配。
**修改**`ticker_24h_stream.py` / `book_ticker_stream.py`
- **有 Redis 时**WS 只做「从 Redis 读出 → 合并本批/本条 → 写回 Redis」**不再更新** `_ticker_24h_cache` / `_book_ticker_cache`
- 进程内缓存只由 **refresh 循环**(每 2 秒从 Redis 拉一次)回填,并限制最多 **500 条**,避免无限增长。
- **无 Redis 时**:仍只写进程内存,并同样限制 500 条。
这样 Leader 不再在进程里常驻全量 ticker/bookTicker也不为写 Redis 做整份拷贝。
---
## 其他可能的内存增长源
若重启后内存仍涨,可再查:
1. **WebSocket 消息队列**:是否有任务/消息堆积
2. **日志**:日志文件与 Redis 日志 handler 是否过大
3. **数据库连接**:连接池是否及时释放
4. **其他缓存**`_price_cache`、`_symbol_info_cache` 等是否有上限并定期淘汰