beego cache 模块对每个引擎类型(如 "file")采用单例注册机制,内部用全局 map 以引擎名为键存储适配器,多次调用 newcache("file", config) 会覆盖前一次配置,导致所有操作实际指向最后一次指定的缓存目录。

Beego 的 cache 模块不支持为同一引擎(如 "file")创建多个独立实例——第二次调用 NewCache("file", ...) 会覆盖前一次配置,所有操作实际都落在最后一个目录里。
为什么 NewCache("file", config) 多次调用只生效最后一次
Beego 的 cache 模块对每个引擎类型("file"、"memory" 等)采用单例注册机制:内部用全局 map adapters 存储,键是引擎名。当你连续执行:
cache.NewCache("file", `{"CachePath":"./cache/a"}`)<br>cache.NewCache("file", `{"CachePath":"./cache/b"}`)
第二行会覆盖 adapters["file"] 的值,并返回同一个底层对象指针。结果是:两个变量看似不同,但 Put、Get 全部写入 ./cache/b,./cache/a 始终为空。
- 这不是 bug,而是设计限制;源码在
cache/cache.go#L84可验证 -
"memory"引擎同样受此约束,但因无路径冲突,问题不明显 -
"redis"和"memcache"因连接信息在配置中硬编码,多实例需靠不同连接地址区分(如不同 Redis DB 或端口),而非靠多次NewCache)
如何安全隔离不同业务的文件缓存
唯一可靠方式是共用一个 file 缓存实例,但通过 key 命名空间隔离:
- 定义统一前缀常量,例如:
const UserCachePrefix = "user:"、const OrderCachePrefix = "order:" - 所有 key 写入前拼接前缀:
cache.Put(UserCachePrefix+"123", data, 3600) - 批量清理时可用前缀过滤:
cache.Delete("user:123")或自行遍历文件系统按前缀匹配删除(Beego 不提供原生前缀清空 API) - 注意
DirectoryLevel配置影响文件分布,避免前缀过长导致单目录文件过多
memory 引擎的 Get 调用后数据消失?
这是 Beego memory 缓存的隐式行为:每次 Get(key) 会触发一次 Delete(key),即“读即删”。官方文档未明确强调,但源码中 memory.Get 方法内部确实包含 m.delete(key) 调用。
- 若需多次读取,必须重复
Put,或改用GetMulti([]string{key})—— 它不会删 key -
file和redis引擎无此行为,Get是纯读取 - 生产环境慎用
memory做状态缓存,尤其涉及会话、令牌等需多次验证的场景
Redis 引擎配置里 "conn" 字段不能省略端口
Beego 的 redis cache 使用 redigo 库,其连接字符串格式为 "host:port"。常见错误是写成 "127.0.0.1" 或 "localhost",导致初始化报错 parse "127.0.0.1": missing port in address。
- 正确写法:
{"conn":"127.0.0.1:6379", "dbNum":"0"} - 密码字段
"password"为空时可省略,但"conn"必须含端口 - 若用 Unix socket,格式为
{"conn":"/var/run/redis.sock"},此时无需端口,但需确保 redigo 支持且 Beego 版本兼容
真正麻烦的是跨服务共享缓存时的 key 冲突和过期策略不一致——Beego 的 file 和 memory 引擎没有原子性的“设置并返回旧值”或“带条件更新”,这类逻辑得自己套一层封装,别指望 cache.Cache 接口原生支持。











