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用户信息
        //权限数据
        //菜单
        //商品列表
        //基础资料 系统设置

      不可用于

        //股票数据
        //图片/视频
  • 相关阅读:
    关于 TIdHttp
    DCEF3 相关资料
    WPF RichTextBox 控件常用方法和属性
    Delphi Data Type to C# Data Type
    获取 CPU 序列号
    Visual Studio 调用 Delphi DLL 会退出的解决方案
    IDHttp的基本用法(转)
    TChromeTabs 优化改进
    java与json转换
    js charAt()方法
  • 原文地址:https://www.cnblogs.com/wskxy/p/9391082.html
Copyright © 2011-2022 走看看