`
jack
  • 浏览: 392752 次
  • 来自: 温州
社区版块
存档分类
最新评论

如何在has_one这样的关联上加入memcache 补丁

    博客分类:
  • Ruby
阅读更多
cache_fu 好用, 不过我有很多表间关联,我希望某些表的数据,通过关联(has_one,has_many)能够按id统一从memcache中读取或者写入. 该如何呢?

唯一的办法就是 monkey patch了,自己写吧.
第一个版本

require 'active_record/associations/belongs_to_association'
require 'active_record/associations/has_many_association'
module ActiveRecord
  class Base

    public

    def self.has_one_cached *params
      has_one *params # call the standard association
     
      assoc_name = params[0]
      

      define_method ("#{assoc_name}_with_cache") do
        
        assoc = self.class.reflections[assoc_name.to_sym]
        instance_values[assoc_name.to_s] || 
        (assoc.klass.get_cache(instance_values["#{assoc_name}_cached_id"]) if instance_values["#{assoc_name}_cached_id"] ) ||
          (a = HasOneAssociation.new(self, assoc) 
           assoc.klass.get_cache(a.id) 
           self.instance_variable_set("@#{assoc_name}_cached_id", a.id)
           self.instance_variable_set("@#{assoc_name}", a)
          )
    end

    # switch out the method. has_one -> has_one_with_cache
    alias_method_chain assoc_name, :cache
  end

  end
end


代码解释下,捡重要的说吧

1-7行,可以忽略
8 增加一个 has_one_cache的方法,使用起来等同于 has_one
17-23行的三个 "||"
第一个,就是读取AR中的缓存数据,这个没啥说的
第二个"||",是根据instance中保存的instance_values["#{assoc_name}_cached_id"]从memcache中获取对应的数据
第三个"||",就是第一次运行的时候,保存一个cache_id的变量和值,和对AR对象中缓存进行赋值

所以这里实际上是三级的缓存读取方式,先对象缓存,再memcache,如果还没有就直接读取数据库.

不过这里有个很明显的缺陷.要求instance长期存在,这个代码才能起作用.不过rails中对象的生命周期仅限于action,超出这个就没有啥用了.所以上面的代码,到头来只能在偶尔的情况下才能真正的用到memcache

解决办法是有,不过看各位是否喜欢的问题,就是把id也保存到memcache中.呵呵,很土的没有办法的办法.

于是上面的方法就改成了
 
define_method ("#{assoc_name}_with_cache") do
        
        assoc = self.class.reflections[assoc_name.to_sym]
        instance_values[assoc_name.to_s] || 
        (assoc.klass.get_cache(instance_values["#{assoc_name}_cached_id"]) if instance_values["#{assoc_name}_cached_id"] ) ||
        (id = assoc.klass.get_cache_ex("#{self.class.to_s}:#{self.id}:#{assoc_name}")
        assoc.klass.get_cache(id) if id)||
          (a = HasOneAssociation.new(self, assoc) 
           assoc.klass.get_cache(a.id) 
           assoc.klass.set_to_cache("#{self.class.to_s}:#{self.id}:#{assoc_name}",a.id,assoc.klass.ttl)
           self.instance_variable_set("@#{assoc_name}_cached_id", a.id)
           self.instance_variable_set("@#{assoc_name}", a)
          )
    end


增加了一个"||"
(id = assoc.klass.get_cache_ex("#{self.class.to_s}:#{self.id}:#{assoc_name}")
        assoc.klass.get_cache(id) if id)

先用memcache中获取id数据,在获取对应的纪录,很囧吧.

不过要看应用场合的,如果你需要访问的数据属于基础数据,永远不变的,或者长期不变的数据,这样的办法能够减轻数据库的访问负担,但是要注意的是"这样的方法不会比直接访问数据库要快"

这里重申下memcache的作用:

"memcache不会使得你的网站访问速度更快,只是为了减轻数据库的访问负担"

另外顺便提下,cache_fu中没有get_cache_ex的函数.这个函数是在robbin的提示下加进来,专门用于非id key的memcache数据读写的.

代码如下

def get_cache_ex(key, timeout = 60 * 30) 
      reset = cache_reset
      data = get_from_cache(key) unless reset
      return data unless data.nil? 
      if block_given?
        if data = yield
          test = true
          if data.instance_of? Array
            test = false if data.size ==0
          end
          set_to_cache(key, data, timeout) if test
        end
        return data  
      end

    end


还有,我这里的代码是参考http://groups.google.com/group/acts_as_cached/browse_thread/thread/5fefb2d2355a5048/25ea72ecd0d5a0c9
这个thread写的.

如果有has_many, belongs_to 的需求,还是参考google groups上的帖子来改写吧.

最后感谢下robbin的自动保存功能,真是救命功能阿
10
4
分享到:
评论
1 楼 robbin 2008-03-10  
在belongs_to关系上面做cache比较容易,has_one的确要麻烦一些。

相关推荐

    Windows_Memcache安装(XAMPP+Memcache+PHP)

    综上所述,Memcache作为一款成熟的分布式缓存系统,在提高Web应用性能和扩展性方面扮演了重要角色。在Windows环境下,结合XAMPP和PHP环境进行安装,只需要按照上述步骤,即可轻松配置Memcache服务。通过学习和使用...

    php_memcache 服务扩展

    $memcache = new Memcache; $memcache->connect("localhost",11211); echo "Server's version: " . $memcache->getVersion() . "\n"; $tmp_object = new stdClass; $tmp_object->str_attr = "test"; $tmp_object->...

    init_system_hem.rar_LINUX远程自动_php memcache_xcache

    标题中的“init_system_hem.rar_LINUX远程自动_php memcache_xcache”表明这是一个关于在Linux系统上自动化安装PHP、Memcache和Xcache等组件的教程。这个压缩包可能包含了一个脚本文件,即“init_system_hem.sh”,...

    Memcached与php_memcache.dll

    1. **分布式**: 数据分布在多个服务器上,通过哈希算法将键映射到特定服务器,实现负载均衡。 2. **内存存储**: 只在内存中存储数据,不持久化,保证了读取速度,但可能会丢失数据。 3. **自动过期**: 每个存储的...

    wampserver 2.4_x64 php_memcache.dll

    1. **wampserver**:WampServer是一款在Windows上运行的本地Web开发环境,包含了Apache、MySQL和PHP等组件,方便开发者在本地搭建Web服务器。 2. **php_memcache**:这是PHP的一个扩展,允许PHP程序与Memcached内存...

    php5.4.4-php_memcache

    3. **使用php_memcache扩展**:`php_memcache`提供了丰富的函数接口,例如`memcache_connect()`用于连接Memcache服务器,`memcache_set()`用于存储数据,`memcache_get()`用于获取数据,`memcache_delete()`用于删除...

    最新windows版php_memcache.dll和memcache.exe

    这个模块是平和php5.3的,在我的windowsxp php5.3.5上安装成功 里面有两个php库,一个php_memcache.dll.vc6 和一个php_memcache.dll.vc9 另外一个windows的memcache.exe文件,都是网上收集的,因为现在要找齐很不容易,...

    PHP7.x 8.0 memcache dll php_memcache.dll

    memcache是广泛应用于Web开发中的一个内存对象缓存系统,它能够提高网站性能,通过将数据存储在内存中,减少对数据库的访问,从而加快数据读取速度。 PHP的memcache扩展允许开发者在PHP应用程序中与memcached服务器...

    php_memcache.dll

    php_memcache.dll php_memcache.dll php_memcache.dll php_memcache.dll

    php5.4_memcache.dll 64位

    `memcached.exe`则是在本地运行Memcached服务的程序。 标签 "php memcached" 暗示了这两个技术的结合。PHP是一种流行的开源脚本语言,常用于Web开发,而Memcached则是一个内存缓存解决方案。两者结合可以提升基于...

    memcache.dll(5.2/5.3/5.4/5.5)

    $memcache = new Memcache; $memcache->connect("localhost",11211); echo "Server's version: " . $memcache->getVersion() . "\n"; $tmp_object = new stdClass; $tmp_object->str_attr = "test"; $tmp_...

    各种版本 PHP memcache_dll .zip

    例如,`memcache_set()`函数用于将键值对存储到缓存中,而`memcache_get()`用于根据键从缓存中获取数据。 在实际应用中,Memcache扩展可以提升网站性能,因为频繁访问的数据可以从内存中快速获取,而不是每次都从...

    php7.1x memcache.dll

    测试环境 php7.1.11 ts vc14 x64 ,直接放到php安装目录的ext文件夹下 即可

    win_php_memcache.dll集合

    在处理大量数据时,高效的缓存机制是必不可少的,而Memcache就是这样的一个内存对象缓存系统。"win_php_memcache.dll集合"为我们提供了从PHP 5.3到PHP 7.1版本,涵盖32位和64位系统的Memcache扩展,确保了在不同环境...

    php_memcache-5.2 5.3 5.4

    - 配置过程中,需要修改php.ini文件,加入`extension=memcache.so`(或根据实际情况调整为.dll文件),然后重启PHP服务使配置生效。 2. **基本用法**: - 初始化Memcached连接:`$m = new Memcache;`,然后通过`$...

    memcache_php使用测试

    **MEMCACHE_COMPRESSED** 是一个整型常量,用于在使用`Memcache::set()`, `Memcache::add()`和相关方法时开启压缩功能,这有助于在网络传输过程中减小数据包的大小,从而提高数据读写效率,特别适用于处理大量文本或...

    php7.1和7.2的memcache.dll文件

    之后,在php.ini中加入配置 extension=php_memcache.dll和 [Memcache] memcache.allow_failover = 1 memcache.max_failover_attempts=20 memcache.chunk_size =8192 memcache.default_port = 11211

    windows下32位php-5.4.x的memcache.dll扩展

    windows下的memcache服务,在windows平台下搭建wamp或者php环境的时候,如果没有memcache服务,会报错找不到memcache()方法,下载并解压这个压缩包,将memcache.exe放到任意位置,然后使用管理员权限在命令行转到...

    php_memcache-2.2.7-7.0-nts-vc14-x64 扩展DLL

    然后,通过PHP代码可以调用如`memcache_connect()`、`memcache_set()`等函数来连接Memcache服务器并存储或获取数据。这极大地提高了Web应用程序的数据处理速度,减少了数据库的压力。 总结来说,...

Global site tag (gtag.js) - Google Analytics