_one

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

转自:http://www.cnblogs.com/mysweet/archive/2012/06/05/2536372.html

缓存是性能优化一个非常重要的模块,几乎计算机哪里都会用到缓存,我们的网站缓存也是非常重要的一块,缓存给网站带来太大的性能提高,在asp.net中的Cache,同样有各种缓存依赖,文件缓存依赖,数据库缓存依赖等等,我们的缓存管理就成了一个很重要的问题,当我们的网站小的时候,我们采用asp.net内置的Cache就可以了,但是如果我们的网站进一步扩展,单独分布式缓存服务器的时候,我们采用Memcached的时候,我们又不得不大量去修改我们的代码,这就是我之前写死缓存的问题,如下图:

201204241516421820

这里配置缓存,如果,现在把asp.net缓存改为Memcached的时候,我们就坑爹了!

因此,很多人就开始抱怨了,改改改!

做网站就是改改改!

呵呵!

这就是一个非常重要的问题,程序员的工作似乎都在开发,修改代码中进行,而往往总是抱怨似乎没什么技术含量,天天做重复性的工作!

这就是oo的开始,这时候就需要慢慢开始学习软件工程和面向对象,

以前的层次,学习这些东西,一般也就是停留在理论层面上,软件工程,面向对象,总被人强调有用,但是总说不出为什么有用!

一旦一个软件,网站做大,就难得多得多,考虑的东西也深得多得多!这就是软件更需要大局观,需要考虑全局,考虑复用,考虑架构!

软件理论,很多人感觉很虚很虚,我刚开始也是这么感觉的,但是一旦你熟练了程序员的工作,写代码写CRUD写多了就容易出现瓶颈,感觉似乎软件都是增删改查和复杂的业务,各种技术浅尝则止,感觉无非如此,无非如此,还不如去学硬件方面的,呵呵!

而这却离软件的思想越离越远,于是乎,出现了大量的精通asp.net,精通asp.net mvc,精通wpf,Silverlight,精通一大堆的人,无非也就是能写点增删改查,这也能叫做精通..........能不能自己写框架,写架构?看博客园那些技术牛人的代码就是一种享受,他们的代码,几乎隔一段时间都会发现技术的演变,重构.这就是造诣!

于是更多的人开始不淡定,我敬佩博客园那么多专研同一种技术动不动就是好多年的牛人.

 

 

话题扯远了!

最近看了基本关于这方面的书,感触挺深的!

 

我们的缓存这时候更应该抽象出来,形成一种组件,以适应日后分布式缓存,而且也方便调用.

在DBO数据库连接类设计中,曾经采用工厂模式的方式以适应多种数据库的设计,

image

我们的缓存也可以设计成复用设计,支持多种缓存模式,

这时候,看了一下.net应用架构设计原则,模式与实践,

感觉那种缓存模式蛮好的,我也尝试着做了部分修改.

 

image

 

ICacheStorage就是通用缓存接口,

 

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:   
   6:  namespace CacheStorage
   7:  {
   8:      /// <summary>
   9:      /// 缓存接口
  10:      /// </summary>
  11:     public interface ICacheStorage
  12:      {
  13:          #region 缓存操作
  14:          /// <summary>
  15:          /// 添加缓存
  16:          /// </summary>
  17:          /// <param name="key"></param>
  18:          /// <param name="value"></param>
  19:          void Insert(string key, object value);
  20:          /// <summary>
  21:          /// 添加缓存(默认滑动时间为20分钟)
  22:          /// </summary>
  23:          /// <param name="key">key</param>
  24:          /// <param name="value">value</param>
  25:          /// <param name="expiration">绝对过期时间</param>
  26:          void Insert(string key, object value, DateTime expiration);
  27:          /// <summary>
  28:          /// 添加缓存
  29:          /// </summary>
  30:          /// <param name="key">key</param>
  31:          /// <param name="value">value</param>
  32:          /// <param name="expiration">过期时间</param>
  33:          void Insert(string key, object value, TimeSpan expiration);
  34:          /// <summary>
  35:          /// 获得key对应的value
  36:          /// </summary>
  37:          /// <param name="key"></param>
  38:          /// <returns></returns>
  39:          object Get(string key);
  40:          /// <summary>
  41:          /// 根据key删除缓存
  42:          /// </summary>
  43:          /// <param name="key"></param>
  44:          void Remove(string key);
  45:          /// <summary>
  46:          /// 缓存是否存在key的value
  47:          /// </summary>
  48:          /// <param name="key">key</param>
  49:          /// <returns></returns>
  50:          bool Exist(string key);
  51:          /// <summary>
  52:          /// 获取所有的缓存key
  53:          /// </summary>
  54:          /// <returns></returns>
  55:          List<string> GetCacheKeys();
  56:          /// <summary>
  57:          /// 清空缓存
  58:          /// </summary>
  59:          void Flush();
  60:          
  61:          #endregion
  62:      }
  63:    
  64:  }
默认的asp.net缓存
   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  using System.Web;
   6:  using System.Web.Caching;
   7:  using System.Collections;
   8:  namespace CacheStorage
   9:  {
  10:      /// <summary>
  11:      /// 默认的asp.net中Cache
  12:      /// </summary>
  13:       class DefaultCacheAdapter : ICacheStorage
  14:      {
  15:          /// <summary>
  16:          /// 当前请求上下文
  17:          /// </summary>
  18:          private static HttpContext context = null;
  19:          /// <summary>
  20:          /// 构造函数
  21:          /// </summary>
  22:          static DefaultCacheAdapter()
  23:          {
  24:              context = HttpContext.Current;
  25:          }
  26:          #region ICacheStorage 成员
  27:          /// <summary>
  28:          /// 添加缓存
  29:          /// </summary>
  30:          /// <param name="key">key</param>
  31:          /// <param name="value">value</param>
  32:          public void Insert(string key, object value)
  33:          {
  34:              context.Cache.Insert(key, value);
  35:          }
  36:          /// <summary>
  37:          /// 添加缓存(默认滑动时间为20分钟)
  38:          /// </summary>
  39:          /// <param name="key">key</param>
  40:          /// <param name="value">value</param>
  41:          /// <param name="expiration">绝对过期时间</param>
  42:          public void Insert(string key, object value, DateTime expiration)
  43:          {
  44:              context.Cache.Insert(key, value, null, expiration, TimeSpan.FromMinutes(20), CacheItemPriority.Normal, null);
  45:          }
  46:          /// <summary>
  47:          /// 添加缓存
  48:          /// </summary>
  49:          /// <param name="key">key</param>
  50:          /// <param name="value">value</param>
  51:          /// <param name="expiration">过期时间</param>
  52:          public void Insert(string key, object value, TimeSpan expiration)
  53:          {
  54:              context.Cache.Insert(key, value, null, DateTime.MaxValue, expiration, CacheItemPriority.Normal, null);
  55:   
  56:          }
  57:          /// <summary>
  58:          /// 获取当前缓存中key的值
  59:          /// </summary>
  60:          /// <param name="key"></param>
  61:          /// <returns></returns>
  62:          public object Get(string key)
  63:          {
  64:              return context.Cache[key];
  65:   
  66:          }
  67:          /// <summary>
  68:          /// 删除当前key的value值
  69:          /// </summary>
  70:          /// <param name="key"></param>
  71:          public void Remove(string key)
  72:          {
  73:              if (Exist(key))
  74:                  context.Cache.Remove(key);
  75:          }
  76:          /// <summary>
  77:          /// 缓存是否存在key的value
  78:          /// </summary>
  79:          /// <param name="key">key</param>
  80:          /// <returns></returns>
  81:          public bool Exist(string key)
  82:          {
  83:              if (context.Cache[key] == null)
  84:                  return false;
  85:              else
  86:                  return true;
  87:          }
  88:          /// <summary>
  89:          /// 获取所有的缓存key
  90:          /// </summary>
  91:          /// <returns></returns>
  92:          public List<string> GetCacheKeys()
  93:          {
  94:              List<string> keys = new List<string>();
  95:              IDictionaryEnumerator ide = context.Cache.GetEnumerator();
  96:              while (ide.MoveNext())
  97:              {
  98:                  keys.Add(ide.Key.ToString());
  99:              }
 100:              return keys;
 101:          }
 102:          /// <summary>
 103:          /// 清空缓存
 104:          /// </summary>
 105:          public void Flush()
 106:          {
 107:              foreach (string s in GetCacheKeys())
 108:              {
 109:                  Remove(s);
 110:              }
 111:          }
 112:          #endregion
 113:      }
 114:  }
分布式Memcached
   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  using Enyim.Caching;
   6:  using Enyim.Caching.Memcached;
   7:   
   8:  namespace CacheStorage
   9:  {
  10:      /// <summary>
  11:      /// 分布式Memcached缓存
  12:      /// </summary>
  13:      class MemcachedCache : ICacheStorage
  14:      {
  15:          /// <summary>
  16:          /// 分布式缓存客户端Cache
  17:          /// </summary>
  18:          private MemcachedClient Cache;
  19:          public MemcachedCache()
  20:          {
  21:              Cache = new MemcachedClient();
  22:              List<string> keys = new List<string>();
  23:              Cache.Store(StoreMode.Add, "keys", keys);
  24:          }
  25:          #region ICacheStorage 成员
  26:          /// <summary>
  27:          /// 插入缓存
  28:          /// </summary>
  29:          /// <param name="key">key</param>
  30:          /// <param name="value">value</param>
  31:          public void Insert(string key, object value)
  32:          {
  33:              Cache.Store(StoreMode.Set, key, value);
  34:   
  35:          }
  36:          /// <summary>
  37:          /// 插入缓存
  38:          /// </summary>
  39:          /// <param name="key">key</param>
  40:          /// <param name="value">value</param>
  41:          /// <param name="expiration">绝对过期时间</param>
  42:          public void Insert(string key, object value, DateTime expiration)
  43:          {
  44:              Cache.Store(StoreMode.Set, key, value, expiration);
  45:              Updatekeys(key);
  46:          }
  47:          /// <summary>
  48:          /// 插入缓存
  49:          /// </summary>
  50:          /// <param name="key">key</param>
  51:          /// <param name="value">value</param>
  52:          /// <param name="expiration">过期时间</param>
  53:          public void Insert(string key, object value, TimeSpan expiration)
  54:          {
  55:              Cache.Store(StoreMode.Set, key, value, expiration);
  56:              Updatekeys(key);
  57:          }
  58:          /// <summary>
  59:          /// 根据key获取value
  60:          /// </summary>
  61:          /// <param name="key">key</param>
  62:          /// <returns></returns>
  63:          public object Get(string key)
  64:          {
  65:              return Cache.Get(key);
  66:          }
  67:          /// <summary>
  68:          /// 删除key的缓存的值
  69:          /// </summary>
  70:          /// <param name="key">key</param>
  71:          public void Remove(string key)
  72:          {
  73:              if (Exist(key))
  74:                  Cache.Remove(key);
  75:          }
  76:          /// <summary>
  77:          /// 检验key是否存在
  78:          /// </summary>
  79:          /// <param name="key"></param>
  80:          /// <returns></returns>
  81:          public bool Exist(string key)
  82:          {
  83:              if (Cache.Get(key) != null)
  84:                  return true;
  85:              else return false;
  86:          }
  87:          /// <summary>
  88:          /// 获取所有的key
  89:          /// </summary>
  90:          /// <returns></returns>
  91:          public List<string> GetCacheKeys()
  92:          {
  93:              return Cache.Get("keys") as List<string>;
  94:   
  95:          }
  96:          /// <summary>
  97:          /// 清空缓存
  98:          /// </summary>
  99:          public void Flush()
 100:          {
 101:              foreach (string s in GetCacheKeys())
 102:              {
 103:                  Remove(s);
 104:              }
 105:          }
 106:          /// <summary>
 107:          /// 更新key
 108:          /// </summary>
 109:          /// <param name="key">key</param>
 110:          private void Updatekeys(string key)
 111:          {
 112:              List<string> keys = new List<string>();
 113:              //读取本地keys
 114:              if (Cache.Get("keys") != null)
 115:                  keys = Cache.Get("keys") as List<string>;
 116:              //如果keys中不存在
 117:              if (!keys.Contains(key.ToLower()))
 118:                  keys.Add(key);
 119:              Cache.Store(StoreMode.Set, "keys", keys);
 120:          }
 121:          #endregion
 122:      }
 123:  }

 

缓存工厂,用来创建缓存

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  using System.Configuration;
   6:   
   7:  namespace CacheStorage
   8:  {
   9:   
  10:      /// <summary>
  11:      /// 缓存工厂
  12:      /// </summary>
  13:      public class CacheFactory
  14:      {
  15:          /// <summary>
  16:          /// 缓存类别
  17:          /// </summary>
  18:          public enum CacheType
  19:          {
  20:              //默认缓存
  21:              DefaultCache = 0,
  22:              /// <summary>
  23:              /// 分布式Memcached缓存
  24:              /// </summary>
  25:              MemcachedCache = 1
  26:          }
  27:          /// <summary>
  28:          /// 初始化
  29:          /// </summary>
  30:          /// <returns></returns>
  31:          public static ICacheStorage CreateCacheFactory()
  32:          {
  33:             string Cache=ConfigurationManager.AppSettings["CacheType"];
  34:             if (CacheType.MemcachedCache.ToString ()== Cache)
  35:             {
  36:                 return new MemcachedCache();
  37:             }
  38:             else
  39:                 return new DefaultCacheAdapter();
  40:          }
  41:      }
  42:  }
在webconfig中配置缓存类别,
然后在客户端,配置缓存
image

image

客户端调用就见得多了,

image

然后,我们的后台需要一个管理缓存的模块,

image

可以动态配置,内容页的缓存时间,等等

   1:  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   2:   
   3:  <html xmlns="http://www.w3.org/1999/xhtml">
   4:  <head>
   5:      <title>缓存管理</title>
   6:       <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
   7:      <link href="../css/demo.css" rel="stylesheet" type="text/css" />
   8:   
   9:      <script src="../scripts/jquery-1.6.2.min.js" type="text/javascript"></script>
  10:   
  11:      <script src="../scripts/miniui/miniui.js" type="text/javascript"></script>
  12:   
  13:      <link href="../scripts/miniui/themes/default/miniui.css" rel="stylesheet" type="text/css" />
  14:      <link href="../scripts/miniui/themes/icons.css" rel="stylesheet" type="text/css" />
  15:  </head>
  16:  <body>
  17:    <div class="mini-toolbar">
  18:          <h1>
  19:              缓存管理</h1>
  20:      </div>
  21:      <div id="datagrid1" class="mini-datagrid" style="width: 100%; height: 400px;" allowresize="true"
  22:          url="Data/UrlInfo.ashx?method=SearchCacheInfo" idfield="Id" multiselect="false">
  23:          <div property="columns">
  24:              <div type="checkcolumn">
  25:              </div>
  26:              <div id="deal" name="action" width="100" headeralign="center" align="center" renderer="onActionRenderer"
  27:                  cellstyle="padding:0;">
  28:                  操作
  29:              </div>
  30:              <div field="Name" width="100" headeralign="center" allowsort="true">
  31:                  缓存标识</div>
  32:              <div field="Day" width="100"> <input  class="mini-spinner"  property="editor" value="0"  minValue="1" maxValue="365" />
  33:                  天</div>
  34:              <div field="Hour" width="100">小时
  35:                  <input  class="mini-spinner"  property="editor"  minValue="1" maxValue="365" /></div>
  36:              <div field="Title" width="100">
  37:                  缓存名称</div>
  38:          </div>
  39:      </div>
  40:   
  41:      <script type="text/javascript">
  42:          mini.parse();
  43:   
  44:          var grid = mini.get("datagrid1");
  45:        //  grid.load();
  46:          grid.sortBy("Name", "desc");
  47:   
  48:          grid.set({ footerStyle: "padding-right:10px;" });
  49:    function onActionRenderer(e) {
  50:              var grid = e.sender;
  51:              var record = e.record;
  52:              var uid = record._uid;
  53:              var rowIndex = e.rowIndex;
  54:   
  55:              var s = ' <a class="Edit_Button" href="javascript:editRow(\'' + uid + '\')">编辑</a>';
  56:   
  57:              if (grid.isEditingRow(record)) {
  58:                  s = '<a class="Update_Button" href="javascript:updateRow(\'' + uid + '\')">更新</a>'
  59:                      + '<a class="Cancel_Button" href="javascript:cancelRow(\'' + uid + '\')">取消</a>'
  60:              }
  61:              return s;
  62:          }
  63:            function editRow(row_uid) {
  64:              var row = grid.getRowByUID(row_uid);
  65:              if (row) {
  66:                  grid.cancelEdit();
  67:                  grid.beginEditRow(row);
  68:              }
  69:          }
  70:          function cancelRow(row_uid) {            
  71:              grid.reload();
  72:          }
  73:          function updateRow(row_uid) {
  74:              var row = grid.getRowByUID(row_uid);
  75:              var rowData = grid.getEditRowData(row);
  76:              grid.loading("保存中,请稍后......");
  77:              var json=mini.encode(rowData);
  78:              $.ajax({
  79:                  url: "Data/UrlInfo.ashx?method=UpdateCacheInfo",
  80:                  data: {CacheInfo:json },
  81:                  success: function (text) {
  82:                      grid.reload();
  83:                  
  84:                  },
  85:                  error: function (jqXHR, textStatus, errorThrown) {
  86:                      alert(jqXHR.responseText);
  87:                  }
  88:              });
  89:   
  90:          }
  91:    
  92:        
  93:   
  94:   
  95:      </script>
  96:   
  97:  </body>
  98:  </html>
后台处理:
   1:    /// <summary>
   2:      /// 更新缓存信息
   3:      /// </summary>
   4:      /// <param name="context"></param>
   5:      public void UpdateCacheInfo(HttpContext context)
   6:      {
   7:          string CacheInfo = context.Request["CacheInfo"];
   8:        CacheInfo=CacheInfo.Trim(new char[] { '[', ']' });
   9:        JObject o = JObject.Parse(CacheInfo);
  10:      string Id=(string)o.SelectToken("Id");
  11:      int Day = (int)o.SelectToken("Day");
  12:      int Hour = (int)o.SelectToken("Hour");
  13:      context.Response.Write(new CacheManage().UpdateCacheInfo(Id, Day, Hour));
  14:      }
  15:      /// <summary>
  16:      ///  查询缓存信息
  17:      /// </summary>
  18:      /// <param name="context"></param>
  19:      public void SearchCacheInfo(HttpContext context)
  20:      {
  21:          //查询条件
  22:         // string key = context.Request["key"];
  23:          //分页
  24:          int pageIndex = Convert.ToInt32(context.Request["pageIndex"]);
  25:          int pageSize = Convert.ToInt32(context.Request["pageSize"]);
  26:          ////字段排序
  27:          //String sortField = context.Request["sortField"];
  28:          //String sortOrder = context.Request["sortOrder"];
  29:          //JSON 序列化
  30:          string json = new CacheManage().GetCacheAllInfoForMiniUIJson(pageIndex,pageSize);
  31:          context.Response.Write(json);
  32:      }

这样我们一个简单的完整的缓存模块就设计完了,可以发现,这样我们的缓存管理就容易得多了.

 

设计需要思考,程序员更需要思考,深入去学习软件思想,架构,而不仅仅停留在简单

的工作,软件的复杂在于做大,软件的扩大,让软件的复杂度成指数级增长,所以更需

要架构,深层次的去研究软件理论,软件精华!

 

 

 

 

posted on 2012-06-28 10:31  _one  阅读(394)  评论(0编辑  收藏  举报