[转载]Asp.net mvc 网站之速度优化 — Memcache – enjoyeclipse – 博客园.
前一章说了一下使用页面缓存的问题,这次说一下数据缓存,我们使用的是Memcache作为数据缓存。
下面弱弱地引用一下百度百科关于Memcache的定义:
Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。Memcache是danga的一个项目,最早是LiveJournal 服务的,最初为了加速 LiveJournal 访问速度而开发的,后来被很多大型的网站采用。
1.Memcache服务器端的安装与启动
- 下载memcache,我们使用的版本是1.2.5。
- 使用命令行方式安装memcached-1.2.5.exe: memcached-1.2.5.exe -d install
- 启动memcached: memcached-1.2.5.exe -d start
- 确认Windows 服务中memcached服务已经安装成功:
- 需要注意的是memcached服务是使用的11211端口,如果开启了防火墙,需要将11211添加到例外中。
2.网站中配置BeITMemcached
- 下载BeITMemcached_source_2010_08_04.zip, 并编译出BeITMemcached的DLL文件添加到项目的解决方案中:
- 配置Web.Config
<!– 第三方的组件配置–>
<configSections>
<section name=”beitmemcached” type=”System.Configuration.NameValueSectionHandler” />
</configSections>
<beitmemcached>
<add key=”MemcachedConfig” value=”localhost” />
</beitmemcached>
我们目前的访问量还不是很大,因此将Memcached与网站部署在一台机器上,使用的是localhost. 如果网站和Memcache部署在不同机 器,这里的value 就应该是memcached所在机器的IP,请再次确认11211端口可以访问。
3. Memcache在业务代码中的设计
前面把配置都弄完了,现在需要说一下Memcache在业务代码中的设计了。我们使用的是Controller->Service->Model的模式,切入点就在Service层。
首先构造一个接口ICachePolicy:
public interface ICachePolicy { void Add<T>(string key, T value); void Add<T>(string key, T value, DateTime dt); T Get<T>(string key); void Add(string key, object value); void Add(string key, object value, DateTime dt); object Get(string key); void Delete(string key); }
接着实现MemcachedCachePolicy实现ICachePlolicy:
public class MemcachedCachePolicy : ICachePolicy { private static readonly ILog Logger = LogManager.GetCurrentClassLogger(); private readonly MemcachedClient _cache; public MemcachedCachePolicy() { _cache = MemcachedClient.GetInstance("MemcachedConfig"); _cache.MaxPoolSize = 10000; } public void Add<T>(string key, T value) { if (_cache.Set(key, value)) { Logger.Debug("Set _cache for key successed, key[" + key + "]"); } else { Logger.Debug("Set _cache for key failed"); } } public void Add<T>(string key, T value, DateTime dt) { _cache.Set(key, value, dt); } public T Get<T>(string key) { try { return (T)_cache.Get(key); } catch (Exception e) { Logger.Debug("Get _cache for key failed, key[" + key + "]", e); _cache.Delete(key); return default(T); } } public void Add(string key, object value) { _cache.Set(key, value); } public void Add(string key, object value, DateTime dt) { _cache.Set(key, value, dt); } public object Get(string key) { return _cache.Get(key); } public void Delete(string key) { _cache.Delete(key); } }
最后构造一个BaseCacheService,让BussinessService都继承BaseCacheService, 比如什么ProductService, ShopService等等。对外可见的是BaseCacheService, 而MemcachePolicy对于其他代码来说就是透明的了。
public abstract class BaseCacheService { protected readonly ICachePolicy _cachePolicy; protected BaseCacheService() { } protected BaseCacheService(ICachePolicy cachePolicy) { _cachePolicy = cachePolicy; } protected T GetCache<T>(string key) where T: class { return _cachePolicy.Get<T>(key); } protected void Add<T>(string key, T items) { _cachePolicy.Add(key, items); } protected T GetOrAdd<T>(string key, T loadedItems) where T : class { var items = _cachePolicy.Get<T>(key); if (items == null) { _cachePolicy.Add(key, loadedItems); return loadedItems; } return items; } protected T GetOrAdd<T>(string key, Func<T> howToGet) where T : class { var items = _cachePolicy.Get<T>(key); if (items == null) { var loadedItems = howToGet(); _cachePolicy.Add(key, loadedItems); return loadedItems; } var type = items.GetType(); if (type == typeof(int) && items.Equals(0)) { var loadedItems = howToGet(); _cachePolicy.Add(key, loadedItems); return loadedItems; } return items; } protected T GetOrAdd<T>(string key, Func<T> howToGet, DateTime dt) where T : class { var items = _cachePolicy.Get<T>(key); if (items == null) { var loadedItems = howToGet(); _cachePolicy.Add(key, loadedItems, dt); return loadedItems; } var type = items.GetType(); if (type == typeof(int) && items.Equals(0)) { var loadedItems = howToGet(); _cachePolicy.Add(key, loadedItems, dt); return loadedItems; } return items; } }