(精华)2020年8月15日 C#基础知识点 cache缓存的实现

(精华)2020年8月15日 C#基础知识点 cache缓存的实现

静态字段缓存基本使用

 /// <summary>
        ///  1 客户端缓存-CDN缓存-反向代理缓存-本地缓存
        ///  2 本地缓存原理和手写基础实现
        ///  3 缓存更新/过期/多线程测试 
        ///  4 缓存类库封装和缓存应用总结 
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {<!-- -->
            try
            {<!-- -->
                Console.WriteLine("开发进阶/蜕变架构!");
                {<!-- -->
                    Console.WriteLine("***************DBHelper*****************");
                    for (int i = 0; i < 5; i++) //会重复查询数据
                    {<!-- -->
                        Console.WriteLine($"获取{nameof(DBHelper)} {i}次 {DateTime.Now.ToString("yyyyMMdd HHmmss.fff")}");
                        List<Program> programList = null;
                        string key = $"{nameof(Program)}_DBHelper.Query_{123}";
                        programList = CustomCache.GetT<List<Program>>(key, () =>
                        {<!-- -->
                            return DBHelper.Query<Program>(123);
                        });
                    }
                }
            }
            catch (Exception ex)
            {<!-- -->
                Console.WriteLine(ex.Message);
            }
            Console.Read();
        }
/// <summary>
    ///模拟数据库查询
    /// </summary>
    public class DBHelper
    {<!-- -->
        /// <summary>
        /// 1 耗时耗资源
        /// 2 参数固定时,结果不变
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="index"></param>
        /// <returns></returns>
        public static List<T> Query<T>(int index)
        {<!-- -->
            Console.WriteLine("This is {0} Query", typeof(DBHelper));
            long lResult = 0;

            //耗时耗资源
            for (int i = index; i < 1_000_000_000; i++)
            {<!-- -->
                lResult += i;
            }

            ///只要Index不变  返回值是不变的!
            List<T> tList = new List<T>();
            for (int i = 0; i < index % 3; i++)
            {<!-- -->
                tList.Add(default(T));
            } 
            return tList;
        }

    }
public class CustomCache
    {<!-- -->
        /// <summary>
        /// 字典缓存
        /// static:不会被Gc回收;
        /// Private:不让外部访问他 
        /// </summary>
        private static Dictionary<string, object> CustomCacheDictionary = new Dictionary<string, object>();

        public static void Add(string key, object value)
        {<!-- -->
            CustomCacheDictionary.Add(key, value);
        }

        public static T Get<T>(string key)
        {<!-- -->
            return (T)CustomCacheDictionary[key];
        }

        public static bool Exists(string key)
        {<!-- -->
            return CustomCacheDictionary.ContainsKey(key);
        }

        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;
        }
    }

cache缓存封装

/// <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; }
    }
/// <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);
        }
    }

缓存管理中心

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);
        }

        /// <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
    }

缓存优化

/// <summary>
    /// 永不过期:当前就是
    /// 绝对过期:过了多长时间以后,就过期了 就不能用了
    /// 滑动过期:设定好过期时间后,如果在有效期内使用过,就往后滑动
    /// 1.Value;数据;
    /// 2.过期时间点:
    /// 3.滑动时间
    /// 普通cache
    /// </summary>
    public class CustomCache
    {<!-- -->
        static CustomCache() //CLR调用  整个进程执行且只执行一次
        {<!-- -->
            Task.Run(() => //
            {<!-- -->
                while (true) //死循环来判断
                {<!-- -->
                    try
                    {<!-- -->
                        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);
        }

        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;
        }

        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;
        }
    }
    /// <summary>
    /// 线程安全cache
    /// </summary>
    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;
        }
    }

    internal class DataModel
    {<!-- -->
        public object Value {<!-- --> get; set; }

        public ObsloteType ObsloteType {<!-- --> get; set; }

        public DateTime Deadline {<!-- --> get; set; }

        public TimeSpan Duraton {<!-- --> get; set; }
    }

    public enum ObsloteType
    {<!-- -->
        Never,
        Absolutely,
        Relative
    }

    /// <summary>
    /// 解决性能问题
    /// </summary>
    public class CustomCacheNewproblem
    {<!-- -->

        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 CustomCacheNewproblem()
        {<!-- -->
            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;
        }
    }
posted @ 2020-12-30 11:57  不要摸我的腰  阅读(407)  评论(0编辑  收藏  举报