feat(cache): 提升内存管理与监控能力

- 在CacheManager中添加健康监控系统,并提供详细的内存统计信息
- 使用新的memory_utils模块实现精确的内存估算
- 添加基于大小的缓存条目限制,以防止过大项目
- 通过去重内存计算优化缓存统计
- 在MultiLevelCache中添加过期条目的自动清理功能
- 增强批处理调度器缓存功能,支持LRU驱逐策略和内存追踪
- 更新配置以支持最大项目大小限制
- 添加全面的内存分析文档和工具

重大变更:CacheManager 的默认 TTL 参数现改为 None 而非 3600。数据库兼容层默认禁用缓存,以防止旧版代码过度使用缓存。
This commit is contained in:
Windpicker-owo
2025-11-03 15:18:00 +08:00
parent 99785d09ad
commit 4e2b598164
10 changed files with 1923 additions and 20 deletions

View File

@@ -19,6 +19,7 @@ from sqlalchemy import delete, insert, select, update
from src.common.database.core.session import get_db_session
from src.common.logger import get_logger
from src.common.memory_utils import estimate_size_smart
logger = get_logger("batch_scheduler")
@@ -65,6 +66,10 @@ class BatchStats:
last_batch_duration: float = 0.0
last_batch_size: int = 0
congestion_score: float = 0.0 # 拥塞评分 (0-1)
# 🔧 新增:缓存统计
cache_size: int = 0 # 缓存条目数
cache_memory_mb: float = 0.0 # 缓存内存占用MB
class AdaptiveBatchScheduler:
@@ -118,8 +123,11 @@ class AdaptiveBatchScheduler:
# 统计信息
self.stats = BatchStats()
# 简单的结果缓存
# 🔧 改进的结果缓存(带大小限制和内存统计)
self._result_cache: dict[str, tuple[Any, float]] = {}
self._cache_max_size = 1000 # 最大缓存条目数
self._cache_memory_estimate = 0 # 缓存内存估算(字节)
self._cache_size_map: dict[str, int] = {} # 每个缓存条目的大小
logger.info(
f"自适应批量调度器初始化: "
@@ -530,11 +538,53 @@ class AdaptiveBatchScheduler:
return None
def _set_cache(self, cache_key: str, result: Any) -> None:
"""设置缓存"""
"""设置缓存(改进版,带大小限制和内存统计)"""
import sys
# 🔧 检查缓存大小限制
if len(self._result_cache) >= self._cache_max_size:
# 首先清理过期条目
current_time = time.time()
expired_keys = [
k for k, (_, ts) in self._result_cache.items()
if current_time - ts >= self.cache_ttl
]
for k in expired_keys:
# 更新内存统计
if k in self._cache_size_map:
self._cache_memory_estimate -= self._cache_size_map[k]
del self._cache_size_map[k]
del self._result_cache[k]
# 如果还是太大清理最老的条目LRU
if len(self._result_cache) >= self._cache_max_size:
oldest_key = min(
self._result_cache.keys(),
key=lambda k: self._result_cache[k][1]
)
# 更新内存统计
if oldest_key in self._cache_size_map:
self._cache_memory_estimate -= self._cache_size_map[oldest_key]
del self._cache_size_map[oldest_key]
del self._result_cache[oldest_key]
logger.debug(f"缓存已满,淘汰最老条目: {oldest_key}")
# 🔧 使用准确的内存估算方法
try:
total_size = estimate_size_smart(cache_key) + estimate_size_smart(result)
self._cache_size_map[cache_key] = total_size
self._cache_memory_estimate += total_size
except Exception as e:
logger.debug(f"估算缓存大小失败: {e}")
# 使用默认值
self._cache_size_map[cache_key] = 1024
self._cache_memory_estimate += 1024
self._result_cache[cache_key] = (result, time.time())
async def get_stats(self) -> BatchStats:
"""获取统计信息"""
"""获取统计信息(改进版,包含缓存统计)"""
async with self._lock:
return BatchStats(
total_operations=self.stats.total_operations,
@@ -547,6 +597,9 @@ class AdaptiveBatchScheduler:
last_batch_duration=self.stats.last_batch_duration,
last_batch_size=self.stats.last_batch_size,
congestion_score=self.stats.congestion_score,
# 🔧 新增:缓存统计
cache_size=len(self._result_cache),
cache_memory_mb=self._cache_memory_estimate / (1024 * 1024),
)