Buffalo.Session不能当通用缓存用,因其强制gob编码、key自动加session:前缀、无原子操作且MaxAge不支持访问重置;应使用全局*redis.Client v9单例,配超时、防穿透并正确处理redis.Nil与错误。

buffalo.Session 不能当 Redis 缓存用
Buffalo 的 buffalo.Session 是会话专用机制,不是缓存中间件。硬塞业务数据进去会立刻踩三个坑:gob 编码导致其他语言/工具(如 redis-cli)完全无法读取;所有 key 自动加 session: 前缀,破坏业务命名空间;没有 SetEx、GETSET 等原子操作,连防重复提交都做不了。更关键的是,它的 MaxAge 是创建后固定过期,不支持“每次访问重置”,不适合用户活跃检测类逻辑。
用 github.com/redis/go-redis/v9 初始化全局单例
在 app.go 里声明一个包级变量:var RDB *redis.Client,不要塞进 c.Value 或靠中间件传参。初始化时必须显式配置连接池和超时:
-
PoolSize设为 20–50(QPS 超 300 就别用默认值 10) -
MinIdleConns≥ 5,防 SLB/NAT 静默断连后首请求失败 -
ReadTimeout和WriteTimeout均设为3 * time.Second,否则网络抖动会让整个 HTTP 请求卡死 - 地址、密码、DB 号必须从环境变量(如
REDIS_ADDR)读,别硬编码"localhost:6379"
初始化后立刻调 RDB.Ping(ctx).Err() 验证连通性——别等第一个 Get 才暴露配置错误。
在 action 层安全读写缓存的典型模式
以「查用户并缓存 5 分钟」为例,重点是空值穿透防护和错误分离处理:
立即学习“go语言免费学习笔记(深入)”;
- 先调
RDB.Get(ctx, key).Result(),若返回redis.Nil,说明缓存未命中,再去查 DB - DB 查询后,用
RDB.Set(ctx, key, data, 5*time.Minute)写入,别用SetNX除非你真需要分布式锁语义 - 若 DB 返回空(如用户不存在),写个短 TTL 空标记:
RDB.Set(ctx, key, "null", 30*time.Second) - 所有
err != nil必须判断:redis.Nil是正常流程,网络错误(如超时、连接拒绝)得打日志告警
键名推荐格式:"user:profile:123",结构体统一用 json.Marshal 序列化,字段必须导出 + 显式 json:"field" tag。
容易被忽略的 TTL 对齐与连接池泄漏
Redis key 过期了,Get 返回 redis.Nil 没问题;但如果你同时用了 PostgreSQL session store,又没让两者的 TTL 对齐,就可能出现「Redis 里 key 已删,DB 里 session 还挂着」的状态不一致。另外,*redis.Client 是线程安全的,但别在 handler 里反复调 redis.NewClient() —— 连接池不会自动回收,进程运行越久,fd 泄漏越严重,最终触发 too many open files。


















