• 为memcached增加缓存依赖的程序实现


    节前的一篇文章中提出了为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 { getset; }
            EnumDependType DependType { 
    getset; }
        }
        
    /// <summary>
        
    /// 缓存依赖类型
        
    /// </summary>
        public enum EnumDependType
        {
            CacheDepend 
    = 0,
           
    // FileDepend = 1,
        }

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

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

            
    /// <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 { setget; }

            
    #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。







  • 相关阅读:
    Android用户界面UI组件--AdapterView及其子类(五) Spinner和SpinnerAdapter
    Android用户界面UI组件--AdapterView及其子类(四) GridView
    Android用户界面UI组件--AdapterView及其子类(三) ExpandableListView
    Android用户界面 UI组件--AdapterView及其子类(二) AdapterViewAnimator及其子类
    Navigation Drawer介绍
    Android用户界面 UI组件--AdapterView及其子类(一) ListView及各种Adapter详解
    draw9patch超详细教程
    主线程中有多个handler的情况
    Python服务器开发二:Python网络基础
    shell脚本实现无密码交互的SSH自动登陆
  • 原文地址:https://www.cnblogs.com/tenghoo/p/Memcached_key_Depend_code.html
Copyright © 2020-2023  润新知