设为首页 收藏本站
查看: 1249|回复: 0

[经验分享] 如何在has_one这样的关联上加入memcache 补丁

[复制链接]

尚未签到

发表于 2017-4-16 10:37:44 | 显示全部楼层 |阅读模式
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的自动保存功能,真是救命功能阿 DSC0000.gif

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-365221-1-1.html 上篇帖子: Memcache缓存与Mongodb数据库的优势和应用(转载) 下篇帖子: 检查memcache,如果停掉了。就重新启动
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表