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

本文介绍了一种在Rails应用中利用memcache实现关联表缓存的方法,通过monkeypatching ActiveRecord关联来提升性能。作者分享了自定义has_one_cached关联的具体实现,并讨论了其局限性和改进方案。
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的作用:

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

另外顺便提下,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的自动保存功能,真是救命功能阿 :idea:
计及源荷不确定性的综合能源生产单元运行调度与容量配置优化研究(Matlab代码实现)内容概要:本文围绕“计及源荷不确定性的综合能源生产单元运行调度与容量配置优化”展开研究,利用Matlab代码实现相关模型的构建与仿真。研究重点在于综合能源系统中多能耦合特性以及风、光等可再生能源出力和负荷需求的不确定性,通过鲁棒优化、场景生成(如Copula方法)、两阶段优化等手段,实现对能源生产单元的运行调度与容量配置的协同优化,旨在提高系统经济性、可靠性和可再生能源消纳能力。文中提及多种优化算法(如BFO、CPO、PSO等)在调度与预测中的应用,并强调了模型在实际能源系统规划与运行中的参考价值。; 适合人群:具备一定电力系统、能源系统或优化理论基础的研究生、科研人员及工程技术人员,熟悉Matlab编程和基本优化工具(如Yalmip)。; 使用场景及目标:①用于学习和复现综合能源系统中考虑不确定性的优化调度与容量配置方法;②为含高比例可再生能源的微电网、区域能源系统规划设计提供模型参考和技术支持;③开展学术研究,如撰写论文、课题申报时的技术方案借鉴。; 阅读建议:建议结合文中提到的Matlab代码和网盘资料,先理解基础模型(如功率平衡、设备模型),再逐步深入不确定性建模与优化求解过程,注意区分鲁棒优化、随机优化与分布鲁棒优化的适用场景,并尝试复现关键案例以加深理解。
内容概要:本文系统分析了DesignData(设计数据)的存储结构,围绕其形态多元化、版本关联性强、读写特性差异化等核心特性,提出了灵活性、版本化、高效性、一致性和可扩展性五大设计原则。文章深入剖析了三类主流存储方案:关系型数据库适用于结构化元信息存储,具备强一致性与高效查询能力;文档型数据库适配半结构化数据,支持动态字段扩展与嵌套结构;对象存储结合元数据索引则有效应对非结构化大文件的存储需求,具备高扩展性与低成本优势。同时,文章从版本管理、性能优化和数据安全三个关键维度提出设计要点,建议采用全量与增量结合的版本策略、索引与缓存优化性能、并通过权限控制、MD5校验和备份机制保障数据安全。最后提出按数据形态分层存储的核心结论,并针对不同规模团队给出实践建议。; 适合人群:从事工业设计、UI/UX设计、工程设计等领域数字化系统开发的技术人员,以及负责设计数据管理系统架构设计的中高级工程师和系统架构师。; 使用场景及目标:①为设计数据管理系统选型提供依据,合理选择或组合使用关系型数据库、文档型数据库与对象存储;②构建支持版本追溯、高性能访问、安全可控的DesignData存储体系;③解决多用户协作、大文件存储、历史版本管理等实际业务挑战。; 阅读建议:此资源以实际应用场景为导向,结合具体数据库类型和表结构设计进行讲解,建议读者结合自身业务数据特征,对比分析不同存储方案的适用边界,并在系统设计中综合考虑成本、性能与可维护性之间的平衡。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值