緩存是性能優化一個非常重要的模塊,幾乎計算機哪里都會用到緩存,我們的網站緩存也是非常重要的一塊,緩存給網站帶來太大的性能提高,在asp.net中的Cache,同樣有各種緩存依賴,文件緩存依賴,數據庫緩存依賴等等,我們的緩存管理就成了一個很重要的問題,當我們的網站小的時候,我們采用asp.net內置的Cache就可以了,但是如果我們的網站進一步擴展,單獨分布式緩存服務器的時候,我們采用Memcached的時候,我們又不得不大量去修改我們的代碼,這就是我之前寫死緩存的問題,如下圖:
這里配置緩存,如果,現在把asp.net緩存改為Memcached的時候,我們就坑爹了!
因此,很多人就開始抱怨了,改改改!
做網站就是改改改!
呵呵!
這就是一個非常重要的問題,程序員的工作似乎都在開發,修改代碼中進行,而往往總是抱怨似乎沒什么技術含量,天天做重復性的工作!
這就是oo的開始,這時候就需要慢慢開始學習軟件工程和面向對象,
以前的層次,學習這些東西,一般也就是停留在理論層面上,軟件工程,面向對象,總被人強調有用,但是總說不出為什么有用!
一旦一個軟件,網站做大,就難得多得多,考慮的東西也深得多得多!這就是軟件更需要大局觀,需要考慮全局,考慮復用,考慮架構!
軟件理論,很多人感覺很虛很虛,我剛開始也是這么感覺的,但是一旦你熟練了程序員的工作,寫代碼寫CRUD寫多了就容易出現瓶頸,感覺似乎軟件都是增刪改查和復雜的業務,各種技術淺嘗則止,感覺無非如此,無非如此,還不如去學硬件方面的,呵呵!
而這卻離軟件的思想越離越遠,於是乎,出現了大量的精通asp.net,精通asp.net mvc,精通wpf,Silverlight,精通一大堆的人,無非也就是能寫點增刪改查,這也能叫做精通..........能不能自己寫框架,寫架構?看博客園那些技術牛人的代碼就是一種享受,他們的代碼,幾乎隔一段時間都會發現技術的演變,重構.這就是造詣!
於是更多的人開始不淡定,我敬佩博客園那么多專研同一種技術動不動就是好多年的牛人.
話題扯遠了!
最近看了基本關於這方面的書,感觸挺深的!
我們的緩存這時候更應該抽象出來,形成一種組件,以適應日后分布式緩存,而且也方便調用.
在DBO數據庫連接類設計中,曾經采用工廠模式的方式以適應多種數據庫的設計,
我們的緩存也可以設計成復用設計,支持多種緩存模式,
這時候,看了一下.net應用架構設計原則,模式與實踐,
感覺那種緩存模式蠻好的,我也嘗試着做了部分修改.
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: }
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中配置緩存類別,
然后在客戶端,配置緩存
客戶端調用就見得多了,
然后,我們的后台需要一個管理緩存的模塊,
可以動態配置,內容頁的緩存時間,等等
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!