片段缓存和 Cache Key

1) 页面上的静态内容

2) 页面上的动态内容

3) 页面上的内容,在 model 层面有关联

4) 页面上的内容有嵌套关系

使用片段缓存几点原则

  1. 缓存由动态内容和静态内容两部分构成。

  2. 动态内容的 cache_key 由我们指定; 2. 没有嵌套的情况下,如果动态内容不指定 cache_key,则自己的动态内容永远不会更新(例外见最后); 2. 有嵌套的情况下,如果动态内容不指定 cache_key,则自己的动态内容 & 孩子的动态内容永远不会更新(例外见最后);

  3. 没有嵌套的情况下,有且只有自己的 cache_key 更新,动态内容才更新;

  4. 有嵌套的情况下,有且只有自己的 cache_key 更新 & 父亲的 cache_key 更新,动态内容才更新;

  5. 动态内容的更新,不影响静态内容的部分;

  6. (各动态内容的 cache_key 是独立的,自己及其父亲、兄弟、孩子的 cache_key 没有依赖关系)

  7. 无论哪的静态内容更改,有且只有重启后更新,不存在(也不用考虑)嵌套的问题;

  8. 静态内容的更新,不影响动态内容的部分(例外见最后);

  9. 例外:动态内容没有指定 cache_key,只有静态内容同时更新,并且重启,动态内容才会更新。

说一说 Cache Key

1) record 的 cache_key

2) helper 方法 cache(name = {}, options = nil, &block) 这里的 name

3) 内存数据库 key

不严格区分的话,它们都可以叫做"Cache Key"

但,你可以把它们区分开来:

post.cache_key
# => "posts/1-20140921032815201680000”
<% cache [ 'a_post', post ] do %>
  ... ...
<% end %>
views/a_post/posts/1-20140921032815201680000/9746fd05c8428f7999681aa804071e9a
(路径    helper方法cache的name部分    静态内容md5)

特点:

1 由 record 的"id + updated_at时间戳"组成,所以 record 更新,cache_key 会更新 (update_column等情况不讨论)

2 由我们指定,所以理论上可以随便写。没有嵌套缓存的情况下,一般可以直接使用 1;有嵌套的情况下可以用 touch 更新父亲资源或者使用一个组合,如: cache [current_user, post]

3 根据 2 生成 (但不等于 2),要求唯一 (要不然就没意义了)

2 每次请求都要计算

2 计算之后和 3 对比是否匹配。不匹配则生成新的内容,渲染页面;匹配则返回,渲染页面

2 不匹配,那么意味着之前的内容过期了,过期的内容还是继续存在的数据库里的。(这里的过期不等于被删除)

2 过期的内容可以由我们手动删除,如:Rails.cache.clear;或让数据库自动删除,如 config.cache_store = :redis_store, 'redis://localhost:6379/5/cache', { expires_in: 90.minutes } 这里数据最多只能在 redis 里保存 redis 每隔 90 分钟,到期的缓存数据会被删除。(这里的到期等于被删除)

几点建议

缓存主要有两种方式过期。 1. 调用 cache(name = {}, options = nil, &block) 的时候把会引起数据变化的元素都放到 name 里 2. 后续更新一个对象的时候,touch 其关联对象

  • 嵌套太深不适合使用缓存(不超过 4 层)

  • 涉及太多不同类型的 record 对象时,不推荐使用缓存

  • 弱关联(非 has_many, has_one, belongs_to)对象,不适合放在一起做缓存

嵌套太深或 record 对象太多, 或几个对象之间属于弱关联,无论使用哪种缓存过期机制对于维护都是恶梦。

最后更新于