feat(cache): 完善缓存系统实现及集成数据访问层

- 新增BrandCache与ModelCache,实现多级缓存和TTL管理
- 引入缓存预热机制,启动时自动加载品牌与型号数据
- 实现缓存穿透防护和数据库降级策略,提升服务稳定性
- 优化缓存键命名和数据序列化策略,增强管理便捷性
- 数据访问层新增缓存感知查询,品牌与型号仓库支持缓存优先
- 调整整体架构,增强组件解耦及依赖注入链路清晰度
- 提供详细的性能优化建议和故障排查指南
- 补充监控指标说明,便于后续运维与监控扩展
This commit is contained in:
yangy
2026-05-28 15:30:05 +08:00
parent 36c6ca2766
commit b2c11adeba
5 changed files with 1086 additions and 596 deletions
@@ -16,6 +16,13 @@
- [config.go](file://internal/config/config.go)
- [base64.go](file://pkg/encode/base64.go)
- [README.md](file://README.md)
- [redis.go](file://internal/cache/redis.go)
- [brand_cache.go](file://internal/cache/brand_cache.go)
- [model_cache.go](file://internal/cache/model_cache.go)
- [brand.go](file://internal/repository/brand.go)
- [model.go](file://internal/repository/model.go)
- [redis.go](file://internal/config/redis.go)
- [meilisearch.go](file://internal/config/meilisearch.go)
</cite>
## 目录
@@ -36,39 +43,50 @@
- 路由分组策略(/api/v1 与 /audio
- 中间件执行顺序与职责(CORS、日志、请求 ID)
- 各端点功能、参数与返回规范
- 依赖注入链:缓存与仓库实例的初始化与装配
- 最佳实践与性能优化建议
- 典型调用序列与中间件链路分析
## 项目结构
路由系统位于 internal/router,入口在 cmd/server/main.go,配合中间件、处理器、统一响应体与配置模块协同工作
路由系统位于 internal/router,入口在 cmd/server/main.go,配合中间件、处理器、统一响应体、缓存与仓库模块协同工作。**更新**:路由系统现已增强,负责初始化缓存和仓库实例,建立完整的依赖注入链
```mermaid
graph TB
subgraph "服务入口"
MAIN["cmd/server/main.go<br/>启动 HTTP 服务器"]
end
ENDSUBGRAPH
subgraph "路由与中间件"
ROUTER["internal/router/router.go<br/>路由工厂与分组注册"]
CORS["internal/middleware/cors.go<br/>CORS 中间件"]
LOGMW["internal/middleware/logger.go<br/>日志中间件"]
REQID["internal/middleware/request_id.go<br/>请求 ID 中间件"]
end
ENDSUBGRAPH
subgraph "缓存与仓库层"
BRANDCACHE["internal/cache/brand_cache.go<br/>品牌缓存"]
MODELCACHE["internal/cache/model_cache.go<br/>型号缓存"]
BRANDREPO["internal/repository/brand.go<br/>品牌仓库"]
MODELREPO["internal/repository/model.go<br/>型号仓库"]
ENDSUBGRAPH
subgraph "处理器层"
HEALTH["internal/handler/health.go"]
BRAND["internal/handler/brand.go"]
MODEL["internal/handler/model.go"]
MODELLIST["internal/handler/model_list.go"]
DEVICE["internal/handler/device.go"]
end
ENDSUBGRAPH
subgraph "基础设施"
RESP["internal/response/response.go<br/>统一响应体"]
ENCODE["pkg/encode/base64.go<br/>Base64 编解码"]
CONFIG["internal/config/config.go<br/>配置加载"]
end
ENDSUBGRAPH
MAIN --> ROUTER
ROUTER --> CORS
ROUTER --> LOGMW
ROUTER --> REQID
ROUTER --> BRANDCACHE
ROUTER --> MODELCACHE
ROUTER --> BRANDREPO
ROUTER --> MODELREPO
ROUTER --> HEALTH
ROUTER --> BRAND
ROUTER --> MODEL
@@ -83,40 +101,37 @@ BRAND --> ENCODE
MODEL --> ENCODE
```
图表来源
- [router.go:14-41](file://internal/router/router.go#L14-L41)
- [main.go:64-69](file://cmd/server/main.go#L64-L69)
- [cors.go:7-19](file://internal/middleware/cors.go#L7-L19)
- [logger.go:10-44](file://internal/middleware/logger.go#L10-L44)
- [request_id.go:20-29](file://internal/middleware/request_id.go#L20-L29)
- [health.go:14-18](file://internal/handler/health.go#L14-L18)
- [brand.go:26-49](file://internal/handler/brand.go#L26-L49)
- [model.go:26-49](file://internal/handler/model.go#L26-L49)
- [model_list.go:26-55](file://internal/handler/model_list.go#L26-L55)
- [device.go:26-84](file://internal/handler/device.go#L26-L84)
- [response.go:15-36](file://internal/response/response.go#L15-L36)
- [base64.go:44-51](file://pkg/encode/base64.go#L44-L51)
- [config.go:18-56](file://internal/config/config.go#L18-L56)
**图表来源**
- [router.go:16-52](file://internal/router/router.go#L16-L52)
- [main.go:59-70](file://cmd/server/main.go#L59-L70)
- [brand_cache.go:18-44](file://internal/cache/brand_cache.go#L18-L44)
- [model_cache.go:19-69](file://internal/cache/model_cache.go#L19-L69)
- [brand.go:14-52](file://internal/repository/brand.go#L14-L52)
- [model.go:14-79](file://internal/repository/model.go#L14-L79)
章节来源
- [router.go:14-41](file://internal/router/router.go#L14-L41)
- [main.go:22-95](file://cmd/server/main.go#L22-L95)
**章节来源**
- [router.go:16-52](file://internal/router/router.go#L16-L52)
- [main.go:25-101](file://cmd/server/main.go#L25-L101)
- [README.md:19-123](file://README.md#L19-L123)
## 核心组件
- 路由工厂函数 New:集中初始化 Gin 引擎、注册全局中间件、创建各处理器实例,并完成路由分组与注册。
- 路由工厂函数 New:集中初始化 Gin 引擎、注册全局中间件、创建各处理器实例,并完成路由分组与注册。**更新**:现负责初始化缓存和仓库实例,建立完整的依赖注入链。
- 路由分组:
- /api/v1:版本化健康检查端点
- /audio:音频设备相关业务端点
- 中间件链:Recovery -> RequestID -> Logger -> CORS
- 统一响应体:OK/Fail/BadRequest/InternalError,保证一致的返回结构
- **新增**:依赖注入链路
- 缓存层:BrandCache、ModelCache
- 仓库层:BrandRepository、ModelRepository
- 处理器层:HealthHandler、BrandHandler、ModelHandler、ModelListHandler、DeviceHandler
章节来源
- [router.go:14-41](file://internal/router/router.go#L14-L41)
**章节来源**
- [router.go:16-52](file://internal/router/router.go#L16-L52)
- [response.go:15-36](file://internal/response/response.go#L15-L36)
## 架构总览
下图展示了从请求进入至响应返回的完整链路,包括中间件执行顺序与处理器调用。
下图展示了从请求进入至响应返回的完整链路,包括中间件执行顺序、依赖注入与处理器调用。
```mermaid
sequenceDiagram
@@ -139,8 +154,8 @@ H-->>G : "写入响应"
G-->>C : "HTTP 响应"
```
图表来源
- [router.go:14-41](file://internal/router/router.go#L14-L41)
**图表来源**
- [router.go:16-52](file://internal/router/router.go#L16-L52)
- [logger.go:10-44](file://internal/middleware/logger.go#L10-L44)
- [request_id.go:20-29](file://internal/middleware/request_id.go#L20-L29)
- [cors.go:7-19](file://internal/middleware/cors.go#L7-L19)
@@ -149,14 +164,44 @@ G-->>C : "HTTP 响应"
### 路由工厂与中间件链
- 工厂函数 New 创建 Gin 引擎并按顺序注册中间件,确保异常恢复、请求追踪、日志记录与跨域支持贯穿所有路由。
- **更新**:在处理器创建前完成缓存和仓库实例的初始化,形成完整的依赖注入链。
- 中间件顺序决定日志统计的粒度与错误兜底能力,建议保持现有顺序以获得最佳可观测性与稳定性。
章节来源
- [router.go:14-19](file://internal/router/router.go#L14-L19)
**章节来源**
- [router.go:16-52](file://internal/router/router.go#L16-L52)
- [logger.go:10-44](file://internal/middleware/logger.go#L10-L44)
- [request_id.go:20-29](file://internal/middleware/request_id.go#L20-L29)
- [cors.go:7-19](file://internal/middleware/cors.go#L7-L19)
### 依赖注入链详解
#### 缓存层初始化
- BrandCache:管理品牌全量数据缓存,键为 "brand:all"TTL 30 分钟
- ModelCache:管理型号数据缓存,支持按品牌和全量两种缓存策略
- 缓存键空间:
- 品牌:brand:all
- 型号按品牌:model:brand:{brand}
- 型号全量:model:all
#### 仓库层初始化
- BrandRepository:封装品牌数据访问,支持缓存优先策略
- ModelRepository:封装型号数据访问,支持多维度缓存策略
- 仓库层具备缓存降级能力,Redis 异常时自动回退到数据库
#### 处理器层初始化
- HealthHandler:健康检查处理器
- BrandHandler:品牌列表处理器,依赖 BrandRepository
- ModelHandler:型号列表处理器,依赖 ModelRepository
- ModelListHandler:型号搜索处理器,依赖 Meilisearch 客户端
- DeviceHandler:设备信息上报处理器,直接依赖 Redis 客户端
**章节来源**
- [router.go:23-36](file://internal/router/router.go#L23-L36)
- [brand_cache.go:13-44](file://internal/cache/brand_cache.go#L13-L44)
- [model_cache.go:13-69](file://internal/cache/model_cache.go#L13-L69)
- [brand.go:14-52](file://internal/repository/brand.go#L14-L52)
- [model.go:14-79](file://internal/repository/model.go#L14-L79)
### 路由分组与端点清单
- /api/v1 分组
- GET /api/v1/health → 健康检查
@@ -166,8 +211,8 @@ G-->>C : "HTTP 响应"
- GET /audio/modelList → 模型搜索列表
- GET /audio/reportDevInfo → 设备信息上报
章节来源
- [router.go:27-38](file://internal/router/router.go#L27-L38)
**章节来源**
- [router.go:38-49](file://internal/router/router.go#L38-L49)
- [README.md:83-110](file://README.md#L83-L110)
### 中间件详解
@@ -177,21 +222,21 @@ G-->>C : "HTTP 响应"
- 对预检请求直接返回状态码
- 放行后续处理器执行
章节来源
**章节来源**
- [cors.go:7-19](file://internal/middleware/cors.go#L7-L19)
#### 日志中间件
- 记录请求路径、方法、耗时、状态码、客户端 IP、请求 ID、查询参数与错误信息
- 按状态码分级输出(info/warn/error
章节来源
**章节来源**
- [logger.go:10-44](file://internal/middleware/logger.go#L10-L44)
#### 请求 ID 中间件
- 从请求头读取或生成唯一标识,注入上下文并回传给客户端
- 用于全链路追踪与问题定位
章节来源
**章节来源**
- [request_id.go:20-29](file://internal/middleware/request_id.go#L20-L29)
### 处理器与端点行为
@@ -201,7 +246,7 @@ G-->>C : "HTTP 响应"
- 参数:无
- 返回:统一响应体,data 包含状态字段
章节来源
**章节来源**
- [health.go:14-18](file://internal/handler/health.go#L14-L18)
- [response.go:15-21](file://internal/response/response.go#L15-L21)
@@ -211,11 +256,12 @@ G-->>C : "HTTP 响应"
- brandName:品牌名称(可选)
- base64Resp:是否返回 Base64 编码结果(默认 true
- 行为:
- 调用仓库层查询
- 调用仓库层查询,优先使用缓存
- 缓存未命中时回退到数据库
- 可选地对结果进行 JSON 编码后返回
章节来源
- [brand.go:26-49](file://internal/handler/brand.go#L26-L49)
**章节来源**
- [brand.go:25-48](file://internal/handler/brand.go#L25-L48)
- [base64.go:44-51](file://pkg/encode/base64.go#L44-L51)
#### 型号列表 /audio/getModel
@@ -225,11 +271,12 @@ G-->>C : "HTTP 响应"
- modelName:型号名称(可选)
- base64Resp:是否返回 Base64 编码结果(默认 true
- 行为:
- 调用仓库层查询
- 调用仓库层查询,支持多种查询策略
- 缓存优先,异常时回退到数据库
- 可选地对结果进行 JSON 编码后返回
章节来源
- [model.go:26-49](file://internal/handler/model.go#L26-L49)
**章节来源**
- [model.go:25-49](file://internal/handler/model.go#L25-L49)
- [base64.go:44-51](file://pkg/encode/base64.go#L44-L51)
#### 模型搜索列表 /audio/modelList
@@ -242,8 +289,8 @@ G-->>C : "HTTP 响应"
- 调用搜索引擎客户端查询
- 可选地对结果进行 JSON 编码后返回
章节来源
- [model_list.go:26-55](file://internal/handler/model_list.go#L26-L55)
**章节来源**
- [model_list.go:26-56](file://internal/handler/model_list.go#L26-L56)
- [base64.go:44-51](file://pkg/encode/base64.go#L44-L51)
#### 设备信息上报 /audio/reportDevInfo
@@ -254,10 +301,10 @@ G-->>C : "HTTP 响应"
- ver:版本号(可选)
- 行为:
- 校验必填参数
- 组装设备信息并写入缓存
- 组装设备信息并写入 Redis Hash
- 返回统一响应体
章节来源
**章节来源**
- [device.go:26-84](file://internal/handler/device.go#L26-L84)
### 统一响应体
@@ -266,13 +313,15 @@ G-->>C : "HTTP 响应"
- BadRequest:客户端错误
- InternalError:服务端错误
章节来源
**章节来源**
- [response.go:15-36](file://internal/response/response.go#L15-L36)
### 路由注册流程(工厂模式)
- 初始化 Gin 引擎
- 注册全局中间件(Recovery、RequestID、Logger、CORS
- 实例化各处理器(数据库/搜索引擎/缓存客户端注入
- **新增**:初始化缓存实例(BrandCache、ModelCache
- **新增**:初始化仓库实例(BrandRepository、ModelRepository
- **新增**:初始化处理器实例(注入相应依赖)
- 创建路由分组并注册端点
- 返回引擎供 HTTP 服务器使用
@@ -283,7 +332,9 @@ Init --> UseRecovery["注册 Recovery 中间件"]
UseRecovery --> UseReqID["注册 RequestID 中间件"]
UseReqID --> UseLogger["注册 Logger 中间件"]
UseLogger --> UseCORS["注册 CORS 中间件"]
UseCORS --> NewHandlers["创建各处理器实例"]
UseCORS --> NewCache["初始化缓存实例<br/>BrandCache, ModelCache"]
NewCache --> NewRepo["初始化仓库实例<br/>BrandRepository, ModelRepository"]
NewRepo --> NewHandlers["创建各处理器实例<br/>注入相应依赖"]
NewHandlers --> GroupV1["创建 /api/v1 分组"]
GroupV1 --> RegHealth["注册 /api/v1/health"]
NewHandlers --> GroupAudio["创建 /audio 分组"]
@@ -294,12 +345,14 @@ GroupAudio --> RegDevice["注册 /audio/reportDevInfo"]
RegDevice --> ReturnEngine["返回引擎"]
```
图表来源
- [router.go:14-41](file://internal/router/router.go#L14-L41)
**图表来源**
- [router.go:16-52](file://internal/router/router.go#L16-L52)
## 依赖关系分析
- 路由层依赖中间件层与处理器层
- 处理器层依赖响应体编码工具
- **更新**处理器层依赖响应体编码工具与底层存储
- **更新**:仓库层依赖缓存层与数据库连接
- **更新**:缓存层依赖 Redis 客户端
- 服务启动层负责装配配置、数据库、搜索引擎与缓存,并将它们注入路由工厂
```mermaid
@@ -308,6 +361,8 @@ MAIN["cmd/server/main.go"] --> ROUTER["internal/router/router.go"]
ROUTER --> MW_REQID["internal/middleware/request_id.go"]
ROUTER --> MW_LOG["internal/middleware/logger.go"]
ROUTER --> MW_CORS["internal/middleware/cors.go"]
ROUTER --> CACHE["internal/cache/*"]
ROUTER --> REPO["internal/repository/*"]
ROUTER --> H_HEALTH["internal/handler/health.go"]
ROUTER --> H_BRAND["internal/handler/brand.go"]
ROUTER --> H_MODEL["internal/handler/model.go"]
@@ -320,22 +375,32 @@ H_DEVICE --> RESP
H_MODELLIST --> ENCODE["pkg/encode/base64.go"]
H_BRAND --> ENCODE
H_MODEL --> ENCODE
CACHE --> REDIS["Redis 客户端"]
REPO --> DB["MySQL 数据库"]
```
图表来源
- [main.go:64](file://cmd/server/main.go#L64)
- [router.go:21-25](file://internal/router/router.go#L21-L25)
**图表来源**
- [main.go:59-70](file://cmd/server/main.go#L59-L70)
- [router.go:23-36](file://internal/router/router.go#L23-L36)
- [response.go:15-36](file://internal/response/response.go#L15-L36)
- [base64.go:44-51](file://pkg/encode/base64.go#L44-L51)
章节来源
- [main.go:32-62](file://cmd/server/main.go#L32-L62)
- [router.go:14-41](file://internal/router/router.go#L14-L41)
**章节来源**
- [main.go:25-101](file://cmd/server/main.go#L25-L101)
- [router.go:16-52](file://internal/router/router.go#L16-L52)
## 性能考量
- 中间件顺序与开销
- Recovery 放在首位,避免重复包裹
- RequestID/CORS/LR 等轻量中间件顺序合理,尽量减少阻塞
- **新增**:缓存策略优化
- 品牌全量缓存:brand:allTTL 30 分钟
- 型号按品牌缓存:model:brand:{brand}TTL 30 分钟
- 型号全量缓存:model:allTTL 30 分钟
- 缓存降级:Redis 异常时自动回退到数据库
- **新增**:预热机制
- 启动时从数据库加载数据到 Redis
- 品牌和型号分别进行全量预热
- 日志中间件
- 建议仅在必要时记录查询参数,避免大对象日志
- 控制错误日志频率,防止雪崩
@@ -348,6 +413,13 @@ H_MODEL --> ENCODE
- 健康检查失败
- 检查 /api/v1/health 是否可达
- 关注日志中间件输出的状态码与耗时
- **新增**:缓存相关问题
- Redis 连接失败:检查 Redis 配置与网络连通性
- 缓存数据异常:验证缓存键空间与 TTL 设置
- 缓存降级:确认数据库连接正常
- **新增**:仓库层问题
- SQL 查询超时:检查数据库索引与查询条件
- 仓库初始化失败:确认依赖的缓存和数据库连接正常
- CORS 相关问题
- 确认浏览器预检请求已正确处理
- 核对允许的方法与头字段
@@ -359,14 +431,14 @@ H_MODEL --> ENCODE
- 编码异常
- base64Resp 开启时确认客户端解析逻辑
章节来源
**章节来源**
- [logger.go:33-43](file://internal/middleware/logger.go#L33-L43)
- [request_id.go:22-27](file://internal/middleware/request_id.go#L22-L27)
- [cors.go:9-12](file://internal/middleware/cors.go#L9-L12)
- [response.go:23-36](file://internal/response/response.go#L23-L36)
## 结论
本路由系统采用清晰的工厂模式与中间件链设计,结合版本化与业务域分组,具备良好的可维护性与扩展性。遵循现有中间件顺序与统一响应体规范,有助于提升可观测性与稳定性。建议在新增端点时严格复用现有中间件与响应体,确保一致性与性能。
本路由系统采用清晰的工厂模式与中间件链设计,结合版本化与业务域分组,具备良好的可维护性与扩展性。**更新**:路由系统现已增强,负责初始化缓存和仓库实例,建立了完整的依赖注入链,提升了系统的整体性能与可靠性。遵循现有中间件顺序与统一响应体规范,有助于提升可观测性与稳定性。建议在新增端点时严格复用现有中间件与响应体,确保一致性与性能。
## 附录
@@ -403,12 +475,12 @@ H_MODEL --> ENCODE
- ver:字符串(可选)
- 返回:统一响应体
章节来源
- [router.go:29](file://internal/router/router.go#L29)
- [brand.go:27-28](file://internal/handler/brand.go#L27-L28)
- [model.go:27-28](file://internal/handler/model.go#L27-L28)
- [model_list.go:27-35](file://internal/handler/model_list.go#L27-L35)
- [device.go:27-28](file://internal/handler/device.go#L27-L28)
**章节来源**
- [router.go:38-49](file://internal/router/router.go#L38-L49)
- [brand.go:25-48](file://internal/handler/brand.go#L25-L48)
- [model.go:25-49](file://internal/handler/model.go#L25-L49)
- [model_list.go:26-56](file://internal/handler/model_list.go#L26-L56)
- [device.go:26-84](file://internal/handler/device.go#L26-L84)
### 中间件链路分析(序列图)
```mermaid
@@ -430,8 +502,54 @@ Handler-->>Engine : "写入响应"
Engine-->>Client : "响应"
```
图表来源
- [router.go:16-19](file://internal/router/router.go#L16-L19)
**图表来源**
- [router.go:18-21](file://internal/router/router.go#L18-L21)
- [logger.go:16](file://internal/middleware/logger.go#L16)
- [request_id.go:28](file://internal/middleware/request_id.go#L28)
- [cors.go:18](file://internal/middleware/cors.go#L18)
- [cors.go:18](file://internal/middleware/cors.go#L18)
### 依赖注入链路图
```mermaid
graph TB
subgraph "应用启动"
MAIN["cmd/server/main.go<br/>warmUpCache()"]
ENDSUBGRAPH
subgraph "路由工厂"
ROUTER["internal/router/router.go<br/>New()"]
ENDSUBGRAPH
subgraph "缓存层"
BC["BrandCache<br/>brand:all"]
MC["ModelCache<br/>model:brand:, model:all"]
ENDSUBGRAPH
subgraph "仓库层"
BR["BrandRepository<br/>缓存+数据库"]
MR["ModelRepository<br/>缓存+数据库"]
ENDSUBGRAPH
subgraph "处理器层"
HH["HealthHandler"]
BH["BrandHandler"]
MH["ModelHandler"]
MLH["ModelListHandler"]
DH["DeviceHandler"]
ENDSUBGRAPH
MAIN --> BC
MAIN --> MC
MAIN --> BR
MAIN --> MR
ROUTER --> BC
ROUTER --> MC
ROUTER --> BR
ROUTER --> MR
ROUTER --> BH
ROUTER --> MH
ROUTER --> MLH
ROUTER --> DH
```
**图表来源**
- [main.go:103-130](file://cmd/server/main.go#L103-L130)
- [router.go:23-36](file://internal/router/router.go#L23-L36)
- [brand_cache.go:18-44](file://internal/cache/brand_cache.go#L18-L44)
- [model_cache.go:19-69](file://internal/cache/model_cache.go#L19-L69)
- [brand.go:14-52](file://internal/repository/brand.go#L14-L52)
- [model.go:14-79](file://internal/repository/model.go#L14-L79)