0

我一直在阅读/玩弄使用 Redis 来补充我的 ActiveRecord 模型的想法,特别是作为一种建模关系的方式。还观看了一些像这样的截屏视频:http ://www.youtube.com/watch?v=dH6VYRMRQFw

在您想要一次获取一个对象的情况下,这似乎是一个好主意,但是当您需要显示对象列表及其每个关联时(例如,在视图中或在对于 API 的 JSON 响应)。

而在纯粹使用 ActiveRecord 的情况下,您可以使用includes预先加载来避免运行 N 多个查询,但当纯粹依赖 Redis 来建模关系时,我似乎无法想到如何做到这一点。

例如,假设您有以下内容(取自非常有用的redis_on_rails项目):

class Conference < ActiveRecord::Base

  def attendees
    # Attendee.find(rdb[:attendee_ids])
    Attendee.find_all_by_id(rdb[:attendee_ids].smembers)
  end

  def register(attendee)  
    Redis.current.multi do
      rdb[:attendee_ids].sadd(attendee.id)
      attendee.rdb[:conference_ids].sadd id
    end
  end

  def unregister(attendee)
    Redis.current.multi do
      rdb[:attendee_ids].srem(attendee.id)
      attendee.rdb[:conference_ids].srem id
    end
  end

end

如果我做了类似的事情

conferences = Conference.first(20)
conferences.each {|c|
    c.attendees.each {|a| puts a.name}
}

我只是获取前 20 个会议并获取每个会议的与会者并将它们打印出来,但您可以想象这样一种情况,我在视图中的列表中呈现会议以及与会者列表。在上述情况下,我会遇到经典的 N+1 查询问题。

如果我将 SQL 中的关系与 一起建模has_many,我将能够使用该includes函数来避免同样的问题。

欢迎提出想法,链接,问题。

4

1 回答 1

1

Redis 可以为您的应用程序的基础架构提供重大优势,但我发现,由于您可以对各种数据类型执行特定操作,您确实需要提前考虑如何访问您的数据。在此示例中,如果您经常迭代一堆会议并输出与会者,并且没有从 Redis 执行丰富集合操作(​​如交集、联合等)的能力中受益,那么这可能不是一个好方法适合该数据模型。

另一方面,如果您在应用程序的性能密集型部分从 Redis受益,则可能值得在 Redis 上偶尔使用 N+1 GET 以获得这些好处。您必须对您关心的应用程序部分进行分析,以查看权衡是否值得。

您还可以在 Redis/您的应用程序中以一种可以避免 N+1 GET 的方式来构造您的数据;例如,如果您可以预先获取所有密钥,则可以使用MGET一次获取所有密钥,这是一个快速的 O(N) 操作,或者使用流水线来避免多次查找的网络延迟。

在我工作的一个应用程序中,我们构建了一个缓存层,用于缓存 has_many 关系的外键 ID,以便我们可以快速查找相互之间具有复杂关系的大量模型的缓存版本;在通过 SQL 获取这些内容时,我们会生成非常大、相对较慢的 SQL 查询,但是通过使用 Redis 和缓存的外键,我们可以执行一些 MGET,而根本不会访问数据库。但是,我们只是通过调查瓶颈所在并讨论如何避免它们来得出该解决方案。

于 2012-11-29T09:38:29.363 回答