1, 项目中写缓存往往比较简单,但是清缓存比较麻烦,往往是清缓存条件一大堆,要加各种 sweeper, observer 来清... 2, 在 views 中,通过 page/action/fragment 来缓存,可是这些缓存方法对 API json 类的请求有一定的局限性
那么怎么缓存比较好呢?我的想法是: 1, 缓存不是用来清的,需要自动过期. 例如:product A 的缓存的 key 需要和 product A 的更新时间相关,那么在这个产品 A 更新后,下次取缓存的时候, 会去查找和更新时间绑定的缓存,也就是说 A 之前的缓存已经自动过期了,这次取会自动生成新的缓存。
2, View 中的 cache 不是最重要的,最应该缓存的地方是取数据层,然后再把这些缓存数据 render。 做为一个 Light Views/Controllers, Heavy Models 的程序来说,最应该缓存的是那些 model 的比较重量级方法。
假设下面的例子:
class Product def heavy_instance_method # ............. end
def self.heavy_class_method end end
Product.find(1).heavy_instance_method Product.heavy_class_method
假设上面的这两个方法都是比较耗时间,那么这两个方法可能就是一个被缓存的好例子. 如果让你去缓存这个方法,怎么做呢?最简单的就是:
class Product def heavy_instance_method Rails.cache.fetch("Product-heavy_instance_method-#{self.updated_at}") do .... end end end
这里用了这个实例的 updated_at 做为 key 来帮助这个方法自动过期。。。虽然简单,可是挺恶心的.... 另外如果这是个类方法,或者里面的缓存如果再和其它类有相互依赖的话,就会麻烦的多....
为了解决上面的问题,我写了个 Gem, 先看一下怎么用:
1, 将这个 gem 加到你的 Gemfile 中
gem 'qor_cache'
2, 定义你的配置文件
# config/qor/cache.rb scope :product do cache_method :heavy_instance_method cache_class_method :heavy_class_method end
3, 搞定了。。。。。。简单么?
先从配置文件看一下,那么这个 gem 做了什么呢?简单的讲:
scope :product 就是意味着 block 里面的操作是对 Product 这个 model 的操作 cache_method :heavy_instance_method 就是说要缓存 Product 的实例方法 heavy_instance_method cache_class_method :heavy_class_method 就是说要缓存 Product 的类方法 heavy_class_method
1, 对实例方法的缓存:
alias 以前的 heavy_instance_method 方法 重新生成一个 heavy_instance_method 然后在这个新的 heavy_instance_method 中,调用 Rails.cache, 以类名,方法名,更新时间为 key 进行缓存
2, 对类方法的缓存:
alias 以前的 heavy_class_method 方法 重新生成一个新的 heavy_class_method 类方法 然后在这个新的类方法中,调用 Rails.cache, 以类名,方法名,这个类的 cache_key 为 key 进行缓存 (PS: 这个类的 cache_key 是一个随机值,会在这个类发生任意保存,删除后更新为新随机值)
上面只是这个 gem 的一部分小功能,更多欢迎查看 README, 源代码。。。参考 https://github.com/qor/qor_cache 代码刚刚完成,木有经过再加工、再优化,大家先凑合着看吧... XD
本来想再多写点,把所有的功能全部描述一遍,可是实在写不下去了,不知道怎么表述,文字功底太差了,所以点到为止,欢迎探讨。。。真佩服那些一写就能写几万字的神人。。。XD