Files
backend/.qoder/repowiki/zh/content/外部集成/Redis缓存集成.md

220 lines
9.0 KiB
Markdown
Raw Normal View History

# Redis缓存集成
<cite>
**本文档引用的文件**
- [redis.go](file://pkg/redis/redis.go)
- [manager.go](file://pkg/redis/manager.go)
- [config.go](file://pkg/config/config.go)
- [jwt.go](file://pkg/auth/jwt.go)
- [captcha_service.go](file://internal/service/captcha_service.go)
- [verification_service.go](file://internal/service/verification_service.go)
</cite>
## 目录
1. [项目结构](#项目结构)
2. [Redis客户端封装设计](#redis客户端封装设计)
3. [连接池与健康检查机制](#连接池与健康检查机制)
4. [缓存操作实现原理](#缓存操作实现原理)
5. [JWT令牌存储应用](#jwt令牌存储应用)
6. [会话管理与验证码应用](#会话管理与验证码应用)
7. [限流控制实现](#限流控制实现)
8. [缓存问题预防策略](#缓存问题预防策略)
9. [高可用架构支持](#高可用架构支持)
## 项目结构
```mermaid
graph TB
subgraph "pkg"
Redis[redis]
Config[config]
Auth[auth]
end
subgraph "internal"
Service[service]
Repository[repository]
end
Redis --> Service
Config --> Redis
Auth --> Service
Service --> Repository
```
**图示来源**
- [redis.go](file://pkg/redis/redis.go#L1-L175)
- [config.go](file://pkg/config/config.go#L1-L305)
- [captcha_service.go](file://internal/service/captcha_service.go#L1-L166)
## Redis客户端封装设计
CarrotSkin项目中的Redis客户端封装采用分层设计模式通过`Client`结构体对`github.com/redis/go-redis/v9`库进行包装提供更简洁的API接口。`Client`结构体包含`*redis.Client`指针和`*zap.Logger`日志记录器,实现了日志记录和错误处理的统一管理。
封装设计遵循单一职责原则将Redis连接管理、操作执行和日志记录分离。通过`New`函数创建客户端实例时,会根据配置参数初始化连接,并执行连接测试,确保连接的可用性。这种设计模式提高了代码的可维护性和可测试性。
**本节来源**
- [redis.go](file://pkg/redis/redis.go#L15-L52)
- [manager.go](file://pkg/redis/manager.go#L11-L18)
## 连接池与健康检查机制
Redis连接池配置在`RedisConfig`结构体中定义,包含`Host``Port``Password``Database``PoolSize`等关键参数。连接池大小通过`PoolSize`字段配置默认值为10可根据实际负载情况进行调整。
健康检查机制在客户端初始化时实现,通过`Ping`命令测试连接可用性。使用`context.WithTimeout`设置5秒超时防止连接测试阻塞主线程。连接成功后会记录包含主机、端口和数据库信息的日志便于监控和故障排查。
```mermaid
sequenceDiagram
participant App as 应用程序
participant Manager as Redis管理器
participant Client as Redis客户端
participant Redis as Redis服务器
App->>Manager : Init(cfg, logger)
Manager->>Client : New(cfg, logger)
Client->>Redis : Ping()
Redis-->>Client : PONG
Client-->>Manager : 返回客户端实例
Manager-->>App : 初始化完成
```
**图示来源**
- [redis.go](file://pkg/redis/redis.go#L22-L47)
- [config.go](file://pkg/config/config.go#L49-L56)
**本节来源**
- [redis.go](file://pkg/redis/redis.go#L22-L47)
- [config.go](file://pkg/config/config.go#L49-L56)
## 缓存操作实现原理
缓存操作通过`Client`结构体的方法实现,包括`Set``Get``Del``Exists``Expire`等基本操作。这些方法直接代理到底层`redis.Client`的对应方法保持了与原生API的一致性。
`Set`方法接受`context.Context`、键、值和过期时间参数,支持设置键值对及其过期时间。`Get`方法返回字符串值和错误,通过`Nil`方法可以判断键不存在的情况。`Expire`方法用于修改现有键的过期时间,支持动态调整缓存策略。
```mermaid
classDiagram
class Client {
+*redis.Client
+*zap.Logger
+Set(ctx, key, value, expiration) error
+Get(ctx, key) (string, error)
+Del(ctx, keys) error
+Exists(ctx, keys) (int64, error)
+Expire(ctx, key, expiration) error
+Nil(err) bool
}
class RedisConfig {
+Host string
+Port int
+Password string
+Database int
+PoolSize int
}
Client --> RedisConfig : 使用
```
**图示来源**
- [redis.go](file://pkg/redis/redis.go#L60-L83)
- [config.go](file://pkg/config/config.go#L49-L56)
**本节来源**
- [redis.go](file://pkg/redis/redis.go#L60-L83)
## JWT令牌存储应用
JWT令牌存储利用Redis作为临时存储介质通过`Set`方法将令牌与用户信息关联存储。令牌的过期时间与JWT的有效期保持一致确保令牌在Redis中的生命周期与JWT一致。
`jwt.go`JWT服务生成令牌后可以通过Redis存储令牌的元数据如用户ID、角色等信息。这种设计实现了无状态认证与有状态缓存的结合既保持了JWT的无状态特性又可以通过Redis快速验证令牌的有效性。
```mermaid
sequenceDiagram
participant User as 用户
participant Auth as 认证服务
participant Redis as Redis缓存
User->>Auth : 登录请求
Auth->>Auth : 生成JWT令牌
Auth->>Redis : Set(token, userInfo, expireTime)
Redis-->>Auth : 存储成功
Auth-->>User : 返回JWT令牌
User->>Auth : 带JWT的请求
Auth->>Redis : Get(token)
Redis-->>Auth : 返回用户信息
Auth-->>User : 处理请求
```
**图示来源**
- [jwt.go](file://pkg/auth/jwt.go#L32-L52)
- [redis.go](file://pkg/redis/redis.go#L60-L63)
**本节来源**
- [jwt.go](file://pkg/auth/jwt.go#L32-L52)
- [redis.go](file://pkg/redis/redis.go#L60-L63)
## 会话管理与验证码应用
会话管理通过Redis存储会话数据每个会话以唯一ID作为键会话数据作为值进行存储。验证码应用在`captcha_service.go`中实现,使用`redisKeyPrefix = "captcha:"`作为键前缀,确保验证码数据的隔离性。
验证码生成时将滑块的目标坐标等验证信息序列化后存储到Redis设置300秒过期时间。验证时从Redis获取原始数据与用户输入进行比对验证成功后立即删除Redis记录防止重复使用。
```mermaid
flowchart TD
Start([生成验证码]) --> Generate["生成滑块坐标(Tx,Ty)"]
Generate --> Serialize["序列化为JSON"]
Serialize --> Store["Set(captcha:id, json, 300s)"]
Store --> Return["返回验证码数据"]
Verify([验证验证码]) --> Get["Get(captcha:id)"]
Get --> Check{"是否存在?"}
Check --> |否| Expired["返回: 验证码已过期"]
Check --> |是| Parse["解析JSON数据"]
Parse --> Validate["验证用户输入"]
Validate --> Delete["Del(captcha:id)"]
Delete --> Result["返回验证结果"]
```
**图示来源**
- [captcha_service.go](file://internal/service/captcha_service.go#L75-L135)
- [redis.go](file://pkg/redis/redis.go#L60-L63)
**本节来源**
- [captcha_service.go](file://internal/service/captcha_service.go#L75-L135)
- [redis.go](file://pkg/redis/redis.go#L144-L146)
## 限流控制实现
限流控制在`verification_service.go`中实现通过Redis的`Set`命令设置频率限制。使用`codeType``email`组合生成限流键,值设为"1",过期时间由`CodeRateLimit`常量定义。
当用户请求发送验证码时先检查限流键是否存在若存在则拒绝请求防止频繁发送。这种基于Redis的限流机制简单高效能够有效防止恶意刷屏攻击保护系统资源。
```mermaid
flowchart LR
Request[发送验证码请求] --> Check["Exists(verification:rate:email)"]
Check --> |存在| Reject[拒绝请求]
Check --> |不存在| Send[发送验证码]
Send --> Set["Set(verification:rate:email, 1, 60s)"]
Set --> Response[返回响应]
```
**图示来源**
- [verification_service.go](file://internal/service/verification_service.go#L58-L67)
- [redis.go](file://pkg/redis/redis.go#L75-L78)
**本节来源**
- [verification_service.go](file://internal/service/verification_service.go#L58-L67)
## 缓存问题预防策略
针对缓存穿透、雪崩、击穿问题CarrotSkin采用多种预防策略。对于缓存穿透使用`Nil`方法识别空值情况,避免频繁查询数据库。对于缓存雪崩,建议在配置中设置随机的过期时间偏移,避免大量缓存同时失效。
缓存击穿问题通过互斥锁或逻辑过期策略解决。当热点数据失效时,只允许一个请求加载数据,其他请求等待并使用旧数据,直到新数据加载完成。这种策略既保证了数据的一致性,又避免了数据库的瞬时压力。
**本节来源**
- [redis.go](file://pkg/redis/redis.go#L160-L162)
- [captcha_service.go](file://internal/service/captcha_service.go#L144-L145)
## 高可用架构支持
Redis高可用架构支持通过配置文件中的连接参数实现。虽然当前代码主要针对单机模式`github.com/redis/go-redis/v9`库原生支持哨兵模式和集群模式。通过修改配置,可以无缝切换到高可用架构。
连接故障恢复机制内置于客户端库中,自动处理网络抖动和临时故障。建议在生产环境中配置合理的超时时间和重试策略,确保系统的稳定性和可靠性。监控连接状态和性能指标,及时发现和解决潜在问题。
**本节来源**
- [redis.go](file://pkg/redis/redis.go#L24-L32)
- [config.go](file://pkg/config/config.go#L49-L56)