如何获取在多个轨道版本应用程序中连接的 redis 数据?



我正在使用redis缓存在我的rails应用程序中获取数据。简而言之,我可以说我有两个应用程序,第一个是基于轨道4,第二个是基于轨道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...

任何建议或任何想法?

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

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

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

但实际上第一步是再次考虑究竟要缓存什么以及为什么要缓存,有几个想法需要考虑:

  1. 当然,Redis/Memcache速度很快,但访问它仍然是一个数据库查询,具有相应的开销。从SQL数据库(如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
}
}
}

最新更新