• Cache缓存(二) 安静点


    缓存过期策略

     如果数据库管理员来删除了数据呢,会存在缓存里面的数据不可用!缓存出现脏数据库;这是无法完全避免的;

    什么情况下使用缓存?

    二八原则     查询频繁;修改少!

     一般有如下三种策略:

     永不过期

    • 一直能够使用

     绝对过期

    • 过了多长时间以后,就过期了 就不能用了,此时可以直接将数据删除

     滑动过期

    • 设定好过期时间后,如果在有效期内使用过,就往后滑动  比如说,当前8点,设置到8点半过期,但是8点10分的时候使用过这个数据了,过期时间会滑动半小时,就是说8点40才会过期

     下面的缓存我们是通过字典自定义的, 如果存在多线程最好加锁:

    代码: 

      public class CustomCache
        {
            static CustomCache() //CLR调用  整个进程执行且只执行一次
            {
                Task.Run(() => //
                {
                    while (true) //死循环来判断
                    {
                        try
                        {
    
                            //Thread.Sleep(60 * 1000 * 10); //十分钟后开始清理缓存
                            List<string> delKeyList = new List<string>();
    
                            lock (obj_Lock)
                            {
                                foreach (var key in CustomCacheDictionary.Keys)
                                {
                                    DataModel model = CustomCacheDictionary[key];
                                    if (model.Deadline < DateTime.Now && model.ObsloteType != ObsloteType.Never) //
                                    {
                                        delKeyList.Add(key);
                                    }
                                }
                                delKeyList.ForEach(key => Remove(key));
                            } 
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                            throw;
                        }
                    }
                });
    
            }
    
            /// <summary>
            /// static:不会被Gc回收;
            /// Private:不让外部访问他 
            /// </summary>
            private static Dictionary<string, DataModel> CustomCacheDictionary = new Dictionary<string, DataModel>();
    
            private static readonly object obj_Lock = new object();
    
    
            /// <summary>
            /// 默认你是不过期
            /// </summary>
            /// <param name="key"></param>
            /// <param name="value"></param>
            public static void Add(string key, object value)
            {
                lock (obj_Lock)
                    CustomCacheDictionary.Add(key, new DataModel()
                    {
                        Value = value,
                        ObsloteType = ObsloteType.Never
                    });
            }
    
            /// <summary>
            /// 绝对过期
            /// </summary>
            /// <param name="key"></param>
            /// <param name="value"></param>
            /// <param name="timeOutSecond"></param>
            public static void Add(string key, object value, int timeOutSecond) //3000
            {
                lock (obj_Lock)
                    CustomCacheDictionary.Add(key, new DataModel()
                    {
                        Value = value,
                        ObsloteType = ObsloteType.Absolutely,
                        Deadline = DateTime.Now.AddSeconds(timeOutSecond)
                    }); ;
            }
    
            public static void Add(string key, object value, TimeSpan durtion)
            {
                lock (obj_Lock)
                    CustomCacheDictionary.Add(key, new DataModel()
                    {
                        Value = value,
                        ObsloteType = ObsloteType.Relative,
                        Deadline = DateTime.Now.Add(durtion),
                        Duraton = durtion
                    }); ; ;
            }
    
    
            //清楚所有缓存,殃及池鱼!
            public static void RemoveAll()
            {
                lock (obj_Lock)
                    CustomCacheDictionary.Clear();//字典中的所有内容全部被清理到
            }
    
            public static void Remove(string key)
            {
                lock (obj_Lock)
                    CustomCacheDictionary.Remove(key);
            }
    
            /// <summary>
            /// 按条件删除
            /// </summary>
            /// <param name="func"></param>
            public static void RemoveCondition(Func<string, bool> func)
            {
                List<string> keyList = new List<string>();
                lock (obj_Lock)
                    foreach (var key in CustomCacheDictionary.Keys)
                    {
                        if (func.Invoke(key))
                        {
                            keyList.Add(key);
                        }
                    }
                keyList.ForEach(s => Remove(s));
            }
    
            public static T Get<T>(string key)
            {
                return (T)(CustomCacheDictionary[key]).Value;
            }
    
            /// <summary>
            /// 判断是否存在
            /// 判断是哪种过期策略,并且还要看是否过期,如果过期的话还要将数据删除
            /// 不过期的话  滑动过期的还将处理过期时间
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public static bool Exists(string key)
            {
                if (CustomCacheDictionary.ContainsKey(key))
                {
                    DataModel model = CustomCacheDictionary[key];
                    if (model.ObsloteType == ObsloteType.Never)
                    {
                        return true;
                    }
                    else if (model.Deadline < DateTime.Now) //
                    {
                        lock (obj_Lock)
                        {
    
                            CustomCacheDictionary.Remove(key);
                            return false;
                        }
    
                    }
                    else
                    {
                        if (model.ObsloteType == ObsloteType.Relative)
                        {
                            model.Deadline = DateTime.Now.Add(model.Duraton);
                        }
                        return true;
                    }
                }
                else
                {
                    return false;
                }
            }
    
            public static T GetT<T>(string key, Func<T> func)
            {
                T t = default(T);
                if (!Exists(key))
                {
                    t = func.Invoke();
                    Add(key, t);
                }
                else
                {
                    t = Get<T>(key);
                }
                return t;
            }
        }

     如果不想加锁,可以使用ConcurrentDictionary,会保证表示可由多个线程同时访问的键/值对的线程安全集合。

     代码示例:

      public class CustomCacheNew
        {
    
            static CustomCacheNew() //
            {
                Task.Run(() => //
                {
                    while (true) //死循环来判断
                    {
                        try
                        {
                            //Thread.Sleep(60 * 1000 * 10); //十分钟后开始清理缓存
                            List<string> delKeyList = new List<string>();
                            foreach (var key in CustomCacheDictionary.Keys)
                            {
                                DataModel model = CustomCacheDictionary[key];
                                if (model.Deadline < DateTime.Now && model.ObsloteType != ObsloteType.Never) //
                                {
                                    delKeyList.Add(key);
                                }
                            }
                            delKeyList.ForEach(key => Remove(key));
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                            throw;
                        }
                    }
                });
    
            }
    
            /// <summary>
            /// static:不会被Gc回收;
            /// Private:不让外部访问他 
            /// 
            /// 线程安全字典
            /// </summary>
            private static ConcurrentDictionary<string, DataModel> CustomCacheDictionary = new ConcurrentDictionary<string, DataModel>();
    
            /// <summary>
            /// 默认你是不过期
            /// </summary>
            /// <param name="key"></param>
            /// <param name="value"></param>
            public static void Add(string key, object value)
            {
                CustomCacheDictionary.TryAdd(key, new DataModel()
                {
                    Value = value,
                    ObsloteType = ObsloteType.Never
                });
            }
    
            /// <summary>
            /// 绝对过期
            /// </summary>
            /// <param name="key"></param>
            /// <param name="value"></param>
            /// <param name="timeOutSecond"></param>
            public static void Add(string key, object value, int timeOutSecond) //3000
            {
                CustomCacheDictionary.TryAdd(key, new DataModel()
                {
                    Value = value,
                    ObsloteType = ObsloteType.Absolutely,
                    Deadline = DateTime.Now.AddSeconds(timeOutSecond)
                }); ;
            }
    
            public static void Add(string key, object value, TimeSpan durtion)
            {
                CustomCacheDictionary.TryAdd(key, new DataModel()
                {
                    Value = value,
                    ObsloteType = ObsloteType.Relative,
                    Deadline = DateTime.Now.Add(durtion),
                    Duraton = durtion
                }); ; ;
            }
    
    
            //清楚所有缓存,殃及池鱼!
            public static void RemoveAll()
            {
                CustomCacheDictionary.Clear();//字典中的所有内容全部被清理到
            }
    
            public static void Remove(string key)
            {
                DataModel data = null;
                CustomCacheDictionary.TryRemove(key, out data);
            }
    
            
            public static T Get<T>(string key)
            {
                return (T)(CustomCacheDictionary[key]).Value;
            }
    
            /// <summary>
            /// 判断是否存在
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public static bool Exists(string key)
            {
                
                if (CustomCacheDictionary.ContainsKey(key))
                {
                    DataModel model = CustomCacheDictionary[key];
                    if (model.ObsloteType == ObsloteType.Never)
                    {
                        return true;
                    }
                    else if (model.Deadline < DateTime.Now) //
                    {
                        DataModel data = null;
                        CustomCacheDictionary.TryRemove(key, out data);
                        return false;
                    }
                    else
                    {
                        if (model.ObsloteType == ObsloteType.Relative)
                        {
                            model.Deadline = DateTime.Now.Add(model.Duraton);
                        }
                        return true;
                    }
                }
                else
                {
                    return false;
                }
            }
    
            public static T GetT<T>(string key, Func<T> func)
            {
                T t = default(T);
                if (!Exists(key))
                {
                    t = func.Invoke();
                    Add(key, t);
                }
                else
                {
                    t = Get<T>(key);
                }
                return t;
            }
        }

     一般情况下我们都是使用字典加锁来实现,但是加锁的话就会造成性能上的问题,我们可以通过模拟CPU分片的方式来解决,这样锁的时候就锁了这一个字典缓存,另外几个字典不会被锁住

     代码:

        public class CustomCacheNewRichard
        {
    
            private static List<Dictionary<string, DataModel>> dicCacheList = new List<Dictionary<string, DataModel>>();
            private static List<object> lockList = new List<object>();
    
            public static int CupNum = 0;
            static CustomCacheNewRichard() //
            {
                CupNum = 3;//模拟获取获取CPU片数  
                //动态生成字典
                for (int i = 0; i < CupNum; i++)
                {
                    dicCacheList.Add(new Dictionary<string, DataModel>()); //CPU 有几片 就来几个字典
                    lockList.Add(new object());//每个字典对应一个锁
                }
    
    
                Task.Run(() => //
                {
                    while (true) //死循环来判断
                    {
                        try
                        {
    
                            for (int i = 0; i < CupNum; i++)
                            {
                                lock (lockList[i])
                                { 
                                    //Thread.Sleep(60 * 1000 * 10); //十分钟后开始清理缓存
                                    List<string> delKeyList = new List<string>();
                                    foreach (var key in dicCacheList[i].Keys)
                                    {
                                        DataModel model = dicCacheList[i][key];
                                        if (model.Deadline < DateTime.Now && model.ObsloteType != ObsloteType.Never) //
                                        {
                                            delKeyList.Add(key);
                                        }
                                    } 
                                    delKeyList.ForEach(key => dicCacheList[i].Remove(key));
                                }
                            }
    
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                            throw;
                        }
                    }
                });
    
            }
    
            /// <summary>
            /// 默认你是不过期
            /// </summary>
            /// <param name="key"></param>
            /// <param name="value"></param>
            public static void Add(string key, object value)
            {
                int hash = key.GetHashCode() * (-1); //只要字符串不变,hash值不变!
                int index = hash % CupNum;
                lock (lockList[index])
                    dicCacheList[index].Add(key, new DataModel()
                    {
                        Value = value,
                        ObsloteType = ObsloteType.Never
                    });
            }
    
            /// <summary>
            /// 绝对过期
            /// </summary>
            /// <param name="key"></param>
            /// <param name="value"></param>
            /// <param name="timeOutSecond"></param>
            public static void Add(string key, object value, int timeOutSecond) //3000
            {
                int hash = key.GetHashCode() * (-1); //只要字符串变,hash值不变!
                int index = hash % CupNum;
                lock (lockList[index])
                    dicCacheList[index].Add(key, new DataModel()
                    {
                        Value = value,
                        ObsloteType = ObsloteType.Absolutely,
                        Deadline = DateTime.Now.AddSeconds(timeOutSecond)
                    }); ;
            }
    
            public static void Add(string key, object value, TimeSpan durtion)
            {
                int hash = key.GetHashCode() * (-1); //只要字符串变,hash值不变!
                int index = hash % CupNum;
                lock (lockList[index])
                    dicCacheList[index].Add(key, new DataModel()
                    {
                        Value = value,
                        ObsloteType = ObsloteType.Relative,
                        Deadline = DateTime.Now.Add(durtion),
                        Duraton = durtion
                    }); ; ;
            }
    
    
            //清楚所有缓存,殃及池鱼!
            public static void RemoveAll()
            {
                for (int i = 0; i < CupNum; i++)
                {
                    dicCacheList[i].Clear();
                }
            }
    
            public static void Remove(string key)
            {
                int hash = key.GetHashCode() * (-1); //只要字符串变,hash值不变!
                int index = hash % CupNum;
    
                if (dicCacheList[index].ContainsKey(key))
                {
                    dicCacheList[index].Remove(key);
                }
    
            }
    
           
            public static T Get<T>(string key)
            {
                int hash = key.GetHashCode() * (-1); //只要字符串变,hash值不变!
                int index = hash % CupNum;
    
                return (T)(dicCacheList[index][key]).Value;
            }
    
            /// <summary>
            /// 判断是否存在
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public static bool Exists(string key)
            {
                int hash = key.GetHashCode() * (-1); //只要字符串变,hash值不变!
                int index = hash % CupNum;
                if (dicCacheList[index].ContainsKey(key))
                {
                    DataModel model = dicCacheList[index][key];
                    if (model.ObsloteType == ObsloteType.Never)
                    {
                        return true;
                    }
                    else if (model.Deadline < DateTime.Now) //
                    {
                        dicCacheList[index].Remove(key);
                        return false;
                    }
                    else
                    {
                        if (model.ObsloteType == ObsloteType.Relative)
                        {
                            model.Deadline = DateTime.Now.Add(model.Duraton);
                        }
                        return true;
                    }
                }
                else
                {
                    return false;
                }
            }
    
            public static T GetT<T>(string key, Func<T> func)
            {
                T t = default(T);
                if (!Exists(key))
                {
                    t = func.Invoke();
                    Add(key, t);
                }
                else
                {
                    t = Get<T>(key);
                }
                return t;
            }
        }

     上面的代码是自己定义的,我们可以使用系统框架自定义的MemoryCacheCache

     MemoryCacheCache

     它的本质其实也是类似于CPU分片实现的,封装的代码如下:

    namespace Common
    {
        /// <summary>
        /// Cache manager interface
        /// </summary>
        public interface ICache
        {
            /// <summary>
            /// Gets or sets the value associated with the specified key.
            /// </summary>
            /// <typeparam name="T">Type</typeparam>
            /// <param name="key">The key of the value to get.</param>
            /// <returns>The value associated with the specified key.</returns>
            T Get<T>(string key);
    
            /// <summary>
            /// Adds the specified key and object to the cache.
            /// </summary>
            /// <param name="key">key</param>
            /// <param name="data">Data</param>
            /// <param name="cacheTime">Cache time</param>
            void Add(string key, object data, int cacheTime = 30);
    
            /// <summary>
            /// Gets a value indicating whether the value associated with the specified key is cached
            /// </summary>
            /// <param name="key">key</param>
            /// <returns>Result</returns>
            bool Contains(string key);
    
            /// <summary>
            /// Removes the value with the specified key from the cache
            /// </summary>
            /// <param name="key">/key</param>
            void Remove(string key);
    
            /// <summary>
            /// Clear all cache data
            /// </summary>
            void RemoveAll();
    
            object this[string key] { get; set; }
    
            int Count { get; }
        }
    }

    MemoryCacheCache

    /// <summary>
        /// MemoryCacheCache
        /// </summary>
        public class MemoryCacheCache : ICache
        {
            public MemoryCacheCache() { }
    
            protected ObjectCache Cache
            {
                get
                {
                    return MemoryCache.Default;
                }
            }
    
            /// <summary>
            /// 读取缓存
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="key"></param>
            /// <returns></returns>
            public T Get<T>(string key)
            {
                if (Cache.Contains(key))
                {
                    return (T)Cache[key];
                }
                else
                {
                    return default(T);
                }
            }
    
            public object Get(string key)
            {
                return Cache[key];
            }
    
            /// <summary>
            /// 增加缓存
            /// </summary>
            /// <param name="key"></param>
            /// <param name="data"></param>
            /// <param name="cacheTime">分钟</param>
            public void Add(string key, object data, int cacheTime = 30)
            {
                if (data == null)
                    return;
    
                var policy = new CacheItemPolicy();
                policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime);
                Cache.Add(new CacheItem(key, data), policy);
            }
    
            /// <summary>
            /// 是否包含
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public bool Contains(string key)
            {
                return Cache.Contains(key);
            }
    
            public int Count { get { return (int)(Cache.GetCount()); } }
    
    
            /// <summary>
            /// 单个清除
            /// </summary>
            /// <param name="key">/key</param>
            public void Remove(string key)
            {
                Cache.Remove(key);
            }
    
            /// <summary>
            /// 正则表达式移除
            /// </summary>
            /// <param name="pattern">pattern</param>
            public void RemoveByPattern(string pattern)
            {
                var regex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
                var keysToRemove = new List<String>();
    
                foreach (var item in Cache)
                    if (regex.IsMatch(item.Key))
                        keysToRemove.Add(item.Key);
    
                foreach (string key in keysToRemove)
                {
                    Remove(key);
                }
            }
    
            /// <summary>
            /// 根据键值返回缓存数据
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public object this[string key]
            {
                get { return Cache.Get(key); }
                set { Add(key, value); }
            }
    
            /// <summary>
            /// 清除全部数据
            /// </summary>
            public void RemoveAll()
            {
                foreach (var item in Cache)
                    Remove(item.Key);
            }
        }

    CacheManager

       public class CacheManager
        {
            #region Identity
            private CacheManager()
            { }
    
            private static ICache cache = null;
    
            static CacheManager()
            {
                Console.WriteLine("开始缓存的初始化.....");
                //可以创建不同的cache对象
                cache = (ICache)Activator.CreateInstance(typeof(MemoryCacheCache));
                // 这里可以根据配置文件来选择
                //cache = (ICache)Activator.CreateInstance(typeof(CustomerCache));
            }
            #endregion Identity
    
            #region ICache
            /// <summary>
            /// 当前缓存数据项的个数
            /// </summary>
            public static int Count
            {
                get { return cache.Count; }
            }
    
            /// <summary>
            /// 如果缓存中已存在数据项键值,则返回true
            /// </summary>
            /// <param name="key">数据项键值</param>
            /// <returns>数据项是否存在</returns>
            public static bool Contains(string key)
            {
                return cache.Contains(key);
            }
    
            /// <summary>
            /// 获取缓存数据
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public static T GetData<T>(string key)
            {
                return cache.Get<T>(key);
            }
    
            /// <summary>
            /// 
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="key">缓存的项</param>
            /// <param name="acquire">没有缓存的时候获取数据的方式</param>
            /// <param name="cacheTime">单位分钟  默认30</param>
            /// <returns></returns>
            public static T Get<T>(string key, Func<T> acquire, int cacheTime = 30)
            {
                if (!cache.Contains(key))
                {
                    T result = acquire.Invoke();
                    cache.Add(key, result, cacheTime);
                }
                return GetData<T>(key);
    
                //if (cache.Contains(key))
                //{
                //    return GetData<T>(key);
                //}
                //else
                //{
                //    T result = acquire.Invoke();//执行委托  获取委托结果   作为缓存值
                //    cache.Add(key, result, cacheTime);
                //    return result;
                //}
            }
    
            /// <summary>
            /// 添加缓存数据。
            /// 如果另一个相同键值的数据已经存在,原数据项将被删除,新数据项被添加。
            /// </summary>
            /// <param name="key">缓存数据的键值</param>
            /// <param name="value">缓存的数据,可以为null值</param>
            /// <param name="expiratTime">缓存过期时间间隔(单位:分钟)</param>
            public static void Add(string key, object value, int expiratTime = 30)
            {
                if (Contains(key))
                    cache.Remove(key);
                cache.Add(key, value, expiratTime);
            }
    
            /// <summary>
            /// 删除缓存数据项
            /// </summary>
            /// <param name="key"></param>
            public static void Remove(string key)
            {
                cache.Remove(key);
            }
    
            /// <summary>
            /// 删除所有缓存数据项
            /// </summary>
            public static void RemoveAll()
            {
                cache.RemoveAll();
            }
            #endregion
    
        }

      

  • 相关阅读:
    [转]对Lucene PhraseQuery的slop的理解
    Best jQuery Plugins of 2010
    15 jQuery Plugins To Create A User Friendly Tooltip
    Lucene:基于Java的全文检索引擎简介
    9 Powerful jQuery File Upload Plugins
    Coding Best Practices Using DateTime in the .NET Framework
    Best Image Croppers ready to use for web developers
    28 jQuery Zoom Plugins Creating Stunning Image Effect
    VS2005 + VSS2005 实现团队开发、源代码管理、版本控制(转)
    禁止状态栏显示超链
  • 原文地址:https://www.cnblogs.com/anjingdian/p/16884100.html
Copyright © 2020-2023  润新知