【问题标题】:Rails store some attributes in redis instead of relational dbRails 将一些属性存储在 redis 而不是关系数据库中
【发布时间】:2021-05-11 22:44:37
【问题描述】:

我有以下型号:

class Movie < ActiveRecord::Base
 #Has rating, duration, year as database fields
 #Want to store content_rating in redis instead of database
end

我这样更新模型:

 movie = Movie.find(1)
 movie.update(rating: 5, duration: 3600, year: "1955", content_rating: "PG-13")

我想要的是所有的db属性(评级,持续时间,年份)都存储在数据库中,而content_rating存储在redis中。

如果不用在 after_update 回调中手动保存 content_rating,是否可以使用 rails?

【问题讨论】:

    标签: ruby-on-rails activerecord redis


    【解决方案1】:

    没有办法让update 方法将一些属性保存在数据库中,而将另一些属性保存在Redis 中。 (除非您强烈建议不要覆盖它。)

    您可以手动定义 setter 和 getter 方法来存储和读取 Redis 中的属性(使用 redis-rb gem):

    class Movie < ActiveRecord::Base
      def content_rating=(value)
        redis.set(content_rating_key, value)
      end
    
      def content_rating
        redis.get(content_rating_key)
      end
    
      private
    
      def redis
        @redis ||= Redis.new
      end
    
      def content_rating_key
        @content_rating_key ||= "#{self.class.table_name}:#{id}:content_rating"
      end
    end
    
    movie = Movie.find(1)
    movie.content_rating = "PG-13"
    movie.content_rating # => "PG-13"
    

    或者,使用 kredis gem 来代替它,它变得非常简单:

    class Movie < ActiveRecord::Base
      kredis_string :content_rating
    end
    
    movie = Movie.find(1)
    movie.content_rating.value = "PG-13" # Saves the attribute in Redis.
    movie.content_rating.value # Reads the attribute from Redis which is now "PG-13".
    

    另外,请注意,如果您要遍历电影并阅读它们的 content_rating,它将生成 N+1 个 Redis 查询,这可能会成为性能瓶颈。在这种情况下,您应该使用Redis#mget 一次性加载所有属性。

    【讨论】:

    • "在这种情况下,您应该使用 Redis#mget 一次性加载所有属性。" - 啊,但现在你的自定义访问器消失了 :) 正如你所说,这总体上是个坏主意。
    猜你喜欢
    • 2013-11-09
    • 2015-07-05
    • 1970-01-01
    • 2019-01-17
    • 1970-01-01
    • 2011-12-15
    • 2017-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多