大约在两年前我写过一篇关于Discuz!NT缓存架构的文章,在那篇文章的结尾介绍了在IIS中如果开启多个 应用程序池会造成多个缓存实例之间数据同步的问题。虽然给出了一个解决方案,但无形中却把压力转移到了 磁盘I/O上(多个进程并发访问cache.config文件)。其实从那时起我就开始关注有什么更好的方案,当然今 天本文中所说的Memcached,以及Velocity等这类的分布式缓存方案之前都考虑过,但一直未能决定该使用那 个。起码Velocity要在.net 4.0之后才会提供,虽然是原生态,但有些远水解不了近火。 我想真正等到Velocity能堪当重任还要等上一段时间。于是我就开始将注意力转移到了Memcached,必定 有Facebook这只“超级小白鼠”使用它并且反响还不错。所以就开始尝试动手在产品中集成Memcached。 其实在之前的那篇关于Discuz!NT缓存架构的文章中已提到过,使用了设计模式中的“策略模式”来构造。 所以为了与以往使用缓存的代码格式相兼容,所以这里采用新添加MemCachedStrategy(MemCached策略) 来构造一个缓存策略类以便于当管理后台开启“MemCached”时以“MemCached策略模式”来做为当前系统默认 的策略模式。 其代码段如下(Discuz.Cache/MemCached.cs): /// <summary>
/// MemCache缓存策略类 /// </summary> public class MemCachedStrategy : Discuz.Cache.ICacheStrategy { /// <summary> /// 添加指定ID的对象 /// </summary> /// <param name="objId"></param> /// <param name="o"></param> public void AddObject(string objId, object o) { RemoveObject(objId); if (TimeOut > 0) { MemCachedManager.CacheClient.Set(objId, o, System.DateTime.Now.AddMinutes(TimeOut)); } else { MemCachedManager.CacheClient.Set(objId, o); } } /// <summary> /// 添加指定ID的对象(关联指定文件组) /// </summary> /// <param name="objId"></param> /// <param name="o"></param> /// <param name="files"></param> public void AddObjectWithFileChange(string objId, object o, string[] files) { ; } /// <summary> /// 添加指定ID的对象(关联指定键值组) /// </summary> /// <param name="objId"></param> /// <param name="o"></param> /// <param name="dependKey"></param> public void AddObjectWithDepend(string objId, object o, string[] dependKey) { ; } /// <summary> /// 移除指定ID的对象 /// </summary> /// <param name="objId"></param> public void RemoveObject(string objId) { if (MemCachedManager.CacheClient.KeyExists(objId)) MemCachedManager.CacheClient.Delete(objId); } /// <summary> /// 返回指定ID的对象 /// </summary> /// <param name="objId"></param> /// <returns></returns> public object RetrieveObject(string objId) { return MemCachedManager.CacheClient.Get(objId); } /// <summary> /// 到期时间 /// </summary> public int TimeOut { set; get; } } 上面类实现的接口Discuz.Cache.ICacheStrategy定义如下: /// <summary>
/// 公共缓存策略接口 /// </summary> public interface ICacheStrategy { /// <summary> /// 添加指定ID的对象 /// </summary> /// <param name="objId"></param> /// <param name="o"></param> void AddObject(string objId, object o); /// <summary> /// 添加指定ID的对象(关联指定文件组) /// </summary> /// <param name="objId"></param> /// <param name="o"></param> /// <param name="files"></param> void AddObjectWithFileChange(string objId, object o, string[] files); /// <summary> /// 添加指定ID的对象(关联指定键值组) /// </summary> /// <param name="objId"></param> /// <param name="o"></param> /// <param name="dependKey"></param> void AddObjectWithDepend(string objId, object o, string[] dependKey); /// <summary> /// 移除指定ID的对象 /// </summary> /// <param name="objId"></param> void RemoveObject(string objId); /// <summary> /// 返回指定ID的对象 /// </summary> /// <param name="objId"></param> /// <returns></returns> object RetrieveObject(string objId); /// <summary> /// 到期时间 /// </summary> int TimeOut { set;get;} } 当然在MemCachedStrategy类中还有一个对象要加以说明,就是MemCachedManager,该类主要是对 Memcached一些常操作和相关初始化实例调用的“封装”,下面是是其变量定义和初始化构造方法的代码: /// <summary>
/// MemCache管理操作类 /// </summary> public sealed class MemCachedManager { #region 静态方法和属性 private static MemcachedClient mc = null; private static SockIOPool pool = null; private static MemCachedConfigInfo memCachedConfigInfo = MemCachedConfigs.GetConfig(); private static string [] serverList = null; static MemCachedManager() { CreateManager(); } private static void CreateManager() { serverList = Utils.SplitString(memCachedConfigInfo.ServerList, ""r"n"); pool = SockIOPool.GetInstance(memCachedConfigInfo.PoolName); pool.SetServers(serverList); pool.InitConnections = memCachedConfigInfo.IntConnections;//初始化链接数 pool.MinConnections = memCachedConfigInfo.MinConnections;//最少链接数 pool.MaxConnections = memCachedConfigInfo.MaxConnections;//最大连接数 pool.SocketConnectTimeout = memCachedConfigInfo.SocketConnectTimeout;//Socket链接超时时间 pool.SocketTimeout = memCachedConfigInfo.SocketTimeout;// Socket超时时间 pool.MaintenanceSleep = memCachedConfigInfo.MaintenanceSleep;//维护线程休息时间 pool.Failover = memCachedConfigInfo.FailOver; //失效转移(一种备份操作模式) pool.Nagle = memCachedConfigInfo.Nagle;//是否用nagle算法启动socket pool.HashingAlgorithm = HashingAlgorithm.NewCompatibleHash; pool.Initialize(); mc = new MemcachedClient(); mc.PoolName = memCachedConfigInfo.PoolName; mc.EnableCompression = false; } /// <summary> /// 缓存服务器地址列表 /// </summary> public static string[] ServerList { set { if (value != null) serverList = value; } get { return serverList; } } /// <summary> /// 客户端缓存操作对象 /// </summary> public static MemcachedClient CacheClient { get { if (mc == null) CreateManager(); return mc; } } public static void Dispose() { if (pool != null) pool.Shutdown(); } 上面代码中构造方法会初始化一个池来管理执行Socket链接,并提供静态属性CacheClient以便MemCachedStrategy 来调用。 (责任编辑:admin) |