最近研究了一下 rails的cache设计,发现其中一些不尽如人意的地方:
* cache expiry 编写繁琐
* 分页缓存的清除,现有cache实现的支持都不是很完善
* 在一次清除大量缓存的时候,脏数据读的问题。
我查阅了一些blog以及相关的文章,从他们的抱怨和设计中得到一些启发,我觉得cache可以做得更好,更智能,更能够减少开发人员的工作量。 下面是我设计思路的一些草稿,如果深入分析,觉得可行的话,就可以动手做他:
* 支持 cache 分组。
* 支持简化的expiry rules
* 适当的设计减少一次清除大量缓存时脏数据读的概率和时间窗
* 仅考虑memcache的支持。
* 尽可能在现有框架的基础上做简单的扩展,减少开发量。
支持cache 分组可以同时带来很多好处,第一,支持分页缓存的一次expire。同时也有利于“减少脏数据读的时间窗”,cache分组的设计是整个设计的关键思路之一。下面来谈谈cache分组的设计:
* 内存开辟一个hash。key是group ID。value是一个特有的Group对象,这个Group对象的设计目的是[b]尽可能简便并且尽快地[/b] 清除同一组的所有cache key。
* 要expire 同组所有脏缓存数据,有两种策略: 1) 按照cacheKey 逐一清楚 2) 不清除,而是加版本号
第一种策略意味着需要保存Group和 CacheKey的一对多关系,这个保存可能需要通过数据库来保存,带来的复杂和性能开销似乎不是上选。
第二种策略不用清除缓存,也不用查询数据库。但这种策略也需要做一些工作,在加入缓存的时候,我们需要修改原有的cacheKey,在后面加上Version=1这样版本标识。get cache的时候
也需要做同样的工作。当expire脏Group的时候,只需要将Group对象上的version属性递增一。原有的脏数据通过memcache的自动清理策略来自动清除。
从这个分析来看,我觉得选择第二种策略更好。
整个smart_cache的设计实现应该在现有的cache实现的基础上,通过alias_method(rails的AOP)加入我们自己的中间逻辑。这样开发量最少。
设计中的另外一个关键点是 expiry rules的设计,目前rails cache的expire的编写已经比较简单了,我们只需要更进一步,初步
设计如下,在config目录下增加一个 cache_expiry_rules.rb,示例代码如下:
[code]
SmartCache::Rules do |config|
config.add_rule(:group=>"user list",:expire_rules=>[cud_rule(User,Department,Room),rule(User.update*)])
config.add_rule(:group=>"department list",:expire_rules=>[cud_rule(Department,Room),rule(Department.update*)])
end[/code]
上面代码中的关键部分:
[b]:expire_rules=>[cud_rule(User,Department,Room),rule(User.update*)])[/b]
其中,cud表示某个model对象上的create,update,delete方法完成后。
后面的rule(user.update*) 表示UserModel上的符合规则的某些方法被调用了之后。
原有的缓存的方法 cache 需要最后增加一个属性 :group=>"your group",比如 cache fragment 的编写
[code] <% cache :controller="user",:action=>"list",:page=>"params[:page]",:group=>"user list" do %>
//rhtml code here to renderring view
<% end %>
caches_action :list, :show,:group="test group"
[/code]
参考文章:
* web agile devel....
* [url]http://www.railsenvy.com/2007/2/28/rails-caching-tutorial[/url]
* [url]http://blog.leetsoft.com/2007/5/22/the-secret-to-memcached[/url]
* [url]http://blog.craigambrose.com/past/2007/11/13/caching_makes_your_brain_explode/[/url]
* [url]http://cfis.savagexi.com/articles/2007/09/05/rails-unusual-architecture[/url]
.............
* cache expiry 编写繁琐
* 分页缓存的清除,现有cache实现的支持都不是很完善
* 在一次清除大量缓存的时候,脏数据读的问题。
我查阅了一些blog以及相关的文章,从他们的抱怨和设计中得到一些启发,我觉得cache可以做得更好,更智能,更能够减少开发人员的工作量。 下面是我设计思路的一些草稿,如果深入分析,觉得可行的话,就可以动手做他:
* 支持 cache 分组。
* 支持简化的expiry rules
* 适当的设计减少一次清除大量缓存时脏数据读的概率和时间窗
* 仅考虑memcache的支持。
* 尽可能在现有框架的基础上做简单的扩展,减少开发量。
支持cache 分组可以同时带来很多好处,第一,支持分页缓存的一次expire。同时也有利于“减少脏数据读的时间窗”,cache分组的设计是整个设计的关键思路之一。下面来谈谈cache分组的设计:
* 内存开辟一个hash。key是group ID。value是一个特有的Group对象,这个Group对象的设计目的是[b]尽可能简便并且尽快地[/b] 清除同一组的所有cache key。
* 要expire 同组所有脏缓存数据,有两种策略: 1) 按照cacheKey 逐一清楚 2) 不清除,而是加版本号
第一种策略意味着需要保存Group和 CacheKey的一对多关系,这个保存可能需要通过数据库来保存,带来的复杂和性能开销似乎不是上选。
第二种策略不用清除缓存,也不用查询数据库。但这种策略也需要做一些工作,在加入缓存的时候,我们需要修改原有的cacheKey,在后面加上Version=1这样版本标识。get cache的时候
也需要做同样的工作。当expire脏Group的时候,只需要将Group对象上的version属性递增一。原有的脏数据通过memcache的自动清理策略来自动清除。
从这个分析来看,我觉得选择第二种策略更好。
整个smart_cache的设计实现应该在现有的cache实现的基础上,通过alias_method(rails的AOP)加入我们自己的中间逻辑。这样开发量最少。
设计中的另外一个关键点是 expiry rules的设计,目前rails cache的expire的编写已经比较简单了,我们只需要更进一步,初步
设计如下,在config目录下增加一个 cache_expiry_rules.rb,示例代码如下:
[code]
SmartCache::Rules do |config|
config.add_rule(:group=>"user list",:expire_rules=>[cud_rule(User,Department,Room),rule(User.update*)])
config.add_rule(:group=>"department list",:expire_rules=>[cud_rule(Department,Room),rule(Department.update*)])
end[/code]
上面代码中的关键部分:
[b]:expire_rules=>[cud_rule(User,Department,Room),rule(User.update*)])[/b]
其中,cud表示某个model对象上的create,update,delete方法完成后。
后面的rule(user.update*) 表示UserModel上的符合规则的某些方法被调用了之后。
原有的缓存的方法 cache 需要最后增加一个属性 :group=>"your group",比如 cache fragment 的编写
[code] <% cache :controller="user",:action=>"list",:page=>"params[:page]",:group=>"user list" do %>
//rhtml code here to renderring view
<% end %>
caches_action :list, :show,:group="test group"
[/code]
参考文章:
* web agile devel....
* [url]http://www.railsenvy.com/2007/2/28/rails-caching-tutorial[/url]
* [url]http://blog.leetsoft.com/2007/5/22/the-secret-to-memcached[/url]
* [url]http://blog.craigambrose.com/past/2007/11/13/caching_makes_your_brain_explode/[/url]
* [url]http://cfis.savagexi.com/articles/2007/09/05/rails-unusual-architecture[/url]
.............