首页 > 解决方案 > 如何获取多个rails版本应用程序中连接的redis数据?

问题描述

我正在使用 redis 缓存在我的 rails 应用程序中获取数据。简而言之,我可以说我有两个应用程序,第一个基于rails 4,第二个基于rails 6。我必须在两个应用程序中使用缓存数据。

在 rails 4 应用程序中:- 我在 rails 4 应用程序中创建了缓存,它成功地获取了数据。

Rails.cache.fetch("test_cache"){User.last}
=> #<User id: 100973, email: "xxxx.com", encrypted_password: "$2a$10$D8aOhoSWvNWeEQE2swAX2OEVIF5H0aY8sR/fGVQ3BhU...........> 

在 rails 6 应用程序中:- 但是当我想在我的 rails 6 应用程序中加载相同的缓存时,会出现错误。

Rails.cache.fetch("test_cache"){User.last}
Traceback (most recent call last):
        2: from (irb):18
        1: from (irb):18:in `rescue in irb_binding'
NameError (uninitialized constant ActiveRecord::AttributeSet)
Did you mean?  ActiveRecord::Attributes

然后我找到了一种解决方案,使用as_json

Rails.cache.fetch("test_cache"){User.last.as_json}

它成功地工作并在两个应用程序上获取了数据,但是我还有一个问题,我该如何访问model methods, associations etc etc...它。

有什么建议或想法吗?

标签: ruby-on-railsredis

解决方案


对于缓存 Rails 使用的非字符串值Marshal.dump(并且还通过 deflate 压缩它以获取大值)。编组数据可以被认为是介于数据和代码之间的东西,因为它引用了类名和内部结构。这就是它有局限性的原因:它只能使用相同的 ruby​​ 版本进行解组(参见ruby​​ 文档),并且应用程序应该具有相同的类。

显然,ActiveRecord::Base导轨 4 和导轨 6 的结构不同,因此在编组时不兼容。

要获得兼容性,您唯一的选择是仅缓存基本的 ruby​​ 类型和 PORO,它们不引用任何在您的应用程序中不同的类。您的尝试as_json正是这样做的——存储模型的哈希表示。

但实际上第一步是重新考虑你想要缓存的确切内容和原因,有几个想法需要考虑:

  1. 当然,Redis/Memcache 很快,但访问它仍然是一个数据库查询,有相应的开销。从 SQL DB(如 )的简单读取User.find(primary_key_value_here)几乎一样快。
  2. AR模型有关联缓存,你可能有一些记忆数据,你可能会遇到这些数据停滞
  3. 访问非缓存的关联仍然会导致数据库调用
  4. 很可能您想要缓存的不是模型本身,而是一种更容易找到它的方法(例如,如果它是一些昂贵计算的结果)或一些派生数据。在前一种情况下,存储记录 id 就足够了,在后一种情况下,您可以存储诸如哈希/PORO 之类的内容以及您需要的所有数据,例如:
hash = Rails.cache.fetch("last_registered_user"){
  User.last.yield_self{|u|
    {
      user_id: u.id,
      name: u.name,
      registered_at: u.created_at,
      invited_by: u.invited_by.name
    }
  }
}

推荐阅读