cache.NewCache("redis", config) 返回 nil 的根本原因是驱动未注册或配置字段不匹配:必须显式导入 _ "github.com/astaxie/beego/cache/redis",且配置中字段名须严格为"conn"、"dbNum"、"password",缺一不可。

cache.NewCache("redis", config) 返回 nil?检查驱动导入和配置字段名
Beego 的 cache.NewCache 不会报错提示“驱动未注册”,而是静默返回 nil,后续调用 Put/Get 会 panic 或始终返回空值。必须确认两点:
- 显式导入驱动:
_ "github.com/astaxie/beego/cache/redis"(注意下划线,否则注册不生效) - 配置字符串字段名严格匹配源码要求:
"conn"(不是"address")、"dbNum"(不是"database")、"password"(即使为空也得写"") - 示例正确配置:
{"conn":"127.0.0.1:6379","dbNum":"0","password":""};少引号、多空格、大小写错误都会导致解析失败
GetString() 总是空或乱码?别跳过 JSON 序列化环节
cache.GetString() 本质只是对 []byte 做 string(v) 强转,它不处理结构体序列化。如果你存的是 struct,直接 bm.Put("key", userStruct, ttl),实际存进去的是 fmt.Sprintf("%+v", userStruct) 的字符串,不可靠且无法反解。
- 存之前必须手动
json.Marshal:data, _ := json.Marshal(userStruct); bm.Put("user:1001", data, time.Hour) - 取的时候推荐用
Get拿[]byte,再json.Unmarshal([]byte(b), &target);用GetString再转[]byte多一次拷贝,还可能因 UTF-8 编码问题出错 - 结构体字段必须导出(首字母大写),并加
json:"field_name"tag,否则json.Marshal会忽略
每次请求都 NewCache?连接池爆炸的根源
在 controller 的 Get() 方法里反复调 cache.NewCache("redis", config),等于每次请求新建一个 Redis 连接池,很快耗尽 Redis 的 maxclients(默认 10000),表现为大量 redis: connection pool timeout。
- 连接池必须全局单例:在
main.go或models/init.go的init()函数中初始化 - 推荐封装为全局变量:
var Cache cache.Cache,初始化后复用 - 配置应从环境变量或 Beego 配置中心读取,避免硬编码
"localhost:6379"
缓存穿透/击穿/雪崩怎么防?Beego 层必须自己兜底
Redis 本身不解决这三类问题,Beego 的 cache 模块也不内置防护逻辑。你得在业务层加策略:
- 穿透:DB 查无结果时,缓存写入
rdb.Set(ctx, key, "null", 60*time.Second),读到"null"就直接返回空,不查 DB - 击穿:热点 key 过期瞬间并发打穿 DB,用
singleflight.Group包一层Do,确保同一 key 只有一个 goroutine 去查 DB - 雪崩:避免批量 key 同一时刻过期,TTL 加随机扰动:
baseTTL + time.Duration(rand.Int63n(int64(2*time.Minute)))
这些逻辑没法靠配置打开,必须手写进业务代码里——最容易被忽略的是“空值缓存”和“随机 TTL”,线上出问题往往就卡在这两步没做。


















