转自:http://www.cnblogs.com/mysweet/archive/2012/06/05/2536372.html
缓存是性能优化一个非常重要的模块,几乎计算机哪里都会用到缓存,我们的网站缓存也是非常重要的一块,缓存给网站带来太大的性能提高,在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: }
这样我们一个简单的完整的缓存模块就设计完了,可以发现,这样我们的缓存管理就容易得多了.
设计需要思考,程序员更需要思考,深入去学习软件思想,架构,而不仅仅停留在简单
的工作,软件的复杂在于做大,软件的扩大,让软件的复杂度成指数级增长,所以更需
要架构,深层次的去研究软件理论,软件精华!