详解.Net缓存之MemoryCahe

 更新时间:2021年05月07日 08:54:00   作者:AZRNG  
这篇文章主要介绍了.Net缓存之MemoryCahe的相关资料,帮助大家更好的理解和学习使用.net技术,感兴趣的朋友可以了解下

1. MemoryCahe

NetCore中的缓存和System.Runtime.Caching很相似,但是在功能上做了增强,缓存的key支持object类型;提供了泛型支持;可以读缓存和单个缓存项的大小做限定,可以设置缓存的压缩比例。

通过实现微软官方的Microsoft.Extensions.Caching里面的IDistributedCache接口实现缓存集成到ASPNETCore中

1.1 简单入门

netcore中缓存相关的类库都在 Microsoft.Extensions.Caching ,使用MemoryCache首先安装包

<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="5.0.0" />

注入

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

使用

        private readonly IMemoryCache _cache;
        public HomeController(IMemoryCache cache)
        {
            _cache = cache;
        }

        [HttpGet]
        public string Set()
        {
            //写
            _cache.Set("login", "4545478244");
            return "";
        }

        [HttpGet]
        public string Get()
        {
            //读
            var value = _cache.Get("login");
            return "";
        }

1.2 过期时间

            //1.最简单使用方式
            _cache.Set("mykey", "myvalue");
            //2.绝对过期时间,3秒后过期
            _cache.Set("key1", "value1", new DateTimeOffset(DateTime.Now.AddSeconds(3)));
            //3.绝对过期时间,效果同上
            _cache.Set("key2", "value2", TimeSpan.FromSeconds(3));
            //4.滑动过期时间,3秒后,即三秒钟内被访问,则重新刷新缓存时间为3秒后
            _cache.Set("key3", "value3", new MemoryCacheEntryOptions
            {
                SlidingExpiration = TimeSpan.FromSeconds(3),
            });
            Console.WriteLine("-----------暂停2秒");
            Thread.Sleep(2000);//暂停2秒
            Console.WriteLine($"key1的值:{_cache.Get("key1") ?? "key1被清除"}");
            Console.WriteLine($"key2的值:{_cache.Get("key2") ?? "key2被清除"}");
            Console.WriteLine($"key3的值:{_cache.Get("key3") ?? "key3被清除"}");
            Console.WriteLine("-----------暂停2秒");
            Thread.Sleep(2000);//再次暂停2秒
            Console.WriteLine($"key1的值:{_cache.Get("key1") ?? "key1被清除"}");
            Console.WriteLine($"key2的值:{_cache.Get("key2") ?? "key2被清除"}");
            Console.WriteLine($"key3的值:{_cache.Get("key3") ?? "key3被清除"}");

在例子中key1,key2都是使用的绝对过期时间,key3使用的相对过期时间,2秒后第一次访问key1、key2、key3都没过期,其中key3的过期时间刷新了,重新设置为3秒后,所以再次暂停2秒后,key1、key2都过期了,key3仍然存在。

程序运行结果如下:

1.2 常用配置

下边的例子介绍netcore中缓存的常用配置,直接看代码

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            services.AddMemoryCache(options =>
            {
                //缓存大小
                options.SizeLimit = 3;//如果设置了该值,那么每个set都必须设置size,并且超过了这个值的大小的会自动销毁 
                //缓存满了时,压缩20%(即删除20份优先级低的缓存项)
                options.CompactionPercentage = 0.2;
                //两秒钟查找一次过期项
                options.ExpirationScanFrequency = TimeSpan.FromSeconds(3);
            });
        }

        [HttpGet]
        public string TestSize()
        {
            //SizeLimit配置3
            _cache.Set("item1", "11111", new MemoryCacheEntryOptions
            {
                //缓存大小占1份
                Size = 2
            });
            _cache.Set("item2", "22222", new MemoryCacheEntryOptions
            {
                Size = 2
            });
            var item1 = _cache.Get("item1");//输出 11111
            var item2 = _cache.Get("item2");//输出 null

            return "";
        }

        [HttpGet]
        public string TestOptions()
        {
            //单个缓存项的配置
            MemoryCacheEntryOptions cacheEntityOps = new MemoryCacheEntryOptions()
            {
                //绝对过期时间1
                //AbsoluteExpiration = new DateTimeOffset(DateTime.Now.AddSeconds(2)),
                //绝对过期时间2
                //AbsoluteExpirationRelativeToNow=TimeSpan.FromSeconds(3),
                //相对过期时间
                SlidingExpiration = TimeSpan.FromSeconds(3),
                //优先级,当缓存压缩时会优先清除优先级低的缓存项
                Priority = CacheItemPriority.Low,//优先级等级:Low,Normal,High,NeverRemove
                //缓存大小占1份
                Size = 1
            };
            //注册缓存项被清除时的回调,可以注册多个回调
            cacheEntityOps.RegisterPostEvictionCallback((key, value, reason, state) =>
            {
                Console.WriteLine($"回调函数输出【键:{key},值:{value},被清除的原因:{reason}】");
            });
            _cache.Set("mykey", "myvalue", cacheEntityOps);
            Console.WriteLine($"mykey的值:{_cache.Get("mykey") ?? "mykey缓存被清除了"}");
            Console.WriteLine("------------------暂停3秒");
            Thread.Sleep(3000);
            Console.WriteLine($"mykey的值:{_cache.Get("mykey") ?? "mykey缓存被清除了"}");

            return "";
        }

注意netcore中设置缓存和缓存项大小是没有单位的

缓存被清空的回调函数可以注册多个(System.Runtime.Caching清除缓存的回调只能是一个)。

程序执行结果

1.3 IChangeToken

上边我们已经简单了解了通过滑动过期时间和绝对过期时间来控制缓存的有效性,但是有时缓存的过期与否和时间没有联系,比如我们缓存一个文件的内容,不管缓存多久只要文件没有发生变化缓存都是有效的。在net framework中我们可以通过CacheDependency来控制,在net core中怎么控制呢?net core中我们可以使用IChangeToken接口轻松实现缓存的过期策略。先看一下IChangeToken接口:

    public interface IChangeToken
    {
        // 是否有变化发生
        bool HasChanged { get; }
        // token是否会调用回调函数,为true时才会有效 
        bool ActiveChangeCallbacks { get; }
        // 注册一个回调函数,当有变化时触发回调
        IDisposable RegisterChangeCallback(Action<object> callback, object state);
    }

看一下IChangeToken实现缓存过期策略的两个例子

1.3.1 监控文件

需要安装组件:Microsoft.Extensions.FileProviders.Physical

    internal class Program
    {
        private static void Main(string[] args)
        {
            string fileName = Path.Combine(Environment.CurrentDirectory, "someCacheData.xml");
            var fileInfo = new FileInfo(fileName);
            MemoryCache myCache = new MemoryCache(new MemoryCacheOptions() { });
            MemoryCacheEntryOptions cacheEntityOps = new MemoryCacheEntryOptions();
            //PollingFileChangeToken是IChangeToken的实现类,通过轮询监控文件变化
            cacheEntityOps.AddExpirationToken(new Microsoft.Extensions.FileProviders.Physical.PollingFileChangeToken(fileInfo));
            //缓存失效时,回调函数
            cacheEntityOps.RegisterPostEvictionCallback((key, value, reason, state) => { Console.WriteLine($"文件【{key}】改动了"); });
            //添加缓存,key为文件名,value为文件内容
            myCache.Set(fileInfo.Name, File.ReadAllText(fileName), cacheEntityOps);
            Console.WriteLine(myCache.Get(fileInfo.Name));
        }
    }

PollingFileChangeToken通过轮询来监控文件有没有发生变化,如果文件中的内容发生改变,缓存就会自动过期。

1.3.2 通过代码控制缓存过期

    class Program
    {
        static void Main(string[] args)
        {
            MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions());
            MemoryCacheEntryOptions cacheEntityOps = new MemoryCacheEntryOptions();
            //使用CancellationChangeToken控制缓存过期
            CancellationTokenSource tokenSource = new CancellationTokenSource();
            cacheEntityOps.AddExpirationToken(new CancellationChangeToken(tokenSource.Token));
            //设置缓存
            memoryCache.Set("mykey", "myvalue", cacheEntityOps);
            Console.WriteLine(memoryCache.Get("mykey") ?? "缓存被清除了");
            //通过代码清除缓存
            tokenSource.Cancel();
            Console.WriteLine(memoryCache.Get("mykey") ?? "缓存被清除了");
        }
    }

tokenSource.Cancel方法发送取消信号,这个方法会触发缓存过期,基于此我们可以通过Cancel方法灵活的实现自定义的缓存策略。

程序执行结果如下:

1.4 引用Nuget包

直接引用我自己简单封装的一个Nuget包(简单封装自己用,不要嘲笑)

    <PackageReference Include="Common.Cache.MemoryCache" Version="1.1.0" />

注入到容器

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            //注入
            services.AddMemoryCacheExtension();
        }

使用

        # 在需要使用的地方进行注入
        private readonly IMemoryCachimg  _cache;
        public HomeController(IMemoryCachimg cache)
        {
            _cache = cache;
        }

以上就是详解.Net缓存之MemoryCahe的详细内容,更多关于.Net缓存之MemoryCahe的资料请关注脚本之家其它相关文章!

相关文章

  • asp.net DataGrid控件中弹出详细信息窗口

    asp.net DataGrid控件中弹出详细信息窗口

    在DataGrid控件里单击某一行的超级链接时,弹出一个新的页面显示出该行的详细信息
    2008-12-12
  • asp.net 文件下载功能函数代码整理

    asp.net 文件下载功能函数代码整理

    asp.net下文件下载功能代码,fullFilename 要下载的文件的路径+文件名,需要的朋友可以参考下。
    2010-04-04
  • .NET Core3.0 日志 logging的实现

    .NET Core3.0 日志 logging的实现

    这篇文章主要介绍了.NET Core3.0 日志 logging的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • ASP.NET Ajax级联DropDownList实现代码

    ASP.NET Ajax级联DropDownList实现代码

    我想大家对Ajax已耳熟能详。自web 2.0概念出现以后,提供更好的用户体验变得越来越重要。那么今天我来讲解一下如何使用ASP.NET Ajax和web service构建无刷新级联DropDownList(以下简称为级联DDL)。完成的效果图
    2008-12-12
  • Asp.Net Mvc2 增删改查DEMO代码

    Asp.Net Mvc2 增删改查DEMO代码

    接触mvc也有一段时间了(2.0),也看到园子里很多人在学习,自己也在园子里面看过前辈们写的博客,确实受益匪浅。本文写的都是基础中的基础,仅供想学习MVC的新手们入门之作
    2012-10-10
  • 解决ASP.NET中的各种乱码问题总结

    解决ASP.NET中的各种乱码问题总结

    本篇文章主要介绍了解决ASP.NET中的各种乱码问题总结,非常具有实用价值,需要的朋友可以参考下。
    2016-12-12
  • asp.net类库中添加WebService引用出现问题解决方法

    asp.net类库中添加WebService引用出现问题解决方法

    在Web项目内添加WebService的引用是件很简单的事情,不过对于一些新手朋友来说,就没有那么简单了,因为在添加的过程中总会遇到一些困难,接下来详细介绍如何解决,感兴趣的你可不要错过了啊
    2013-02-02
  • c# .net 生成图片验证码的代码

    c# .net 生成图片验证码的代码

    c# .net 生成图片验证码的代码...
    2007-03-03
  • ASP.NET中Request.Form中文乱码的解决方法

    ASP.NET中Request.Form中文乱码的解决方法

    一直以为,只有 Request.QueryString 接收url查询字符串含中文时可能会乱码(做好编解码工作,很容易可以避免),碰到的时候,才知道 Request.Form 接收表单的值中含中文也会乱码,以前真是很傻很天真很无知。
    2011-03-03
  • 微软官方SqlHelper类 数据库辅助操作类

    微软官方SqlHelper类 数据库辅助操作类

    本文主要介绍微软官方的数据库操作类极其使用方法,帮助大家利用已经非常成熟的类库来进行快速开发。
    2016-03-03

最新评论