# AI Provider Factory 缓存永不过期机制 **日期**: 2026-02-14 **类型**: Bug 修复 + 架构优化 **影响范围**: 后端 AI Provider 缓存系统 **严重程度**: 高(影响所有 AI 功能) --- ## 问题描述 ### 原问题 应用在运行 5 小时后,用户调用 AI 功能时出现错误: ``` 模型 {model_name} 不存在或未激活。 请检查:1) 模型是否已同步到数据库 2) 模型是否已启用(is_active=True) 3) Redis 缓存是否已初始化 ``` ### 根本原因 - **Redis 缓存 TTL 过短**: 原 TTL 为 3600 秒(1 小时) - **缓存过期后未自动重建**: 应用启动 5 小时后,缓存已过期且未刷新 ### 问题影响 - 所有 AI 相关功能(文生图、文生视频、配音等)不可用 - 需要手动重启应用才能恢复 --- ## 解决方案 ### 技术方案 采用 **永不过期 + 懒加载 + 手动刷新** 的组合方案: 1. ✅ **Redis 缓存永不过期**: 彻底解决缓存失效问题 2. ✅ **实现懒加载**: 缓存不存在时自动从数据库重建 3. ✅ **手动刷新接口**: 模型更新后可主动刷新缓存 4. ✅ **应用启动时强制刷新**: 确保数据最新 ### 方案演进 | 阶段 | 方案 | TTL | 问题 | |------|------|-----|------| | 阶段 1 | 原方案 | 1 小时 | ❌ 1 小时后服务不可用 | | 阶段 2 | 延长 TTL | 24 小时 | ⚠️ 24 小时后仍会过期 | | 阶段 3 | 永不过期 ✅ | 无 | ✅ 彻底解决缓存失效问题 | ### 为什么永不过期是最优解? **AI 模型配置的特点**: - 📊 **低频变更**: 通常几周/几个月才更新一次 - 🔒 **管理员操作**: 模型更新由管理员控制 - 📈 **高频读取**: 每次 AI 请求都需要查询模型配置 **永不过期的优势**: - ✅ **零缓存失效**: 彻底消除缓存过期问题 - ✅ **性能最优**: 所有请求都从 Redis 读取(< 1ms) - ✅ **架构简单**: 无需管理 TTL,无需定时任务 - ✅ **可控刷新**: 主动控制刷新时机 --- ## 关键改动 ### 1. 移除 CACHE_TTL ```diff class AIProviderFactory: - CACHE_TTL = 86400 # 缓存过期时间:24 小时 + # 注意:缓存永不过期,模型更新后需手动调用 refresh_cache() ``` ### 2. 使用 `redis.set()` 替代 `redis.setex()` ```diff # 应用启动时初始化 - await redis.setex(cls.CACHE_KEY, cls.CACHE_TTL, json.dumps(cache_dict)) + await redis.set(cls.CACHE_KEY, json.dumps(cache_dict)) # 懒加载重建 - await redis_client.setex(cls.CACHE_KEY, cls.CACHE_TTL, json.dumps(cache_dict)) + await redis_client.set(cls.CACHE_KEY, json.dumps(cache_dict)) ``` ### 3. 更新日志信息 ```diff - logger.info("✅ AI Provider Factory 缓存已初始化(Redis): 已加载 %d 个模型", len(cache_dict)) + logger.info("✅ AI Provider Factory 缓存已初始化(Redis,永不过期): 已加载 %d 个模型", len(cache_dict)) - logger.info("✅ 缓存重建成功: 已加载 %d 个模型", len(cache_dict)) + logger.info("✅ 缓存重建成功(永不过期): 已加载 %d 个模型", len(cache_dict)) ``` --- ## 验证测试 ### 测试 1: 懒加载验证 ```bash # 1. 清空缓存 docker exec jointo-server-redis redis-cli DEL "ai_models:provider_cache" # 2. 执行测试 docker exec jointo-server-app python tests/manual/test_cache_lazy_loading.py # 预期结果 ⚠️ Redis 缓存为空,正在从数据库重建缓存... ✅ 缓存重建成功(永不过期): 已加载 21 个模型 ``` ### 测试 2: 永不过期验证 ```bash # 检查 TTL docker exec jointo-server-redis redis-cli TTL "ai_models:provider_cache" # 返回: -1 (表示永不过期) ``` --- ## 运维指南 ### 何时需要刷新缓存? 当执行以下操作后,需要手动刷新缓存: 1. ✏️ 新增/删除 AI 模型 2. ✏️ 修改模型配置(provider、capabilities) 3. ✏️ 启用/禁用模型(`is_active`) ### 刷新缓存的方法 #### 方法 1: 代码中调用(推荐) ```python from app.services.ai_providers.factory import AIProviderFactory # 在修改模型后立即刷新 await AIProviderFactory.refresh_cache(db) ``` #### 方法 2: 重启应用 ```bash docker restart jointo-server-app ``` 应用启动时会自动刷新缓存。 #### 方法 3: 删除 Redis 键(触发懒加载) ```bash docker exec jointo-server-redis redis-cli DEL "ai_models:provider_cache" ``` 下次 AI 请求时会自动重建缓存。 --- ## 性能影响 ### 正常情况(缓存命中) - **Redis 查询**: 1 次 GET(< 1ms) - **数据库查询**: 0 次 - **性能**: 最优 ✅ ### 缓存重建(懒加载触发) - **数据库查询**: 1 次(< 100ms,21 个模型) - **频率**: 仅在缓存被手动删除或 Redis 重启后触发 --- ## 架构优势 1. ✅ **零缓存失效** - 永不过期,应用可长期运行 2. ✅ **性能最优** - 所有请求都从 Redis 读取 3. ✅ **架构简单** - 无需管理 TTL,无需定时任务 4. ✅ **可控刷新** - 管理员主动控制刷新时机 --- ## 风险与缓解 ### 风险 1: 忘记刷新缓存 **缓解**: - ✅ 代码规范:模型更新时自动调用 `refresh_cache()` - ✅ 应用重启:部署新版本时自动刷新 - ✅ 懒加载兜底:缓存被删除时自动重建 ### 风险 2: Redis 重启导致缓存丢失 **缓解**: - ✅ 懒加载:自动从数据库重建 - ✅ Redis 持久化:生产环境已启用 RDB/AOF --- ## 后续优化建议 ### 1. 自动刷新集成 在模型更新的 Service 层自动刷新缓存。 ### 2. 监控告警 添加 Prometheus 指标:`ai_cache_rebuilds_total` ### 3. 管理后台 添加缓存管理界面(查看状态、手动刷新) --- ## 相关文件 ### 修改文件 - `server/app/services/ai_providers/factory.py` ### 新增文件 - `server/tests/manual/test_cache_lazy_loading.py` --- ## 变更记录 - **2026-02-14 17:30**: 升级为永不过期方案 - **2026-02-14 17:25**: 初版(24h TTL + 懒加载) - **修复人员**: AI Assistant