十年磨一劍--從程序員到架構師

一个.net程序员,一个企业应用的开发者,喜欢系统架构,数据库,领域驱动,面向对象,表现层技术。关注重用的理论和实践。设计原则:简单,快速,适应变化能力强,表现层灵活多变...

博客园 首页 新随笔 联系 订阅 管理

1.缓存是提高程序性能的一种非常重要的方式,其原理就是通过空间换取时间,在内存中存储CPU的运算结果,这样下次相同的运算时,可直接从缓存中提取,提高系统性能。

 

2.以下情况一般都会用到缓存:数据库查询,系统配置模块,对象池等。

3.缓存运用的一些特点:运算比较復杂或耗时,运算结果是与运算条件一一对应的(如通过账号查询user,账号与DataSet对象是一一对应的),但是其数量是可变的(缓存的项次与Client的查询请求和资料库中user的数量有关)。

4.如果某个类出现以下类似代码:

 1 Dictionary<string,object> _store;
 2 
 3  public object GetSomeThing(string key){
 4       if(_store.ContainsKey(key))
 5            return _store[key];
 6       else{
 7               object o = 计算(key);
 8               _store.Add(key,o);
 9               return o;
10       }
11 }

 

那么就要考虑这是否属于缓存的范畴了。

 

5.缓存设计有关的概念:
a.计算类:如资料库查询,获取配置,创建对象等工具类别,该类或模块不依赖缓存类,只完成运算,缓存类对其是透明的。
b.Client:请求计算类进行计算,并得到结果。Client只依赖计算类,缓存对於该类来说也是透明的,即它不知道运算结果是从缓存中得来,还是直接运算得来的。
c.缓存工具类:该类是一个独立的工具类,完成如存储,获取,清空,多线程读写,过期策略等缓存功能。
在asp.net中可以利用已经实现多线程读写完全,支持丰富的过期策略的HttpCache对象,对其进行简单的包装就可以完成了。
如果是需要缓存大数据量的系统,考虑现在比较流行的key/value存储memcached,实现多主机缓存等更稳定,扩展性更强的专业方案。

d.具体缓存类:
该类实现在Client端请求计算类计算时进行拦截,如果该运算结果已在缓存中,则直接命中缓存完成,如果无运算结果,则调用计算类得到结果,并将结果存入缓存,以备下次再用。

该类的另一个重要部份就是要负责缓存的清空,具体清空方式与实际的计算类有关,如配置获取类的缓存依赖于配置是否修改。数据库查询结果的缓存可能与table有关,因此侦测到对该table的增,删,改时,要清空相应的缓存,另外查询结果可能太多,也可以通过设定低优先级以及固定过期策略来自动清空缓存。

由于具体缓存类依赖于计算类,因此计算类必须是一种通用的工具类,否则会造成大量的具体缓存类,增加復杂性。

e.具体缓存类与计算类的结合方式:
这是一种典型的AOP应用,如果不喜欢aop框架的复杂与笨拙,可以使用Decorator模式来完成计算类的拦截。

 

6.计算类示例:对象创建类

 1 public class ObjectFactory
 2 {
 3     //Decorator构建
 4      public static readonly ObjectFactory Instance 
         = new CacheObjectFactory(new ObjectFactory());
 5     
 6     public T Create<T>(string objectID)
 7     {
 8           T ret = 创建对象...
 9           return ret;
10     }
11 }

 


7.具体缓存类(Decorator模式实现)

 1 public class CacheObjectFactory:ObjectFactory
 2 {
 3     ObjectFactory _orgFactory;    //被包装的计算类
 4      CacheTool  _cache;            //缓存工具类
 5      public CacheObjectFactory(ObjectFactory orgFactory)
 6     {
 7         _cache = new HttpCache(this.GetType().FullName);
 8         _orgFactory = orgFactory;
 9     }
10 
11     public T Create<T>(string objectID){
12           T ret = _cache.Get<T>(objectID);
13           if(ret==null){   //根据具体情况还要考虑是null还是没有cache,以及lock策略
14                ret = _orgFactory.Create<T>(objectID);
15               _cache.Set(objectID,T);
16           }
17           return ret;
18     }
19 }

 


8.客户端调用示例代码

1 BusClass bus = ObjectFactory.Instance.Create<BusClass>("BusClass");
2 bus.CallSomeMethod();

 

 

缓存只是一种提高系统性能的工具,将缓存独立出来设计后,可以使缓存模块在整个系统中透明。这样,在开发某一模块时,可以将与主逻辑无关的系统优化的缓存延后。待主逻辑功能实现后,再专门来考虑如何使用缓存提升模块的性能。而专门的缓存模块设计,对于缓存的重用,也是有很大帮助的。

 

 

posted on 2009-12-31 12:12  Kevin Zou  阅读(3459)  评论(6编辑  收藏  举报