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

升级至Rails 7.1后从Redis缓存读取Active Record模型报错

Rails 7.1.3.2 升级后 Redis 缓存 Active Record 模型的属性读取问题

问题背景

将Rails从7.0.8升级至7.1.3.2后,使用Redis缓存Active Record(AR)模型时出现异常:读取缓存中的模型实例时,除id外的其他属性无法访问,报错提示未知方法。缓存代码示例:

Rails.cache.fetch("key_name") { Ar_Model[some_key] }

复现步骤与现象

  1. 第一个控制台(正常场景):

    model = Rails.cache.fetch("key_name") { Ar_Model[some_key] }
    model.class => Ar_Model(id: integer, name: string)
    model.name => "some_name"
    

    所有属性均可正常读取。

  2. 第二个控制台(异常场景):

    model = Rails.cache.fetch("key_name")
    model.class => Ar_Model(id: integer, name: string)
    model.id => some_id
    model.name => Error! Unknown method 'name' for Ar_Model()
    

    读取非id属性时报错。

  3. 特殊修复现象:在第二个控制台执行Ar_Model.first后,无需重新加载缓存模型即可正常读取所有属性:

    model = Rails.cache.fetch("key_name")
    model.class => Ar_Model(id: integer, name: string)
    model.id => some_id
    model.name => Error! Unknown method 'name' for Ar_Model()
    Ar_Model.first
    model.name => "some_name"
    

问题原因

Rails 7.1对Active Record的序列化/反序列化机制做了优化,当模型类在当前进程中未完成初始化(未执行过查询、未加载属性定义)时,反序列化缓存中的模型实例只会加载主键属性的访问器方法。而执行Ar_Model.first这类操作会触发模型类的初始化,加载所有属性的访问器,因此之后能正常读取属性。

解决方案

方案1:缓存属性哈希而非模型实例

避免直接缓存AR实例,改为缓存属性哈希,读取时再构建模型:

# 写入缓存
Rails.cache.fetch("key_name") { Ar_Model[some_key].attributes }

# 读取缓存
model = Ar_Model.new(Rails.cache.fetch("key_name")).tap(&:readonly!)

如果需要包含关联数据,可使用serializable_hash(include: [:关联名])替代attributes。

方案2:预加载模型类初始化

在读取缓存前,主动触发模型类的属性加载,确保访问器已定义:

# 读取缓存前执行,触发模型属性初始化
Ar_Model.columns_hash

model = Rails.cache.fetch("key_name")

也可以在应用启动时预加载所有AR模型,比如在初始化脚本中添加:

Rails.application.eager_load!

方案3:统一缓存序列化版本

确保应用使用Rails 7.1的缓存序列化格式,在config/application.rb中配置:

config.active_record.cache_format_version = 7.1

注意:如果缓存中存在旧版本格式的数据,需先清理缓存,否则反序列化仍会异常。

内容的提问来源于stack exchange,提问作者S. Chekan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 12:33:23