model级别cache的(一)

上一篇 / 下一篇  2007-11-18 11:37:28 / 精华(1) / 个人分类:projects

查看( 6 ) / 评论( 4 )
数据库是瓶颈,今天我们介绍model级别的cache。Cached Model 是一个简单的只对单记录做缓存的plugin.Cached Model的的存储分为本地存储和Memcached存储。本地存储大家都知道,一般都是用Hash来存储的。这里的Memcached是一种网络分布式存储。

我们先来看看如果应用cached model
一:安装

CODE:

gem install cached_model -y二:应用
简单的创建一个工程

CODE:

rails cached_model_demo新建Page

CODE:

ruby script/generate scaffold_resource page title:string content:text created_at:timestamp创建数据库

CODE:

rake db:migrate修改Page Model,继承CachedModel

CODE:

class Page < CachedModel
end
在enviroment中增加memcached的配置的代码:

CODE:

require 'cached_model'

memcache_options = {
  :c_threshold => 10_000,
  :compression => true,
  :debug => false,
  :namespace => 'cached_model_demo',
  :readonly => false,
  :urlencode => false
}

CACHE = MemCache.new memcache_options
CACHE.servers = 'localhost:11211'
上面都是一些简单的东西,我们就忽略了,有什么问题,大家提出来。

好了,准备就绪。cached_model 默认是采用memcached store的方式,当然你可以采用local的方式

CODE:

CachedModel::use_local_cache=true启动memcached server

CODE:

memcached -vv我们传递vv参数可以查看更多的日志信息,具体的可以查看--help


打开ruby script/console 并打开tail -f log/development.log查看日志
新建page

CODE:

Page.create :title=>'Hello World'
Page.create :title=>'Hello World Again'
成功。cached_model只覆盖了ActiveRecord的两个方法,一个是find,一个是find_by_sql.我们具体的分析一下这两个方法
1:) find

CODE:

def self.find(*args)
        args[0] = args.first.to_i if args.first =~ /\A\d+\Z/
        # Only handle simple find requests.  If the request was more complicated,
        # let the base class handle it, but store the retrieved records in the
        # local cache in case we need them later.        
        if args.length != 1 || !Fixnum === args.first then
            # Rails requires multiple levels of indirection to look up a record
            # First call super
            records = super
            # Then, if it was a :all, just return
            return records if args.first == :all
            return records if RAILS_ENV == 'test'
            case records
            when Array then
                records.each { |r| r.cache_store }
            end
            return records
        end

        return super
    end
这里面压根没有读取cache的代码,不管这么样,都会先调用super执行查询,只有在
>参数个数不为1或第一个不是数字
>第一个参数不是:all
>不是test环境下
>返回结果为Array的时候才缓存model   
也就是说基本没什么作用。
我们试验下

CODE:

Page.find 1依然执行SQL,memcached无反应

CODE:

Page.find 1,2我们会看到memcached中有了两条记录

CODE:

<1924 new client connection
<1924 set cached_model_demo:active_record:Page:1 0 900 95
>1924 STORED
<1924 set cached_model_demo:active_record:Page:2 0 900 101
>1924 STORED
保存了两条记录

在执行

CODE:

Page.find 1依然查询数据库。那我们该如何取这样的数据呢?

CODE:

>> Cache.get "active_record:Page:1"
=> #"Hello World", "id"=>"1", "content"=>nil, "cr
ed_at"=>"2007-11-10 18:29:29"}>
2:)find_by_sql

CODE:

def self.find_by_sql(*args)
        return super unless args.first =~ /^SELECT \* FROM #{table_name} WHERE \(?#{table_name}\.#{primary_key} = '?(\d+)'?\)? +LIMIT 1/
很简单,但是他只cache根据主键id查询的record

CODE:

Page.find_by_sql "SELECT * FROM PAGES WHERE PAGES.ID = 1 LIMIT 1"

CODE:

<1924 get cached_model_demo:active_record:Page:1
>1924 sending key cached_model_demo:active_record:Page:1
>1924 END
development.log无SQL查询

CODE:

MemCache Get (0.000000)  active_record:Page:1这里取回的是我们刚才执行Page.find 1,2,缓存1的数据,如果没有,则会存储该数据,下次再查询直接从cache中获取。

三:更新
当该id的记录update,destroy都会更新cache,这个没什么好说的。

四:改进
这些功能太过于简单了,我们可以稍微对源码做点修改
一:缓存Page.find 的单条记录

CODE:

if CachedModel.use_memcache?
        record = Cache.get "active_record:#{name}:#{args.first}"

        #return cached model
        return record unless record.nil?
        #call super find
        record = super
        #store in memcache
        record.cache_store

        return record
      end
    end
二:find_by_sql的改进,空格,大小写必须一致才能生效
这条正则表达式太过于简单,我们可以稍微修改
1:) 忽略大小写 /i
2:) 忽略table的名称,只需要id=?几匹配
2;) 忽略空格


警告:
对于有关联的Model请谨慎使用cached_model,建议不使用。

[本帖最后由 martin 于 2007-11-12 09:38 编辑]

TAG:

axgle发布于2007-11-16 11:54:45
本文有没有必要放到还没有开设的新版"高级编程"里?

"高级编程":Ruby/Rails高级编程 面向对象设计 性能优化,企业级应用等.
小飞猪之Ruby窝 drive2me 发布于2007-11-16 15:34:30
收藏了,哈哈!谢谢2位高手!
我有红宝石 bayerlin 发布于2007-11-18 01:32:42
谢谢楼主,提供了这么好的ruby
幻 blackanger 发布于2007-11-24 17:10:07
文章不错。但是这最后的警告:
“对于有关联的Model请谨慎使用cached_model,建议不使用。”

一般还是有关联的model多啊。。。
我来说两句

(可选)

日历

« 2009-07-05  
   1234
567891011
12131415161718
19202122232425
262728293031 

数据统计

  • 访问量: 286
  • 日志数: 19
  • 建立时间: 2007-08-13
  • 更新时间: 2008-01-23

RSS订阅

Open Toolbar