节前的一篇文章中提出了为memcached增加缓存依赖的初步设想,本文对第一个思路进行实现。

实现思路

key1发生变化时,不立即移除 key2,key3。在每次返回key2,key3对象时检查key1是否发生变化。如果发生变化再移除key2,key3。

为了方便阅读,再把上文中的图贴出来。

参考程序

DiscuzNT:http://download.comsenz.com/DiscuzNT/src/

我是对DiscuzNT3.0中的缓存部分做的修改。请先自行下载dnt3_src.zip。
程序实现

CacheKeys

参照上图,首先将四个缓存域的Key前缀定义下来。

    public class CacheKeys
    {
        //DATA域   CTIME域  DEPEND域   DEPCTIME域
        public const string DATA = "DATA_";
        public const string CTIME = "CTIME_";
        public const string DEPEND = "DEPEND_";
        public const string DEPCTIME = "DEPCTIME_";
    }

MemCacheDependency
在ASP.NET中有一个CacheDependency类,我创建了一个简化版的MemCacheDependency,并继承自接口ICacheDependency。同时用一个枚举类型的EnumDependType表示缓存依赖类型,目前只实现了缓存之间的键依赖。

    public interface ICacheDependency
    {
        string Dependkey { get; set; }
        EnumDependType DependType { get; set; }
    }
    /// <summary>
    /// 缓存依赖类型
    /// </summary>
    public enum EnumDependType
    {
        CacheDepend = 0,
       // FileDepend = 1,
    }

MemCacheDependency的实现也非常简单,就是初始化Dependkey和DependType。

    public class MemCacheDependency:ICacheDependency
    {
        public string Dependkey { get; set; }
        public EnumDependType DependType { get; set; }

/// <summary>
        /// 初始化
        /// </summary>
        /// <param name="dependkey">缓存依赖项key</param>
        public MemCacheDependency(string dependkey)
        {
            Dependkey = dependkey;
            DependType = EnumDependType.CacheDepend;
        }
    }

MemCachedStrategy
上面引入了MemCacheDependency,创建cache时增加了以下方法。

void AddObjectWithDepend(string objId, object o, ICacheDependency dep);
先修改策略接口

    /// <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的对象(关联ICacheDependency)
        /// </summary>
        /// <param name="objId"></param>
        /// <param name="o"></param>
        /// <param name="dep"></param>
        void AddObjectWithDepend(string objId, object o, ICacheDependency dep);
        /// <summary>
        /// 移除指定ID的对象
        /// </summary>
        /// <param name="objId"></param>
        void RemoveObject(string objId);
        /// <summary>
        /// 返回指定ID的对象
        /// </summary>
        /// <param name="objId">key1</param>
        /// <returns></returns>
        object RetrieveObject(string objId);
        /// <summary>
        /// 返回指定ID的cache     
        /// </summary>
        /// <param name="objId">DATA_key1,CTIME_key1,DEPEND_key1,DEPCTIME_key1</param>
        /// <returns></returns>
        object RetrieveCache(string objId);
        /// <summary>
        /// 到期时间,单位:分钟
        /// </summary>
        int TimeOut { set;get;}
   }

接口中,新增了一个方法RetrieveCache,他和RetrieveObject的不同:
RetrieveObject
objId:创建cache时的key,如:上图中的key1,key2,key3。返回DATA_key1,DATA_key2,DATA_key3的value。
RetrieveCache
objId:cache中实际存在的key,如:CTIME_key1,DEPEND_key1等。返回对应的value。
下面是MemCachedStrategy的实现:

    /// <summary>
    /// MemCache缓存策略类 
    /// </summary>
    public class MemCachedStrategy : Lee.Cache.ICacheStrategy
    {
        /// <summary>
        /// 到期时间
        /// </summary>
        public int TimeOut { set; get; }

#region  操作指定key的Cache

private void AddCache(string objId, object o)
        {
            RemoveCache(objId);
            if (TimeOut > 0)
                MemCachedManager.CacheClient.Set(objId, o, System.DateTime.Now.AddMinutes(TimeOut));
            else
                MemCachedManager.CacheClient.Set(objId, o);
        }

private void RemoveCache(string objId)
        {
            if (MemCachedManager.CacheClient.KeyExists(objId))
                MemCachedManager.CacheClient.Delete(objId);
        }
    
        private bool KeyExists(string objId)
        {
            return MemCachedManager.CacheClient.KeyExists(objId);
        }

public object RetrieveCache(string objId)
        {
            return MemCachedManager.CacheClient.Get(objId);
        }

#endregion

/// <summary>
        ///  添加指定ID的cache 没有依赖项
        /// </summary>
        /// <param name="objId"></param>
        /// <param name="o"></param>
        public void AddObject(string objId, object o)
        {
            string data_key = CacheKeys.DATA + objId;
            string ctime_key = CacheKeys.CTIME + objId;
            string ctime_value = System.DateTime.Now.ToString("yyyyMMddHHmmssfff");
            //DATA
            AddCache(data_key, o);
            //CTIME
            AddCache(ctime_key, ctime_value);
        }
        /// <summary>
        /// 添加指定ID的cache 有依赖项 
        /// </summary>
        /// <param name="objId"></param>
        /// <param name="o"></param>
        /// <param name="dependkey">依赖项key,目前只支持设置一个依赖key</param>
        public void AddObjectWithDepend(string objId, object o, string[] dependkey)
        {
            if (dependkey.Length > 0)
            {
                string depend_key = CacheKeys.DEPEND + objId;
                string depend_value = dependkey[0];

string depctime_key = CacheKeys.DEPCTIME + objId;
                object depctime_value = RetrieveCache(CacheKeys.CTIME + dependkey[0]);

//判断dependkey是否存在 
                if (depctime_value != null)
                {
                    AddObject(objId, o);

//Depend key
                    AddCache(depend_key, depend_value);
                    //DEPTIME
                    AddCache(depctime_key, depctime_value);
                }
                else
                {
                   
                }
            }
        }
        /// <summary>
        /// 添加指定ID的cache 有依赖项
        /// </summary>
        /// <param name="objId"></param>
        /// <param name="o"></param>
        /// <param name="dep">ICacheDependency</param>
        public void AddObjectWithDepend(string objId, object o, ICacheDependency dep)
        {
            if (dep.DependType == EnumDependType.CacheDepend)
            {
                string depend_key = CacheKeys.DEPEND + objId;
                string depend_value =  dep.Dependkey;

string depctime_key = CacheKeys.DEPCTIME + objId;
                object depctime_value = RetrieveCache(CacheKeys.CTIME + dep.Dependkey);

//判断dependkey是否存在 
                if (depctime_value != null)
                {
                    AddObject(objId, o);

//Depend key
                    AddCache(depend_key, depend_value);
                    //DEPTIME
                    AddCache(depctime_key, depctime_value);
                }
                else
                {
                    
                }
            }
        }
        /// <summary>
        /// 移除指定ID的对象
        /// </summary>
        /// <param name="objId"></param>
        public void RemoveObject(string objId)
        {
            string data_key = CacheKeys.DATA + objId;
            string ctime_key = CacheKeys.CTIME + objId;
            string depend_key = CacheKeys.DEPEND + objId;
            string depctime_key = CacheKeys.DEPCTIME + objId;

RemoveCache(data_key);
            RemoveCache(ctime_key);
            RemoveCache(depend_key);
            RemoveCache(depctime_key);
        }
        /// <summary>
        /// 返回指定ID的对象,并根据缓存依赖做失效操作 
        /// </summary>
        /// <param name="objId"></param>
        /// <returns></returns>
        public object RetrieveObject(string objId)
        {
            string data_key = CacheKeys.DATA + objId;
            string ctime_key = CacheKeys.CTIME + objId;
            string depend_key = CacheKeys.DEPEND + objId;
            string depctime_key = CacheKeys.DEPCTIME + objId;

object obj = null;
            //判断objId是否依赖于其他key
            if (!KeyExists(depend_key) && !KeyExists(depctime_key))
            {
                obj = RetrieveCache(data_key);
            }
            else
            {
                object depkey = RetrieveCache(depend_key);//depend key 
                string oldtime = RetrieveCache(depctime_key).ToString();
                string newtime = System.Convert.ToString(RetrieveCache(CacheKeys.CTIME + depkey.ToString()));
                //判断依赖项的key是否过期
                if (oldtime == newtime)
                {
                    obj = RetrieveCache(data_key);
                }
                else
                {
                    RemoveObject(objId);
                }
            }
            return obj;

}

public void AddObjectWithFileChange(string objId, object o, string[] files)
        {
            ;
        }

}

其中的AddObject、AddObjectWithDepend、RemoveObject和RetrieveObject方法可以参照实现思路进行理解。更详细介绍请参考为 memcached增加缓存依赖的初步设想。
CacheContext
下面是对CacheContext的改造,同样增加了包含ICacheDependency类型参数的AddObject方法。

    /// <summary>
    /// 缓存进行全局控制管理
    /// </summary>
    public class CacheContext
    {
        private static ICacheStrategy cs;
        private static volatile CacheContext instance = null;
        private static object lockHelper = new object();

private static System.Timers.Timer cacheConfigTimer = new System.Timers.Timer(15000);

private static bool applyMemCached = false;

/// <summary>
        /// 构造函数
        /// </summary>
        private CacheContext()
        {
            if(MemCachedConfigs.GetConfig() != null && MemCachedConfigs.GetConfig().ApplyMemCached)
                applyMemCached = true;

if (applyMemCached)
                cs = new MemCachedStrategy();
            else
            {
                cs = new DefaultCacheStrategy();
            }
        }
        /// <summary>
        /// 单体模式返回当前类的实例
        /// </summary>
        /// <returns></returns>
        public static CacheContext GetCacheService()
        {
            if (instance == null)
            {
                lock (lockHelper)
                {
                    if (instance == null)
                    {
                        instance = new CacheContext();
                    }
                }
            }

return instance;
        }
        public virtual void AddObject(string objectId, object o)
        {
            lock (lockHelper)
            {
                cs.AddObject(objectId, o);
            }
        }
        public virtual void AddObject(string objectId, object o,string[] keys)
        {
            lock (lockHelper)
            {
                cs.AddObjectWithDepend(objectId, o, keys);
            }
        }
        public virtual void AddObject(string objectId, object o,ICacheDependency dep)
        {
            lock (lockHelper)
            {
                cs.AddObjectWithDepend(objectId, o, dep);
            }
        }
        public virtual object GetObject(string objid)
        {
            try
            {
                object cacheObject = cs.RetrieveObject(objid);

return cacheObject;
            }
            catch
            {
                return null;
            }
        }
        public virtual object GetCache(string objid)
        {
            try
            {
                object cacheObject = cs.RetrieveCache(objid);

return cacheObject;
            }
            catch
            {
                return null;
            }
        }
        public virtual void RemoveObject(string objid)
        {
            lock (lockHelper)
            {
                cs.RemoveObject(objid);
            }
        }
        /// <summary>
        /// 加载指定的缓存策略
        /// </summary>
        /// <param name="ics"></param>
        public void LoadCacheStrategy(ICacheStrategy ics)
        {
            lock (lockHelper)
            {   
                //当不使用MemCached时
                if (!applyMemCached)
                {
                    cs = ics;
                }
            }
        }

/// <summary>
        /// 加载默认的缓存策略
        /// </summary>
        public void LoadDefaultCacheStrategy()
        {
            lock (lockHelper)
            {
                //当不使用MemCached时
                if (applyMemCached)
                {
                    cs = new MemCachedStrategy();
                }
                else
                {
                    cs = new DefaultCacheStrategy();
                }
            }
        }

}

策略模式

上面的实现用到了策略模式(Strategy),可以参考吕老师的文章:http://www.cnblogs.com/zhenyulu/articles/82017.html。

转载于:https://www.cnblogs.com/tenghoo/archive/2010/02/22/Memcached_key_Depend_code.html

为memcached增加缓存依赖的程序实现相关推荐

  1. 为memcached增加缓存依赖的性能测试

    阅读准备 阅读本文前,请先通过下面两篇文章了解该缓存依赖的设计思路和程序实现. 1. 为memcached增加缓存依赖的初步设想. 2. 为memcached增加缓存依赖的程序实现. 测试环境 环境: ...

  2. 简单的Spring Memcached – Spring缓存抽象和Memcached

    在任何读取繁重的数据库应用程序中,缓存仍然是最基本的性能增强机制之一. Spring 3.1发行版提供了一个很酷的新功能,称为Cache Abstraction . Spring Cache Abst ...

  3. Tomcat 警告之“资源添加到Web应用程序[]的缓存中,因为在清除过期缓存条目后可用空间仍不足 - 请考虑增加缓存的最大空间”

    问题 [/attach/image/89833d7734344d10980e0c4450c0e575.png]的资源添加到Web应用程序[/uacp_yunguan]的缓存中,因为在清除过期缓存条目后 ...

  4. Memcached对象缓存详解

    一.NoSQL概述 NoSQL数据存储不需要固定的表结构,通常也不存在连接操作.在大数据存取上具备关系型数据库无法比拟的性能优势.随着互联网web2.0网站的兴起,NoSQL数据库现在成了一个极其热门 ...

  5. 【状态保持】Cache 基于SQL 数据库 的缓存依赖 轮询机制详解

    首先声明一下如果您还不了解什么是Cache(缓存)请您先搜一下有关信息然后再看这篇文章. 当数据库中的信息发生变化的时候,应用程序能够获取变化的通知是缓存依赖得以实现的基础.应用程序可以通过两种途径获 ...

  6. 第一节 Memcached分布式缓存入门

    关于Memcached的博文太多了,以下是个人学习的收集整理. 本节讨论问题: 简单介绍与应用 下载安装注意事项 简单测试 Memcached分布式原理 一.介绍与应用 在常规的WEB开发下,基本都会 ...

  7. ASP.NET使用Memcached高缓存实例(初级教程)

    http://www.itruanjian.com/a/itruanjian/datebase/nosql/2011/0927/5706.html Memcached是一个高性能的分布式内存对象缓存系 ...

  8. memcached搭建缓存系统

    概念 Memcached是danga.com(运营LiveJournal的技术团队)开发的一套分布式内存对象缓存系统,用于在动态系统中减少数据库负载,提升性能. 适用场合 分布式应用.由于memcac ...

  9. System.Web.Caching.Cache类 缓存 各种缓存依赖

    原文:System.Web.Caching.Cache类 缓存 各种缓存依赖 Cache类,是一个用于缓存常用信息的类.HttpRuntime.Cache以及HttpContext.Current.C ...

最新文章

  1. Elon Musk的OpenAI用VR训练机器人:解锁更多复杂动作!
  2. NIO详解(九):Channel详解
  3. 根据指定行数拆分内表
  4. 神策数据算法专家:推荐系统的实践与思考(下)
  5. JAVA图片不显示imageicon_怎么没法显示图片图标呢?
  6. 如何允许用户自定义UI
  7. 远控免杀专题(20)-GreatSCT免杀
  8. iterm2 保存阿里云登陆并防止断开连接
  9. LightOJ - 1140 How Many Zeroes?
  10. 被吹得天花乱坠的无服务器架构,究竟是什么?
  11. mysql定时导出数据_mysql定时备份数据
  12. vue+i18n 切换语言后无法刷新数据 的 解决方案
  13. PCB负片(PCB Negative)
  14. 服务器:CPU虚拟化_服务器虚拟化技术
  15. 计算机的内存储器比外存储器的比较,计算机的内存储器比外存储器
  16. 程序员转公务员之Hello World
  17. 3D旋转相册(附源码+素材)
  18. Linux 桌面玩家指南:03. 针对 Gnome 3 的 Linux 桌面进行美化
  19. Geek-10h-re-wp
  20. 重新试用了office与wps.感觉这次wps好多了.

热门文章

  1. linux下串口程序测试
  2. 【Elasticsearch】用Elasticsearch和Raspberry Pi构建一个真实世界的警报
  3. 【Elasticsearch】Curator 从入门到实战
  4. 【Flink】Flink 1.9 升级 到 flink 1.12.4 报错 shaded netty4 AbstractChannel AnnotatedConnectException
  5. 【Flink】Flink kafka Spark 如何实现数据有序性
  6. 【Docker】Docker 一个偶现的错误 bash命令突然找不到
  7. Dubbo :广播模式下Can't assign requested address问题
  8. spark学习-40-Spark的UnifiedMemoryManager
  9. 【Hbase】HBase数据快速导入之ImportTsv
  10. foreach为什么不能给数组赋值