zoukankan      html  css  js  c++  java
  • 服务器本地缓存

    1.简介

      服务器本地缓存是使用一个静态字典,根据唯一准确描述缓存的key来将值存入内存中

      新建一个CustomCache类,用来保存缓存

      代码如下:

    using System;
    using System.Collections.Generic;
    namespace ceshi
    {
        class CustomCache
        {
            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 GetT<T>(string key)//获取缓存的值
            {
                return (T)CustomCacheDictionary[key];
            }
            public static bool Exsits(string key)//判断缓存是否存在
            {
                return CustomCacheDictionary.ContainsKey(key);
            }
        }
    }

      Program:

    using System;
    using System.Threading.Tasks;
    using System.Threading;
    namespace ceshi
    {
        class Program
        {
            static void Main(string[] args)
            {
                for (int i = 0; i < 5; i++)
                {
                    string key = "add_key_101";//唯一准确描述缓存的key
                    int result;
                    if (CustomCache.Exsits(key))
                    {
                        result = CustomCache.GetT<int>(key);
                    }
                    else
                    {
                //----------------调用模拟函数--------------- result = Simulation(); //----------------添加缓存-------------------
    CustomCache.Add(key, result); } Console.WriteLine(result); } Console.Read(); } static int Simulation() { //-------------模拟获取数据的时耗-------------- int result; Thread.Sleep(2000); Random random = new Random(); result = random.Next(0, 100); return result; } } }

    2.封装调用函数

      现实羡慕中缓存是无处不在的,所以为了方便使用缓存,可以将上面红色字体的代码封装到CustomCache里面,以方便调用

      CustomCache类添加一个函数:

    using System;
    using System.Collections.Generic;
    namespace ceshi
    {
        class CustomCache
        {
            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 GetT<T>(string key)
            {
                return (T)CustomCacheDictionary[key];
            }
            public static bool Exsits(string key)
            {
                return CustomCacheDictionary.ContainsKey(key);
            }
            public static T GetDataT<T>(string key,Func<T> func)//委托Func是无参有返回值
            {
                T result = default(T);
                if(Exsits(key))
                {
                    result=(T)CustomCacheDictionary[key];
                }
                else
                {
                    result=func.Invoke();//实例化外部模拟获取数据的函数,也就是运行这个函数并接收返回值
                    Add(key, result);
                }
                return result;
            }
        }
    }

      Program:

    using System;
    using System.Threading.Tasks;
    using System.Threading;
    namespace ceshi
    {
        class Program
        {
            static void Main(string[] args)
            {
                for (int i = 0; i < 5; i++)
                {
                    string key = "add_key_101";//唯一准确描述缓存的key
                    int result;
                    result=CustomCache.GetDataT<int>(key, () => Simulation());
                    Console.WriteLine(result);
                }
                Console.Read();
            }
    
            static int Simulation()
            {
                //-------------模拟获取数据的时耗--------------
                int result;
                Thread.Sleep(2000);
                Random random = new Random();
                result = random.Next(0, 100);
                return result;
            }
        }
    }

      这样在多次调用时可以节省很多代码量。

    3.缓存进阶

      在缓存中,如果数据库的数据被修改了,缓存就可能产生脏数据

      所以应该使用一些方法,来及时清除更新这些脏数据

      1)更新的数据,影响一条缓存

        每次主动修改数据库时,根据key删除对应的缓存(为什么是删除不是更新呢,缓存一般不更新,删除之后再次访问会继续做缓存)

                CustomCacheDictionary.Remove(key);

      2)更新的数据,影响到多条缓存

        可以直接删除所有缓存,简单粗暴

                CustomCacheDictionary.Clear();

      3)跟新的数据,影响多条缓存,但这些缓存的key有大致相同的结构

        如,均以_customcategory为结尾

        这样我们可以根据条件删除缓存

    using System;
    using System.Collections.Generic;
    namespace ceshi
    {
        class CustomCache
        {
            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 GetT<T>(string key)
            {
                return (T)CustomCacheDictionary[key];
            }
            public static bool Exsits(string key)
            {
                return CustomCacheDictionary.ContainsKey(key);
            }
            public static T GetDataT<T>(string key,Func<T> func)//Func是无参有返回值
            {
                T result = default(T);
                if(Exsits(key))
                {
                    result=(T)CustomCacheDictionary[key];
                }
                else
                {
                    result=func.Invoke();
                    Add(key, result);
                }
                return result;
            }
    
            public static void RemoveCondition(Func<string,bool> func)//根据条件删除缓存,委托为给一个string类型的参数,返回bool
            {
                List<string> keyList = new List<string>();
                foreach(string item in CustomCacheDictionary.Keys)
                {
                    if(func.Invoke(item))
                    {
                        keyList.Add(item);
                    }
                }
                keyList.ForEach(key => CustomCacheDictionary.Remove(key));
            }
        }
    }

      Program

    using System;
    using System.Threading.Tasks;
    using System.Threading;
    namespace ceshi
    {
        class Program
        {
            static void Main(string[] args)
            {
                for (int i = 0; i < 4; i++)//添加四条以_customcategory为结尾的缓存
                {
                    string key = $"add_key_10{i}_customcategory";//唯一准确描述缓存的key
                    int result;
                    result = CustomCache.GetDataT<int>(key, () => Simulation());
                    Console.WriteLine(result);
                }
    
    
                {
                    CustomCache.RemoveCondition((s) => s.EndsWith("_customcategory"));清除以_customcategory为结尾的缓存
                }
    
                Console.Read();
            }
    
            static int Simulation()
            {
                //-------------模拟获取数据的时耗--------------
                int result;
                Thread.Sleep(2000);
                Random random = new Random();
                result = random.Next(0, 100);
                return result;
            }
        }
    }

      4)缓存过期

         在缓存中,我们基本需要加上过期时间,这样可以保证数据的可靠性

    using System;
    using System.Collections.Generic;
    namespace ceshi
    {
        class CustomCache
        {
            private static Dictionary<string, KeyValuePair<object, DateTime>> CustomCacheDictionary = new Dictionary<string, KeyValuePair<object, DateTime>>();
    
            public static void Add(string key, object value, int second = 3)//second定义数据过期时间,单位是秒
            {
                CustomCacheDictionary.Add(key, new KeyValuePair<object, DateTime>(value, DateTime.Now.AddSeconds(second)));
            }
    
            public static T GetT<T>(string key)
            {
                return (T)CustomCacheDictionary[key].Key;
            }
            public static bool IsExsits(string key)//判断缓存是否存在和是否过期
            {
                if (CustomCacheDictionary.ContainsKey(key))
                {
                    if (CustomCacheDictionary[key].Value > DateTime.Now)
                    {
                        return true;
                    }
                    else//过期,删除
                    {
                        CustomCacheDictionary.Remove(key);
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
            public static T GetDataT<T>(string key, Func<T> func)//Func是无参有返回值
            {
                T result = default(T);
                if (IsExsits(key))
                {
                    result = (T)CustomCacheDictionary[key].Key;
                }
                else
                {
                    result = func.Invoke();
                    Add(key, result);
                }
                return result;
            }
        }
    }

      Program:

    using System;
    using System.Threading.Tasks;
    using System.Threading;
    namespace ceshi
    {
        class Program
        {
            static void Main(string[] args)
            {
                for (int i = 0; i < 500; i++)
                {
                    string key = $"add_key_10_customcategory";//唯一准确描述缓存的key
                    int result;
                    result = CustomCache.GetDataT<int>(key, () => Simulation());
                    Console.WriteLine(result);
                    Thread.Sleep(1000);
                }
                Console.Read();
            }
    
            static int Simulation()
            {
                //-------------模拟获取数据的时耗--------------
                int result;
                Thread.Sleep(2000);
                Random random = new Random();
                result = random.Next(0, 100);
                return result;
            }
        }
    }

      结果:

        

      我们定义缓存的过期时间是3秒后,当然现实中需要按要求合理定义过期时间,这里只是为了方便测试。

       以上这个方法还有一个缺陷,那就是如果一个缓存数据一直没有被访问到,那过期了也不会被判断并删除,会占用内存。

      所以,我们需要新开一个线程,让他实时进行过期检索操作。

      在类中添加一个构造函数,这样第一次使用这个类时,构造函数也会被调用,即可以马上打开这个线程进行监听

         static CustomCache()
            {
                Task.Run(() =>
                {
                    while(true)
                    {
                        List<string> keyList = new List<string>();
                        foreach(string item in CustomCacheDictionary.Keys)
                        {
                            if (CustomCacheDictionary[item].Value > DateTime.Now)
                            {
                                //还没过期,无需操作
                            }
                            else//过期,删除
                            {
                                keyList.Add(item);
                            }
                        }
                        keyList.ForEach(key => CustomCacheDictionary.Remove(key));
                        Thread.Sleep(60*1000);
                    }
                });
            }

     4.缓存的使用场景

      适合使用缓存的资源一般具有以下特性

        //常用
        //耗时
        //稳定
        //即时性要求低
        //内存小

      举几个小例子

      可用于

        //session用户信息
        //权限数据
        //菜单
        //商品列表
        //基础资料 系统设置

      不可用于

        //股票数据
        //图片/视频
  • 相关阅读:
    0309. Best Time to Buy and Sell Stock with Cooldown (M)
    0621. Task Scheduler (M)
    0106. Construct Binary Tree from Inorder and Postorder Traversal (M)
    0258. Add Digits (E)
    0154. Find Minimum in Rotated Sorted Array II (H)
    0797. All Paths From Source to Target (M)
    0260. Single Number III (M)
    0072. Edit Distance (H)
    0103. Binary Tree Zigzag Level Order Traversal (M)
    0312. Burst Balloons (H)
  • 原文地址:https://www.cnblogs.com/wskxy/p/9391082.html
Copyright © 2011-2022 走看看