You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails 5.2+redis-rails片段缓存未自动过期问题咨询

排查Rails 5.2片段缓存touch后未更新的问题

我来帮你梳理几个可能导致这个问题的原因,以及对应的排查和解决方法:

1. 检查Site模型是否重写了cache_key方法

Rails片段缓存的键是基于对象的cache_key方法生成的,默认格式为"model_name/id-#{updated_at.utc.to_s(:number)}"。如果你的Site模型自定义了cache_key方法,但没有包含updated_at字段,那么即使执行touch更新了时间戳,缓存键也不会变化,自然不会触发缓存失效。

比如,如果你在模型里写了这样的代码:

class Site < ApplicationRecord
  def cache_key
    "sites/#{id}"
  end
end

这就会导致缓存键固定为"sites/1"(假设id是1),touch后键不变,缓存不会更新。解决方法是恢复默认逻辑,或者在自定义方法里包含updated_at:

def cache_key
  "sites/#{id}-#{updated_at.utc.to_s(:number)}"
end

2. 确认touch操作确实正确更新了updated_at

虽然你提到updated_at时间戳变更了,但可以再仔细验证一下:

  • 在Rails控制台执行@site.touch,然后立即执行@site.reload.updated_at,对比touch前后的时间是否有变化。
  • 检查Site模型是否有回调方法干扰了updated_at的更新,比如before_save回调手动设置了updated_at为某个固定值,或者阻止了字段的更新。
  • 检查数据库表结构,确保updated_at字段是datetime类型且允许自动更新(Rails默认会维护这个字段,但如果手动修改过迁移文件可能会出问题)。

3. 检查缓存存储的配置是否正确

使用redis-rails时,缓存存储的配置可能影响缓存键的处理:

  • 确认config.action_controller.cache_versioning的设置:Rails 5.2中这个配置默认是false,此时缓存键直接包含对象的cache_key(包含updated_at);如果手动开启了cache_versioning,需要确保对象的cache_version方法正确返回基于updated_at的值(默认是会的,但如果自定义了cache_version就需要检查)。
  • 检查config.cache_store的配置,确保使用的是:redis_cache_store且参数正确,比如没有设置错误的命名空间导致缓存隔离,或者序列化器配置异常影响缓存的读写。

4. 排查缓存键的生成是否符合预期

直接在视图或控制台里打印缓存键,确认touch前后是否变化:
在视图里添加临时调试代码:

<%= "Cache key: #{cache_key([@site, 'header'])}" %>
<% cache [@site, "header"] do %> header goes here <% end %>

然后执行@site.touch刷新页面,看缓存键是否变化。如果键没变,那问题肯定出在键的生成逻辑上;如果键变了但还是显示旧内容,那可能是Redis缓存没有正确写入,或者存在缓存穿透的情况(比如Redis连接异常, fallback到了其他缓存存储)。

5. 检查是否存在缓存分层或代理问题

如果你的应用使用了多层缓存(比如CDN+Redis),即使Redis里的缓存失效了,CDN可能还缓存了旧内容。这种情况下需要检查CDN的缓存策略,确保片段缓存的响应头设置了正确的缓存失效规则,或者在touch操作时主动清除CDN对应路径的缓存。


内容的提问来源于stack exchange,提问作者Dan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:55:10