我网站上的数据库负载变得非常高,因此我需要缓存每小时被调用 1000 次且结果不变的常见查询。
例如,在我的城市模型上,我执行以下操作:
def self.fetch(id)
Rails.cache.fetch("city_#{id}") { City.find(id) }
end
def after_save
Rails.cache.delete("city_#{self.id}")
end
def after_destroy
Rails.cache.delete("city_#{self.id}")
end
所以现在当我第一次访问数据库时我可以 City.find(1) 但接下来的 1000 次我从内存中得到结果。伟大的。但大多数对 city 的调用不是 City.find(1) 而是 @user.city.name,其中 Rails 不使用 fetch,而是再次查询数据库...这是有道理的,但不完全是我想要它做的事情。
我可以做 City.find(@user.city_id) 但这很丑陋。
所以我问你们这个问题。聪明人都在做什么?什么是
正确的方法是这样做吗?
关于缓存,有几个要点:
值得使用斜杠来分隔对象类型和 ID,这是 Rails 约定。更好的是,ActiveRecord 模型提供了 cacke_key 实例方法,它将提供表名和 id 的唯一标识符,“cities/13”等。
对 after_save 过滤器的一项小修正。既然您手头有数据,您不妨将其写回缓存,而不是删除它。这可以节省您一次访问数据库的时间;)
def after_save
Rails.cache.write(cache_key,self)
end
至于问题的根源,如果你不断地拉@user.city.name,有两个真正的选择:
- 将用户的城市名称非规范化为用户行。 @user.city_name(保留 city_id 外键)。应在保存时写入该值。
-or-
- 实现 User.fetch 方法来立即加载城市。仅当城市行的内容从未更改(即名称等)时才执行此操作,否则您可能会遇到与缓存失效有关的蠕虫病毒。
个人想法:
实现基于 id 的基本获取方法(或使用插件)以与 memcached 集成,并将城市名称非规范化为用户的行。
我个人并不是缓存模型样式插件的忠实粉丝,我从来没有见过一个可以节省大量开发时间的插件,而我还没有很快摆脱这些时间。
如果您收到太多数据库查询,那么绝对值得检查一下急切加载(通过:include)(如果您还没有这样做的话)。这应该是减少数据库查询数量的第一步。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)