博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
中小型网站的缓存策略
阅读量:6849 次
发布时间:2019-06-26

本文共 8883 字,大约阅读时间需要 29 分钟。

在上一篇文章《大型网站系统架构分析》 中,介绍了大型网站的系统架构,其中缓存环境非常重要,大型网站往往使用Squid前端缓存服务器群,memcache分布式缓存,负载均衡,CDN等来 提升性能。但中小型网站使用这些大家伙就有杀鸡用牛刀的感觉,但毋庸置疑,缓存是需要的,开发者开发程序的时候若没有并发思维,一味注重业务逻辑,往往导 致并发用户可能在差不多相同的时间请求相同的数据,网站再请求数据库,如果使用缓存,对这种相同的请求,或者不变的数据,可以缓存起来,直接从内存读取, 可以大大提升并发访问的性能,减少数据库访问次数。因为数据库往往是最容易出现瓶颈的地方,而通过使用恰当的缓存技术可以非常有效地减轻数据库的负载。

根据我的经验,中小型网站可以采用这样的缓存策略 :

  • 如果是单台服务器可以直接缓存在内存,怕内存不够就合理利用ASP.NET所提供的缓存机制,有现成的干嘛不用呢?缓存存在XML文件中 也是一种备选方案,但首先速度没有内存的来的快,其次是写入并发写入XML的时候会锁住文件。可以选用现成的微软Cache application block来实现。
  • 有多台的服务器的话可以考虑memcached,或者其他类似的东西,或者另加一个数据库作为缓存库也行啊。当然有钱的可以用内存数据库。

但不是所有数据都可以缓存的:

  • 对于恒定不变的数据,系统启动后放入缓存就不过期不更新了。
  • 对于偶尔改变的数据,缓存过期时间可以稍微长一些,比如15分钟。
  • 对于经常改变的数据,但访问量极大的热点数据,可以缓存很短的时间,例如30秒,或60秒。(微软有一种数据库数据改变自动同步缓存的SqlDependency功能,有兴趣的读者可以关注)   

如此,便可最大程度的利用缓存,从而可以有效提高系统性能,并明显减轻数据库和网络负载。

你也可以统计并发访问最高的页面和DB访问的频率,把网页静态化,或缓存该些热点,淘汰不热的(缓存替换算法),即使缓存30秒,或60秒也是很大的性能提升,因为他们的并发访问量很大,导致数据库的压力也很大。

代码参考:使用策略模式和单例模式的单机内存缓存:(可以扩展到其他的缓存策略,例如memcache等)

ICacheStrategy.cs

1: using System;
2: using System.Text;
3: 
4: namespace Sample.Caching
5: {
6: /// 
7: /// 缓存策略接口
8: /// 
9: public interface ICacheStrategy
10: {
11: void AddObject(string objId, object o);
12:
13: void AddObjectWithTimeout(string objId, object o, int timeoutSec);
14:
15: void AddObjectWithFileChange(string objId, object o, string[] files);
16:
17: void AddObjectWithDepend(string objId, object o, string[] dependKey);
18: 
19: void RemoveObject(string objId);
20: 
21: object RetrieveObject(string objId);
22: 
23: int TimeOut { set;get;}
24: }
25: }

DefaultCacheStrategy.cs

1: using System;
2: using System.Web;
3: using System.Collections;
4: using System.Web.Caching;
5: 
6: namespace Sample.Caching
7: {
8: /// 
9: /// 默认的缓存策略,实现了缓存策略接口
10: /// 
11: public class DefaultCacheStrategy : ICacheStrategy
12: {
13: private static readonly DefaultCacheStrategy instance = new DefaultCacheStrategy();
14: 
15: protected static volatile System.Web.Caching.Cache webCache = System.Web.HttpRuntime.Cache;
16: 
17: protected int _timeOut = 1; //默认缓存一分钟,也可以单独设置对象的超时时间
18: 
19: private static object syncObj = new object();
20: 
21: /// 
22: /// Initializes the 
class.
23: /// 
24: static DefaultCacheStrategy()
25: {
26: //lock (syncObj)
27: //{
28: // //System.Web.HttpContext context = System.Web.HttpContext.Current;
29: // //if(context != null)
30: // // webCache = context.Cache;
31: // //else
32: // webCache = System.Web.HttpRuntime.Cache;
33: //}
34: }
35: 
36: 
37: public int TimeOut
38: {
39: set { _timeOut = value > 0 ? value : 6000; }
40: get { return _timeOut > 0 ? _timeOut : 6000; }
41: }
42: 
43:
44: public static System.Web.Caching.Cache GetWebCacheObj
45: {
46: get { return webCache; }
47: }
48: 
49: public void AddObject(string objId, object o)
50: {
51: 
52: if (objId == null || objId.Length == 0 || o == null)
53: {
54: return;
55: }
56: 
57: CacheItemRemovedCallback callBack = new CacheItemRemovedCallback(onRemove);
58: 
59: if (TimeOut == 6000)
60: {
61: webCache.Insert(objId, o, null, DateTime.MaxValue, TimeSpan.Zero, System.Web.Caching.CacheItemPriority.High, callBack);
62: }
63: else
64: {
65: webCache.Insert(objId, o, null, DateTime.Now.AddMinutes(TimeOut), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.High, callBack);
66: }
67: }
68: 
69: public void AddObjectWith(string objId, object o)
70: {
71: if (objId == null || objId.Length == 0 || o == null)
72: {
73: return;
74: }
75: 
76: CacheItemRemovedCallback callBack = new CacheItemRemovedCallback(onRemove);
77: 
78: webCache.Insert(objId, o, null, System.DateTime.Now.AddHours(TimeOut), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.High, callBack);
79: }
80: 
81:
82: public void AddObjectWithTimeout(string objId, object o, int timeoutSec)
83: {
84: if (objId == null || objId.Length == 0 || o == null || timeoutSec <= 0)
85: {
86: return;
87: }
88: 
89: CacheItemRemovedCallback callBack = new CacheItemRemovedCallback(onRemove);
90: 
91: webCache.Insert(objId, o, null, System.DateTime.Now.AddSeconds(timeoutSec), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.High, callBack);
92: }
93: 
94: public void AddObjectWithFileChange(string objId, object o, string[] files)
95: {
96: if (objId == null || objId.Length == 0 || o == null)
97: {
98: return;
99: }
100: 
101: CacheItemRemovedCallback callBack = new CacheItemRemovedCallback(onRemove);
102: 
103: CacheDependency dep = new CacheDependency(files, DateTime.Now);
104: 
105: webCache.Insert(objId, o, dep, System.DateTime.Now.AddHours(TimeOut), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.High, callBack);
106: }
107: 
108:
109: public void AddObjectWithDepend(string objId, object o, string[] dependKey)
110: {
111: if (objId == null || objId.Length == 0 || o == null)
112: {
113: return;
114: }
115: 
116: CacheItemRemovedCallback callBack = new CacheItemRemovedCallback(onRemove);
117: 
118: CacheDependency dep = new CacheDependency(null, dependKey, DateTime.Now);
119: 
120: webCache.Insert(objId, o, dep, System.DateTime.Now.AddMinutes(TimeOut), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.High, callBack);
121: }
122: 
123: public void onRemove(string key, object val, CacheItemRemovedReason reason)
124: {
125: switch (reason)
126: {
127: case CacheItemRemovedReason.DependencyChanged:
128: break;
129: case CacheItemRemovedReason.Expired:
130: {
131: //CacheItemRemovedCallback callBack = new CacheItemRemovedCallback(this.onRemove);
132: 
133: //webCache.Insert(key, val, null, System.DateTime.Now.AddMinutes(TimeOut),
134: // System.Web.Caching.Cache.NoSlidingExpiration,
135: // System.Web.Caching.CacheItemPriority.High,
136: // callBack);
137: break;
138: }
139: case CacheItemRemovedReason.Removed:
140: {
141: break;
142: }
143: case CacheItemRemovedReason.Underused:
144: {
145: break;
146: }
147: default: break;
148: }
149: 
150: //TODO: write log here
151: }
152: 
153:
154: public void RemoveObject(string objId)
155: {
156: //objectTable.Remove(objId);
157: if (objId == null || objId.Length == 0)
158: {
159: return;
160: }
161: webCache.Remove(objId);
162: }
163: 
164: 
165: public object RetrieveObject(string objId)
166: {
167: //return objectTable[objId];
168: 
169: if (objId == null || objId.Length == 0)
170: {
171: return null;
172: }
173: 
174: return webCache.Get(objId);
175: }
176: 
177: }
178: }

CachingManager.cs

1: using System;
2: using System.Collections.Generic;
3: using System.Text;
4: 
5: namespace Sample.Caching
6: {
7: /// 
8: /// The caching manager
9: /// 
10: public class CachingManager
11: {
12: private static ICacheStrategy cs;
13: private static volatile CachingManager instance = null;
14: private static object lockHelper = new object();
15:
16: //private static System.Timers.Timer cacheConfigTimer = new System.Timers.Timer(15000);//Interval in ms
17: 
18:
19: private CachingManager()
20: {
21: cs = new DefaultCacheStrategy();
22: 
23: Set timer
24: //cacheConfigTimer.AutoReset = true;
25: //cacheConfigTimer.Enabled = true;
26: //cacheConfigTimer.Elapsed += new System.Timers.ElapsedEventHandler(Timer_Elapsed);
27: //cacheConfigTimer.Start();
28: }
29: 
30:
31: private static void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
32: {
33: //TODO:
34: }
35: 
36:
37: public static CachingManager GetCachingService()
38: {
39: if (instance == null)
40: {
41: lock (lockHelper)
42: {
43: if (instance == null)
44: {
45: instance = new CachingManager();
46: }
47: }
48: }
49: 
50: return instance;
51: }
52: 
53:
54: public virtual void AddObject(string key, object o)
55: {
56: if (String.IsNullOrEmpty(key) || o == null) return;
57: 
58: lock (lockHelper)
59: {
60: if (cs.TimeOut <= 0) return;
61: 
62: cs.AddObject(key, o);
63: }
64: }
65: 
66:
67: public virtual void AddObject(string key, object o, int timeout)
68: {
69: if (String.IsNullOrEmpty(key) || o == null) return;
70: 
71: lock (lockHelper)
72: {
73: if (cs.TimeOut <= 0) return;
74: 
75: cs.AddObjectWithTimeout(key, o, timeout);
76: }
77: }
78: 
79:
80: public virtual object RetrieveObject(string objectId)
81: {
82: return cs.RetrieveObject(objectId);
83: }
84: 
85:
86: public virtual void RemoveObject(string key)
87: {
88: lock (lockHelper)
89: {
90: cs.RemoveObject(key);
91: }
92: }
93: 
94:
95: public void LoadCacheStrategy(ICacheStrategy ics)
96: {
97: lock (lockHelper)
98: {
99: cs = ics;
100: }
101: }
102: 
103:
104: public void LoadDefaultCacheStrategy()
105: {
106: lock (lockHelper)
107: {
108: cs = new DefaultCacheStrategy();
109: }
110: }
111: }
112: }

调用:

1: CachingManager cm = CachingManager.GetCachingService();
2: cm.LoadDefaultCacheStrategy();
3: //从缓存获取
4: IList list = cm.RetrieveObject("mykey") as IList;
5: if (list == null)
6: {
7: list = DAL.GetData(); //从数据库查询
8: cm.AddObject("mykey", list, 2 * 60); //缓存2分钟
9: }
10: return list;

调用时序图:

转载地址:http://wloul.baihongyu.com/

你可能感兴趣的文章
机器学习---计算学习理论
查看>>
git 删除远程分支文件夹
查看>>
常用单词1
查看>>
angular 的 GET 请求 和 POST 请求的 区别 及 实现
查看>>
C# 如何在Excel表格中插入、编辑和删除批注
查看>>
基于微服务的电商系统架构
查看>>
用户管理及授权管理
查看>>
mysql 配置MHA
查看>>
Windows Developer Day - MSIX and Advanced Installer
查看>>
【tp5】ThinkCMF5框架,配置使其支持不同终端PC/WAP/Wechat能加载不同配置和视图
查看>>
spring security+freemarker获取登陆用户的信息
查看>>
[RxJS] Implement RxJS `concatMap` by Waiting for Inner Subscriptions to Complete
查看>>
ubuntu创建idea桌面快捷方式
查看>>
详解JNDI的lookup资源引用java:/comp/env
查看>>
如何在IntelliJ IDEA中使用Git .ignore插件忽略不必要提交的文件
查看>>
愿你走出半生,归来仍是Java Parser
查看>>
C# 获取接口数据(xml格式)转为json格式
查看>>
asp.net mvc session锁问题 (转载)
查看>>
[转]决定人生的三种成本:机会成本,沉没成本,边际成本
查看>>
A Generic Particle IO Library
查看>>