revel 缓存需手动配置实现,官方仅原生支持 memcached;必须在 app.conf 中设置 cache.impl=memcached 及 server、timeout 等参数,否则 cache.get/set 无效;redis 需自行实现 cache.cache 接口并调用 cache.setcache 注册。

Revel 框架本身内置了缓存支持,但默认不启用,且不绑定具体后端 —— 你得自己配 cache.impl 和连接参数,否则 cache.Get、cache.Set 全是空操作。
确认 Revel 的 cache 包已启用并指定实现
Revel 的缓存抽象在 github.com/revel/revel/cache,但它只是接口层。真正起作用的是你配置的实现,比如 memcached 或自定义的 redis 封装。
常见错误现象:cache.Get("key") 总返回空、无报错、也不写入;或本地开发时误以为开了缓存,上线后才发现根本没连上 Memcached。
- 必须在
conf/app.conf中显式设置:cache.impl=memcached(目前 Revel 官方只原生支持 Memcached) - 如果要用 Redis,得自己实现
cache.Cache接口,并在app.Init阶段用cache.SetCache替换默认实例 -
cache.impl=memory是测试用的内存缓存,仅进程内有效,不能用于多实例部署
配置 Memcached 连接参数(官方唯一开箱即用方案)
Revel 默认只认 Memcached,且要求服务端监听在 127.0.0.1:11211。它不读取环境变量或复杂配置,全靠 app.conf 的固定字段。
配置项必须严格匹配,大小写和缩进都不能错:
cache.memcached.servers = 127.0.0.1:11211 cache.memcached.timeout = 500 cache.memcached.connectTimeout = 500
注意:cache.memcached.servers 是字符串,不是数组;多个地址用逗号分隔,如 "10.0.1.10:11211,10.0.1.11:11211";超时单位是毫秒。
- 如果 Memcached 没跑起来,
cache.Set不会报错,但后续Get一定为空 —— 建议启动时加一行cache.Get("test")+ 日志验证连通性 - Revel 不做连接池管理,每个请求都新建连接,高并发下容易打满 Memcached 的 fd 限制
在 Controller 中安全使用 cache.Get / cache.Set
缓存调用本身是同步阻塞的,别在异步 goroutine 里直接用 cache 实例 —— Revel 的全局 cache 实例不是线程安全的封装,而是直连底层 client。
典型缓存逻辑(先查后回源)要自己写,Revel 不提供注解或自动拦截:
func (c App) Show(id string) revel.Result {
key := "user:" + id
if data, found := cache.Get(key); found {
return c.RenderJSON(data)
}
user := findUserFromDB(id) // 你的 DB 查询逻辑
if user != nil {
cache.Set(key, user, 300) // 5 分钟 TTL
}
return c.RenderJSON(user)
}
-
cache.Get返回(interface{}, bool),第二个布尔值才是关键,不能只判data != nil - TTL 单位是秒,不是毫秒;传负数表示永不过期(不推荐)
- 缓存值必须是可序列化类型(
map、struct、string等),函数或 channel 会 panic
想用 Redis?得自己桥接,别依赖 Revel 内置机制
Revel 没有 cache.impl=redis 这种配置项,它的 cache 包压根没引用任何 Redis client。所谓“支持 Redis”只是指你可以替换底层实现。
最简做法:用 github.com/go-redis/redis/v9 写个适配器,实现 cache.Cache 接口的 Get、Set、Delete 方法,然后在 app.Init 中注册:
func init() {
revel.InterceptMethod((*App).Begin, revel.BEFORE)
revel.OnAppStart(Init)
}
func Init() {
rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"})
cache.SetCache(&RedisCache{Client: rdb})
}
这个过程没有魔法,也没有自动序列化配置 —— 你要自己处理 JSON marshal/unmarshal、错误重试、连接健康检查。
最容易被忽略的一点:Revel 的 cache 接口不暴露上下文(context.Context),所以你写的 Redis 适配器没法支持超时控制或取消,所有操作都是阻塞到底。生产环境务必加熔断或 fallback 逻辑。











