.Net Core缓存组件(MemoryCache)【缓存篇(二)】,.NET Core ResponseCache【缓存篇(一)】

admin 3个月前 (07-23) 科技 44 0

一、前言

  .Net Core缓存源码

  1、上篇.NET Core ResponseCache【缓存篇(一)】中我们提到了使用客户端缓存、和服务端缓存。本文我们先容MemoryCache缓存组件,说到服务端缓存我们一样平时都市想到MemoryCache、Redis等等优异的缓存组件,各自有各自使用的场景。MemoryCache的类型对照单一是Object工具存储、Redis的数据类型就相对对照多 String(字符串),List(列表),set(去重聚集),zset(去重排序聚集),hash(哈希)。另有HyperLogLog,bitMap,GeoHash,BloomFilter这四种还没有详细领会,等下篇解说Redis的时刻详细给列位姥爷供上。

二、MemoryCache缓存组件使用

  1、首先我们需要将MemoryCache组件注入到程序中。

 public void ConfigureServices(IServiceCollection services)
        {
            //添加内存缓存
            services.AddMemoryCache();
        }

  2、使用的方式也对照简单和我们平时写代码差不多。在控制其中注入基类IMemoryCache,看到下面这个基类,我还以为会只有两个方式。

 #region 注入缓存
        private readonly IMemoryCache Cache;
        public MemoryCacheController(IMemoryCache cache)
        {
            Cache = cache;
        }
        #endregion

   3、当我正常使用的时刻发现方式原来使用推展方式写在这里。使用起来很简单我就直接代码了。

  4、设置缓存主要是四种过时时间。

      1:永远不过时 就是老子就是不过时气死你。

       2:绝对过时时间 这个就好比我们买的安眠药,2020年07月22日过时。那你今天就要好好行使这个时间了。

      3:相对过时时间 这个好比你用饭三个小时,肚子就呱呱叫了,相对于当前时间延伸。

      4:滑动过时时间 这个就是相对过时时间的升级版,我们每隔三个小时就会肚子饿,那么我们是不是可以等到两个半小时就是用饭,肚子就不会叫了。这样在一定时间内使用这个缓存就会在你最后使用缓存的时间上延伸。

            //设置缓存  当我们没有指定过时时间,理论是永远的(后面会说到不理论的)
            Cache.Set("key", "value");
            Console.WriteLine(Cache.Get("key"));

            //设置缓存绝对过时时间
            Cache.Set("key1", "value", new DateTimeOffset(new DateTime(2020, 7, 22)));
            Console.WriteLine(Cache.Get("key1"));

            //设置相对过时时间
            Cache.Set("key2", "value", new TimeSpan(0, 0, 10));
            Console.WriteLine(Cache.Get("key2"));

            //设置滑动过时时间
            Cache.Set("key3", "value", new MemoryCacheEntryOptions()
            {
                //设置滑动过时
                SlidingExpiration = new TimeSpan(0, 0, 5),
                //设置缓存的优先级,当我们缓存空间不足的时刻会移除等级低的缓存,以此类推(消灭的时刻不会管是否过时)
                //Low,    低的意思
                //Normal, 正常模式  默认模式
                //High,   高
                //NeverRemove 绝不接纳,这个就算内存满了也不会消灭。
                Priority = CacheItemPriority.NeverRemove
            });
            Console.WriteLine(Cache.Get("key3"));

  5、这里我们还要讲一下缓存失效机制,这里它不是自动失效的,只有当我们再次对缓存MemoryCache组件举行增删查改的时刻才会扫描内里的内存是否存在过时的,举行垃圾接纳。这里我们使用GetOrCreate方式建立我们的缓存证实我们的说法。这个可以设置过时回调函数。图下我们可以看到当我们的缓存过时之后,就没有对缓存举行操作了就不会有回调函数触发。

Cache.GetOrCreate("key4", cacheEntry =>
            {
                //设置滑动过时
                cacheEntry.SlidingExpiration= new TimeSpan(0, 0, 5);
                //设置删除回调函数
                cacheEntry.RegisterPostEvictionCallback(CallbackFunction);
                //设置内存
                return cacheEntry.Value = "滑动过时时间带删除回调";
            });
            Thread.Sleep(2000);
            Console.WriteLine(Cache.Get("key4"));
            Thread.Sleep(4000);
            Console.WriteLine(Cache.Get("key4"));
            Thread.Sleep(5000);

   6、然则我们将最后一句代码解开封印。这里有一个问题,当我们执行等待了5秒钟按原理过时了,然则没有触发删除回调,我截图上的是我将代码块拉到了之前执行的最后一行代码才有,这个我也蒙了。然则当我第二次进来接见就有回调函数了。

.Net Core缓存组件(MemoryCache)【缓存篇(二)】,.NET Core ResponseCache【缓存篇(一)】 第1张

/// <summary>
        /// 删除回调函数
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="reason"></param>
        /// <param name="state"></param>
        public void CallbackFunction(object key, object value, EvictionReason reason, object state)
        {
            Console.WriteLine($"你被删除了key:{key},value:{value}回调函数");
        }

  7、CreateEntry设置缓存,有一点特殊正常设置缓存的时刻,获取的时刻是null,只有当我们执行Dispose或者using的时刻才乐成。带着这个疑问我们决议看看源码。 

            ////CreateEntry设置缓存
            var entity = Cache.CreateEntry("key5");
            entity.Value = "5555";
            Console.WriteLine("CreateEntry 获取信息:" + Cache.Get("key5"));  //效果null
 //方式1
            var entity = Cache.CreateEntry("key5");
            entity.Value = "5555";
            entity.Dispose();
            Console.WriteLine("CreateEntry 获取信息:" + Cache.Get("key5"));  //效果5555

            //方式2
            using (var entity = Cache.CreateEntry("key5"))
            {
                entity.Value = "5555";
                Console.WriteLine("CreateEntry 获取信息:" + Cache.Get("key5"));  //效果5555
            }

  8、CacheEntry有一个主要的方式Dispose(),由于它继续IDisposable,在Dispost方式中挪用了_notifyCacheEntryDisposed委托。

public void Dispose()
{
      if (!_added)
      {
          _added = true;
          _scope.Dispose();
          _notifyCacheEntryDisposed(this);//在此挪用委托,而此委托是被MemoryCache类中的SetEntry赋值。目的是将CacheEntry实体放入MemoryCache类的字典中,也就是放入缓存中。
          PropagateOptions(CacheEntryHelper.Current);
      

三、MemoryCache组件源码

  1、首先看我们在Startup中声明添加的内存缓存的对应的源码。 services.AddMemoryCache();可以看到这里是将缓存组件使用单例模式注入我们程序中。

        /// <summary>
        /// Adds a non distributed in memory implementation of <see cref="IMemoryCache"/> to the
        /// <see cref="IServiceCollection" />.
        /// </summary>
        /// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
        /// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
        public static IServiceCollection AddMemoryCache(this IServiceCollection services)
        {
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            services.AddOptions();
            services.TryAdd(ServiceDescriptor.Singleton<IMemoryCache, MemoryCache>());

            return services;
        }

  2、MemoryCacheOptions类:主要是设置一些参数

    ExpirationScanFrequency:此字段解释隔一段时间扫描缓存,移除过时缓存,默认频率为一分钟。

    SizeLimit:设置缓存的巨细。

    CompactionPercentage:压缩比例 默以为百分之五。

            //添加内存缓存
            services.AddMemoryCache(x=> {
                x.CompactionPercentage = 0.05;//缓存压缩巨细
                x.ExpirationScanFrequency= new TimeSpan(0, 0, 1); //默认自动扫描时间为三分钟
                x.SizeLimit = 500 * 1024 * 1024; //巨细为500M
            });

  3、MemoryCache类

    1:ConcurrentDictionary<object, CacheEntry> _entries:一个多线程平安的字典类型,实在缓存的本质就是这个字典,将所有缓存都放入这个字典中,然后通过字典的key(字典的key实在和缓存实体CacheEntry的key值一样)获取CacheEntry实体(CacheEntry实体包罗key和value,也就是我们代码中设置的key和value)。

    2:_expirationScanFrequency:Span类型,示意扫描过时缓存的频率时间,此字段的值来自MemoryCacheOptions类的ExpirationScanFrequency。需要注重的是:若是设置为一分钟扫描一次缓存聚集,这个扫描不是自动扫描的,只有当对缓存聚集操作时才会扫描。好比增删改查缓存聚集的时刻,会判断上一次扫描的时间离现在已往多久了,若是跨越扫描设置的时间,才会扫描。

private void StartScanForExpiredItems()//扫描函数。在添加、查找、删除、修改缓存的时刻,会挪用此方式扫描过滤过时缓存,并不是自动隔一段时间执行
        {
            var now = _clock.UtcNow;
            if (_expirationScanFrequency < now - _lastExpirationScan)//判断现在的时间和最后一次扫描时间,是不是大于设置的时间段
            {
                _lastExpirationScan = now;
                Task.Factory.StartNew(state => ScanForExpiredItems((MemoryCache)state), this, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
            }
        }
        private static void ScanForExpiredItems(MemoryCache cache)
        {
            var now = cache._clock.UtcNow;
            foreach (var entry in cache._entries.Values)//然后遍历字典聚集,移除过时缓存
            {
                if (entry.CheckExpired(now))
                {
                    cache.RemoveEntry(entry);
                }
            }
        }
,

AllbetAPP下载

欢迎进入AllbetAPP下载(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。

皇冠体育声明:该文看法仅代表作者自己,与本平台无关。转载请注明:.Net Core缓存组件(MemoryCache)【缓存篇(二)】,.NET Core ResponseCache【缓存篇(一)】

网友评论

  • (*)

最新评论

文章归档

站点信息

  • 文章总数:784
  • 页面总数:0
  • 分类总数:8
  • 标签总数:1280
  • 评论总数:446
  • 浏览总数:31163