# Redis缓存集成 **本文档引用的文件** - [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) ## 目录 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)