十年磨一剑--缓存模块设计

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();

 

 

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

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值