Rails 对 Rails 中「缓存失效」的一点疑惑

linjunzhugg · 2014年10月04日 · 最后由 jayliud 回复于 2014年10月08日 · 2927 次阅读

我们知道,现在要让缓存自动过期,主要是根据资源的「cache_key」

一般的请求如下:

浏览器请求 => 服务器渲染页面时拿着cache_key => 进缓存区查找 => 命中返回

那么,服务器是在什么时候知道资源更新了呢?

我有以下三种想法:

  1. 资源更新 => 自动通知到缓存区,使资源的缓存失效
  2. 资源更新 => 自动通知到页面的 cache 块,修改其 cache_key ( 计算 cache_key 时自动查询资源出来),这样拿着新的 cache_key 进缓存区查找时自然就找不到资源了。
  3. 服务器拿着 cache_key 进缓存块查找 => 命中资源 => 查询资源是否有更新过 => 再决定是否重新查找 or 直接返回

不知道哪种对?还是都错呢?

没人回我,伤心欲绝

每次资源更新 应该是直接删了缓存 第一次取的时候生成新的缓存

#2 楼 @chucai 那资源更新后,是如何通知到缓存区使缓存过期的?

是否是依据 cache_key?

那么资源更新后是从何拿到原先的 cache_key 的呢?

不好意思,之前回复有误(不适用于 rails 4),已删除 6 楼 @saiga 的回答是正确的。

#4 楼 @beiersi

感谢你的耐心解答 : )

恩,我知道 cache_key 是由我们自己定义的。

让 cache 失效也是我们自己来实现么?Rails 没帮我们实现吗?

说说 Rails 的套娃缓存机制 這篇文章中貌似有个观点:只要定义了 cache_key,资源更新时,Rails 会使缓存区里的缓存自动过期。 官方对 cache 的解释 中的观点貌似也是自动过期

泪流满面。。。。

缓存失效即使是人为控制都非常麻烦,这个程序帮不了... expire_cache 在 rails4 基本没用,因为 4 默认给每个 key 加入了 digest

只要定义了 cache_key,资源更新时,Rails 会使缓存区里的缓存自动过期。

这个说法是正确的,只不过自动过期并不是把缓存数据删除,而是不再命中该缓存,过期的缓存还是继续存在的,所以基于 file 的缓存方案会产生许多重复的垃圾,dhh 推荐使用 memcache 就是把删除缓存的操作交给 memcache 来做。

简单的说,关键在于如何生成 cache key。

一般来说,cache_key = f(m1, m2, m3, ..),每个实例 mx 的变化,必须反应到 cache_key 的变化,至于是 model 关联自动 touch 还是手动 touch 由你应用自己决定。

#6 楼 @saiga

感谢耐心解答 😄

所以基于 file 的缓存方案会产生许多重复的垃圾,dhh 推荐使用 memcache 就是把删除缓存的操作交给 memcache 来做。

学习到了,谢谢!!

不过还是有个疑问(原谅我问题这么多):

资源更新时为何不再命中该缓存了呢?

我们知道,程序是拿 cache_key 去缓存区命中缓存的,既然是不再命中缓存,也就是说,程序拿的这个 cache_key 已经是更新过的了。那么问题来了:

1. 程序是什么时候拿到 cache_key 的?每次请求都会重新计算该 cache_key 么?
2. 每次请求不会重新计算 cache_key, 当第一次计算 cache_key 后会保存起来,当资源更新时,自动找到该资源所关联的所有 cache_key ,进行更新?

不过我的观点倾向于第二个,您觉得呢?: )

#7 楼 @hooopo

恩恩,谢谢耐心解答!!

还有个小问题,在 8 楼,还希望您能够给出您的意见 😄

#8 楼 @linjunzhugg 第一个,计算 cache_key 的代价很小。第二种方案过于复杂。

#10 楼 @hooopo 那每次计算 cache_key 的时候,不是都需要进入数据库查询么?这样的话不会耗费资源吗?

#11 楼 @linjunzhugg 所以要你设计合理的 cache key,比如你已经有了一个 product 对象,product.cache_key 是不需要查的。

#12 楼 @hooopo 😢 咦,为什么不需要查呢?

如果一个对象列表 products

那么我的 cache_key,则是这些 products 中 updated_at 最晚的那个。

那我每次请求需要拿到 新/旧 资源的 cache_key 时,不需要进数据库查询 products.max(&:updated_at)吗?

#13 楼 @linjunzhugg 列表要查,但是 max 这种查询很快(在索引正确的情况下)。

缓存本质倒不是查不查,而是把一个长查询转化成短查询。

#14 楼 @hooopo

原来如此,学习到了。你解决了我一个纠结了两天的困惑,感谢谢谢谢谢~~!!!☺

#12 楼 @hooopo 这不也得查么。。。一般都有用到 product 的 updated_at

需要 登录 后方可回复, 如果你还没有账号请 注册新账号