9.0 KiB
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)目录
项目结构
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客户端封装设计
CarrotSkin项目中的Redis客户端封装采用分层设计模式,通过Client结构体对github.com/redis/go-redis/v9库进行包装,提供更简洁的API接口。Client结构体包含*redis.Client指针和*zap.Logger日志记录器,实现了日志记录和错误处理的统一管理。
封装设计遵循单一职责原则,将Redis连接管理、操作执行和日志记录分离。通过New函数创建客户端实例时,会根据配置参数初始化连接,并执行连接测试,确保连接的可用性。这种设计模式提高了代码的可维护性和可测试性。
本节来源
连接池与健康检查机制
Redis连接池配置在RedisConfig结构体中定义,包含Host、Port、Password、Database和PoolSize等关键参数。连接池大小通过PoolSize字段配置,默认值为10,可根据实际负载情况进行调整。
健康检查机制在客户端初始化时实现,通过Ping命令测试连接可用性。使用context.WithTimeout设置5秒超时,防止连接测试阻塞主线程。连接成功后会记录包含主机、端口和数据库信息的日志,便于监控和故障排查。
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 : 初始化完成
图示来源
本节来源
缓存操作实现原理
缓存操作通过Client结构体的方法实现,包括Set、Get、Del、Exists、Expire等基本操作。这些方法直接代理到底层redis.Client的对应方法,保持了与原生API的一致性。
Set方法接受context.Context、键、值和过期时间参数,支持设置键值对及其过期时间。Get方法返回字符串值和错误,通过Nil方法可以判断键不存在的情况。Expire方法用于修改现有键的过期时间,支持动态调整缓存策略。
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 : 使用
图示来源
本节来源
JWT令牌存储应用
JWT令牌存储利用Redis作为临时存储介质,通过Set方法将令牌与用户信息关联存储。令牌的过期时间与JWT的有效期保持一致,确保令牌在Redis中的生命周期与JWT一致。
在jwt.go中,JWT服务生成令牌后,可以通过Redis存储令牌的元数据,如用户ID、角色等信息。这种设计实现了无状态认证与有状态缓存的结合,既保持了JWT的无状态特性,又可以通过Redis快速验证令牌的有效性。
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 : 处理请求
图示来源
本节来源
会话管理与验证码应用
会话管理通过Redis存储会话数据,每个会话以唯一ID作为键,会话数据作为值进行存储。验证码应用在captcha_service.go中实现,使用redisKeyPrefix = "captcha:"作为键前缀,确保验证码数据的隔离性。
验证码生成时,将滑块的目标坐标等验证信息序列化后存储到Redis,设置300秒过期时间。验证时从Redis获取原始数据,与用户输入进行比对,验证成功后立即删除Redis记录,防止重复使用。
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["返回验证结果"]
图示来源
本节来源
限流控制实现
限流控制在verification_service.go中实现,通过Redis的Set命令设置频率限制。使用codeType和email组合生成限流键,值设为"1",过期时间由CodeRateLimit常量定义。
当用户请求发送验证码时,先检查限流键是否存在,若存在则拒绝请求,防止频繁发送。这种基于Redis的限流机制简单高效,能够有效防止恶意刷屏攻击,保护系统资源。
flowchart LR
Request[发送验证码请求] --> Check["Exists(verification:rate:email)"]
Check --> |存在| Reject[拒绝请求]
Check --> |不存在| Send[发送验证码]
Send --> Set["Set(verification:rate:email, 1, 60s)"]
Set --> Response[返回响应]
图示来源
本节来源
缓存问题预防策略
针对缓存穿透、雪崩、击穿问题,CarrotSkin采用多种预防策略。对于缓存穿透,使用Nil方法识别空值情况,避免频繁查询数据库。对于缓存雪崩,建议在配置中设置随机的过期时间偏移,避免大量缓存同时失效。
缓存击穿问题通过互斥锁或逻辑过期策略解决。当热点数据失效时,只允许一个请求加载数据,其他请求等待并使用旧数据,直到新数据加载完成。这种策略既保证了数据的一致性,又避免了数据库的瞬时压力。
本节来源
高可用架构支持
Redis高可用架构支持通过配置文件中的连接参数实现。虽然当前代码主要针对单机模式,但github.com/redis/go-redis/v9库原生支持哨兵模式和集群模式。通过修改配置,可以无缝切换到高可用架构。
连接故障恢复机制内置于客户端库中,自动处理网络抖动和临时故障。建议在生产环境中配置合理的超时时间和重试策略,确保系统的稳定性和可靠性。监控连接状态和性能指标,及时发现和解决潜在问题。
本节来源