• 第十一节:Asp.Net Core 之内容缓存(IMemoryCache)


    1. 整体说明

      ASP.NET Core 支持多种不同的缓存,最简单的缓存基于 IMemoryCache,它表示存储在 Web 服务器内存中的缓存,内存缓存可以存储任何对象,存储形式键值对,需要 .net standard 2.0 或者 .Net framework 4.5 或更高版本。

    本节主要介绍:依赖注入的方式使用、全局封装单例配置、缓存几个方法和性质。

    2. 常规使用步骤

      (1) 安装程序集:System.Runtime.Caching 和 Microsoft.Extensions.Caching.Memory,如果是是Core MVC程序自带的Microsoft.AspNetCore.App包里已经涵盖了

     Microsoft.Extensions.Caching.Memory,无需重复下载。

      (2) 在ConfigureService中注册内存缓存服务: services.AddMemoryCache();

     1 using Microsoft.AspNetCore.Builder;
     2 using Microsoft.AspNetCore.Mvc;
     3 using Microsoft.Extensions.DependencyInjection;
     4 
     5 public class Startup
     6 {
     7     public void ConfigureServices(IServiceCollection services)
     8     {
     9         services.AddMemoryCache();
    10         services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    11     }
    12 
    13 
    14 }

      (3) 通过属性注入的方式在控制器中注入IMemoryCache对象。

    1  public class FirstController : Controller
    2     {
    3         private IMemoryCache _cache1;
    4         public FirstController(IMemoryCache memoryCache)
    5         {
    6             _cache1 = memoryCache;
    7         }
    8     }

      (4) 通过get、set方法实现常规缓存的读取和写入,如下 案例①。

    1    {
    2        string nowTime1 = _cache1.Get<string>("t1");
    3        if (String.IsNullOrEmpty(nowTime1))
    4        {
    5            nowTime1 = DateTime.Now.ToString();
    6            _cache1.Set("t1", nowTime1);
    7        }
    8        ViewBag.t1 = nowTime1;
    9   }

    3. 全局封装单例的形式

     (1)新建一个memoryCacheHelp类,声明一个IMemoryCache属性,并在构造函数中进行初始化,实例化的时候可以通过SizeLimit设置全局缓存的最大Size。

    特别注意:如果在这全局设置了最大Size,凡是使用的时候都需要通过SetSize进行设置,且必须 "小于等于" 这个最大Size,不设置会报错,设置的比这个大,缓存会失效。

     1  public class memoryCacheHelp
     2     {
     3         public IMemoryCache _cache { get; set; }
     4         public memoryCacheHelp()
     5         {
     6             _cache = new MemoryCache(new MemoryCacheOptions {
     7                 SizeLimit = 1024
     8             });
     9         }
    10     }

     (2)在ConfigureService将该类注册成单例的:services.AddSingleton<memoryCacheHelp>();

    1 public void ConfigureServices(IServiceCollection services)
    2 {
    3     services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    4     services.AddSingleton<memoryCacheHelp>();
    5 }

     (3)通过属性注入的方式在控制器中注入IMemoryCache对象

    1  public class FirstController : Controller
    2     {
    3         private IMemoryCache _cache2;
    4         public FirstController(memoryCacheHelp cache)
    5         {
    6             _cache2 = cache._cache;
    7         }
    8    }

     (4)通过TryGetValue、set方法实现缓存的读取和写入,如下 案例②

    注: 这里通过依赖注入的形式将memoryCacheHelp注册成单例类,和直接声明成单例类道理是一样的。

     1  {
     2      string nowTime2 = null;
     3      if (!_cache2.TryGetValue("t2", out nowTime2))
     4      {
     5          nowTime2 = DateTime.Now.ToString();
     6          //设置缓存的大小
     7          var cacheOptions = new MemoryCacheEntryOptions()
     8                                       .SetSize(100)
     9                                       .SetAbsoluteExpiration(TimeSpan.FromSeconds(5));
    10           _cache2.Set("t2", nowTime2, cacheOptions);
    11      }
    12     ViewBag.t2 = nowTime2;
    13 }

    4. 方法、属性详解

    (1) 获取数据

     A. Get<T>方法:根据键名获取指定类型的值,将返回值做判断,比如根据是否为null,来判断有没有值。 如下面的案例①

     B. TryGetValue(object key, out TItem value);根据key获取指定类型值,通过out参数进行输出,如果拿到值返回true,如果拿不到值返回false,相比Get<T>方法 如下面案例②

     C. GetOrCreate(object key, Func<ICacheEntry, TItem> factory);适用场景:key有值则获取该值,没有值为它赋值(通过return直接返回)。如下面案例③

    (2) 写入数据

     A. Set方法:有很多重载,重点看下面两个

      ①:Set<TItem>(object key, TItem value); 最简单的键值模式

      ②:Set<TItem>(object key, TItem value, MemoryCacheEntryOptions options); 通过MemoryCacheEntryOptions设置缓存的性质,详见下面

     B. GetOrCreate方法:当key对应的值为空则通过return返回来赋值,如下面的:案例③,通过第二个参数在Func委托中设置ICacheEntry属性进行缓存性质的设置。 详见下面(5)

     1 {
     2     string nowTime3 = _cache1.GetOrCreate("t3", entry =>
     3     {
     4       entry.Size = 100;
     5       //滑动过期时间设置为2秒
     6       entry.SlidingExpiration = TimeSpan.FromSeconds(2);
     7       //绝对和滑动只能设置一个
     8       //entry.AbsoluteExpiration = new DateTimeOffset(DateTime.Parse("2019-07-16 16:33:10"));
     9       entry.Priority = CacheItemPriority.High;
    10       entry.RegisterPostEvictionCallback(MyCallback, this);
    11       return DateTime.Now.ToString();
    12     });
    13     ViewBag.t3 = nowTime3;
    14 }

    (3) 移除数据

     A. Remove方法:Remove(object key); 移除缓存

    (4) MemoryCacheEntryOptions类

     用来设置缓存的一些性质,可以通过方法或者属性进行设置,在Set方法中使用。

     A. 缓存大小(SetSize方法和Size属性):如果全局单例设置缓存的最大值,则每个使用的地方都需要显式的设置,必须小于等于最大值,如果不设置报错,如果设置比最大值还大,缓存不生效。

     B. 绝对过期时间(SetAbsoluteExpiration方法和AbsoluteExpiration属性):绝对指的是到了这个时间就过期,不管这期间有没有人访问。

     绝对过期有两种设置方式:① 通过TimeSpan设置距离当前时间的间隔 ② 通过DateTimeOffset设置具体到某一时刻。 详见下面案例④

     C. 滑动过期时间(SetSlidingExpiration方法和SlidingExpiration属性):相对是指以最后一次访问来计算,每访问一次重新计算过期时间。

     D. 缓存级别(SetPriority方法和Priority属性):有Low、Normal、High、NeverRemove。

     E. 缓存移除时回调(RegisterPostEvictionCallback方法和属性):缓存过期或者手动移除时调用,该方法有四个参数,调用的时候自动赋值,分别是: 键、值、消失原因、状态。

     1   {
     2                 string nowTime4 = null;
     3                 if (!_cache2.TryGetValue("t4", out nowTime4))
     4                 {
     5                     nowTime4 = DateTime.Now.ToString();
     6                     MemoryCacheEntryOptions cacheOptions = null;
     7 
     8                     //设置缓存方式一:(通过方法)
     9                     {
    10                         cacheOptions = new MemoryCacheEntryOptions()
    11                          .SetSize(100)
    12                          //.SetSlidingExpiration(TimeSpan.FromSeconds(5))
    13                          //绝对和滑动只能设置一个
    14                          .SetAbsoluteExpiration(TimeSpan.FromSeconds(60))
    15                          .SetPriority(CacheItemPriority.Normal)
    16                          .RegisterPostEvictionCallback(MyCallback, this);
    17 
    18                     }
    19 
    20                     //设置缓存方式二:(通过属性)
    21                     //{
    22                     //    cacheOptions = new MemoryCacheEntryOptions();
    23                     //    cacheOptions.Size = 100;
    24                     //    //cacheOptions.SlidingExpiration = TimeSpan.FromSeconds(5);
    25                     //    //绝对和滑动只能设置一个
    26                     //    cacheOptions.AbsoluteExpiration = new DateTimeOffset(DateTime.Parse("2019-07-16 16:33:10"));
    27                     //    cacheOptions.Priority = CacheItemPriority.High;
    28                     //    cacheOptions.RegisterPostEvictionCallback(MyCallback, this);
    29                     //}
    30                     _cache2.Set("t4", nowTime4, cacheOptions);
    31 
    32                 }
    33                 ViewBag.t4 = nowTime4;
    34             } 
    35 
    36         /// <summary>
    37         /// 失败回调
    38         /// </summary>
    39         /// <param name="key"></param>
    40         /// <param name="value"></param>
    41         /// <param name="reason">缓存消失的原因,比如移除、过期,是个枚举类型</param>
    42         /// <param name="state"></param>
    43         private static void MyCallback(object key, object value, EvictionReason reason, object state)
    44         {
    45             var message = $"Cache entry was removed : key={key},value={value}, reason={reason}, state={state}";
    46         }

    (5) ICacheEntry

     通过属性的形式设置:缓存大小、绝对过期、滑动过期、缓存级别、缓存移除回调,详见案例③

    5.即时创建调用 VS 全局单例调用

     首先需要明白,不管即时创建调用还是全局单例调用,MemoryCache都是存在服务器内存中的,这一点是毋庸置疑的。

     (1) 即时创建调用:多个客户端每次访问该方法的时候,都需要现创建一个IMemoryCache对象,然后进行读取或写入。

     (2) 全局单例调用:只要有一个客户端访问该方法,创建IMemoryCache对象,后续不管谁访问,都是使用的同一个对象进行读取或写入。

     

    很傻瓜的一个问题:内存缓存是以键值对的形式进行存储,同一个键如果多次设置会覆盖,但是不同键之间设置过期时间是互相不影响的。

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    .bash_profile与.bashrc和.profile的区分概念
    java创建文件和目录
    Win7设置wifi热点
    JAVA之File类创建对象构造函数传参数需要注意的几点
    linux 控制台使用技巧
    poj1426-Find The Multiple
    Ubuntu下安装Android SDK(图文教程)
    屏蔽EditText长按导致的弹出输入法的对话框
    ZJUT 1423 地下迷宫(期望DP&高斯消元)
    Hadoop之SequenceFile
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/11043337.html
Copyright © 2020-2023  润新知