论坛首页 编程语言技术论坛

一行代码搞定ActiveRecord的二级缓存

浏览 16453 次
该帖已经被评为精华帖
作者 正文
   发表时间:2008-10-06  
可以参考一下CachedModel的代码:

1、User.find(1, :select => "id,name")

这个问题CachedModel解决的挺好,他直接拦截find_by_sql方法,插入缓存。另外CachedModel对于非 find :all的查询语句,会自动把得到的结果集遍历model对象,把每个model对象插入缓存,自动的把查询缓存转化为对象缓存,我觉得这个思路挺好。

2、还要考虑Transaction回滚的问题

如果Transaction回滚,那么cache已经被更新了,就会出现Cache和数据库数据不一致的现象。所以CachedModel对ActiveRecord的transction方法也做了改写,把更新缓存的动作延迟到事务成功提交之后才执行。
0 请登录后投票
   发表时间:2008-10-09  
2. 对于belongs_to/has_one等关系的一方,如果该model被标记为使用cache,调用关系方法的时候也将会先从cache中查找。

我在用插件的过程中发现
如果user has_many image 对user缓存没问题,但好像无法对image进行缓存。
像user.images这样来访问的话 第一次直接读数据库没问题,但如果后面从缓存中取数据的话,会报:undefined method `images' 是不是我哪里出了问题.
0 请登录后投票
   发表时间:2008-10-09  
这个插件对于many的集合是没有做缓存的,调用user.images都是从数据库查询的,你说的从缓存取是自己写的代码吧?把代码贴上来看看。
0 请登录后投票
   发表时间:2008-10-09  
没有自己写缓存,用的是你的插件。
Model user里面代码如下:
 
  acts_as_cached
  def self.get_users 
    get_cache("users") {find(:all)}
  end 


Action里面代码如下:

  def users
    @users = User.get_users 
    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @users }
    end
  end


在view里面这样访问:
<% for user in @users %>
   <% if user.images.size > 0 -%>
    ....
   <% end -%>
<% end %>


第一次访问从数据库读取数据没任何问题,但当再次访问的时候就报错。
0 请登录后投票
   发表时间:2008-10-09  
我试了一下,不会报错
class User < ActiveRecord::Base
  acts_as_cached
  has_many :images

  def get_users
    get_cache("users") {find :all}
  end
end


ruby script/console
>> User.get_users #cache miss
>> users = User.get_users #cache hit
>> users[0].images.size #正确输出

你检查后台log看看,是不是其他错误造成的?
0 请登录后投票
   发表时间:2008-10-09  
有点奇怪,我在console下测试也没问题,但是在view里面执行,就是报错!
0 请登录后投票
   发表时间:2008-10-09  
在Action里面对@users遍历访问iamges,同样的问题。报undefined method `images',但在console下测试没有问题

  def users
    @users = User.get_users 
    @users.each { |i| i.images.size}
    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @users }
    end
  end

0 请登录后投票
   发表时间:2008-10-09  
可能和我前面文章中讲的第4点有关系:
4. memcached的undefined class/module错误,从cache_fu抄袭了一个autoload_missing_constants方法来解决这个问题:
http://www.philsergi.com/2007/06/rails-memcached-undefinded-classmodule.html

你试试看在action的第一行写一下Image,让rails先load这个class,看看还会不会出错。

我明天再写代码调试看看到底是什么原因。

---分割线---
后来我在view和action里面都实验了,还是无法重现你说的错误,是不是你在开发环境没有用mem_store?
Rails默认使用MemoryStore作为cache,在开发环境下是会和class reload有冲突:
http://rails.lighthouseapp.com/projects/8994/tickets/785-caching-models-fails-in-development
0 请登录后投票
   发表时间:2008-10-10  
测试了一下,是默认的MemoryStore会和class reload有冲突,造成这个问题。
具体的原因可以看上面的链接。
只要指定config.cache_store = :mem_cache_store使用MemcacheStore就可以了。
0 请登录后投票
   发表时间:2008-10-21  
Good Job
可以讓我學學Cache的一些技巧
剛好項目會用上呢0ˇ0
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics