一步一步asp.net_緩存管理


緩存是性能優化一個非常重要的模塊,幾乎計算機哪里都會用到緩存,我們的網站緩存也是非常重要的一塊,緩存給網站帶來太大的性能提高,在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:      }

這樣我們一個簡單的完整的緩存模塊就設計完了,可以發現,這樣我們的緩存管理就容易得多了.

 

設計需要思考,程序員更需要思考,深入去學習軟件思想,架構,而不僅僅停留在簡單

的工作,軟件的復雜在於做大,軟件的擴大,讓軟件的復雜度成指數級增長,所以更需

要架構,深層次的去研究軟件理論,軟件精華!

 

整個項目也快接近尾聲了!下一個模塊就是刪除模塊的設計!然后總結總個項目!

呵呵!慢慢准備開始學習asp.net MVC!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM