[转载]Asp.net mvc 网站之速度优化 — Memcached

[转载]Asp.net mvc 网站之速度优化 -- Memcache - enjoyeclipse - 博客园.

前一章说了一下使用页面缓存的问题,这次说一下数据缓存,我们使用的是Memcache作为数据缓存。

下面弱弱地引用一下百度百科关于Memcache的定义:

Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像视频文件以及数据库检索的结果等。Memcache是danga的一个项目,最早是LiveJournal 服务的,最初为了加速 LiveJournal 访问速度而开发的,后来被很多大型的网站采用。

1.Memcache服务器端的安装与启动

  1. 下载memcache,我们使用的版本是1.2.5。
  2. 使用命令行方式安装memcached-1.2.5.exe:  memcached-1.2.5.exe -d install
  3. 启动memcached: memcached-1.2.5.exe -d start
  4. 确认Windows 服务中memcached服务已经安装成功:
  5. 需要注意的是memcached服务是使用的11211端口,如果开启了防火墙,需要将11211添加到例外中。



2.网站中配置BeITMemcached

  1. 下载BeITMemcached_source_2010_08_04.zip, 并编译出BeITMemcached的DLL文件添加到项目的解决方案中:
  2. 配置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:


[csharp]
public interface ICachePolicy {

void Add(string key, T value);

void Add(string key, T value, DateTime dt);

T Get(string key);

void Add(string key, object value);

void Add(string key, object value, DateTime dt);

object Get(string key);

void Delete(string key);

}
[/csharp]

接着实现MemcachedCachePolicy实现ICachePlolicy:
[csharp]
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(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(string key, T value, DateTime dt)
{
_cache.Set(key, value, dt);
}

public T Get(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);
}
}
[/csharp]
最后构造一个BaseCacheService,让BussinessService都继承BaseCacheService, 比如什么ProductService, ShopService等等。对外可见的是BaseCacheService, 而MemcachePolicy对于其他代码来说就是透明的了。
[csharp]
public abstract class BaseCacheService
{
protected readonly ICachePolicy _cachePolicy;

protected BaseCacheService()
{

}

protected BaseCacheService(ICachePolicy cachePolicy)
{
_cachePolicy = cachePolicy;
}

protected T GetCache(string key) where T: class
{
return _cachePolicy.Get(key);
}

protected void Add(string key, T items)
{
_cachePolicy.Add(key, items);
}

protected T GetOrAdd(string key, T loadedItems) where T : class
{
var items = _cachePolicy.Get(key);

if (items == null)
{
_cachePolicy.Add(key, loadedItems);
return loadedItems;
}

return items;
}

protected T GetOrAdd(string key, Func howToGet) where T : class
{
var items = _cachePolicy.Get(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(string key, Func howToGet, DateTime dt) where T : class
{
var items = _cachePolicy.Get(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;
}
}
[/csharp]