您的位置:首页 > 教程 > ASP.NET > 一文掌握.Net core中的缓存

一文掌握.Net core中的缓存

2022-06-18 11:55:46 来源:易采站长站 作者:

一文掌握.Net core中的缓存

目录
1 Net Framewoke的缓存1.1 System.Web.Caching1.2 System.Runtime.Caching2 Net core的缓存介绍2.1 MemoryCache2.2 RedisCache

Cache(缓存)是优化web应用的常用方法,缓存存放在服务端的内存中,被所有用户共享。由于Cache存放在服务器的内存中,所以用户获取缓存资源的速度远比从服务器硬盘中获取快,但是从资源占有的角度考虑缓存也不是越多越好。经常要用到且不会频繁改变且被用户共享的数据很适合放在缓存中。在介绍netcore的缓存前我们先回顾下net framework中的缓存技术。hZN站长之家-易采站长站-Easck.Com

net framework中常用的缓存有两种:System.Runtime.Caching和System.Web.CachinghZN站长之家-易采站长站-Easck.Com

hZN站长之家-易采站长站-Easck.Com

1>

hZN站长之家-易采站长站-Easck.Com

1.1>

  System.Web.Caching应该是我们最熟悉的缓存类库了,做ASP.NET开发时用到缓存基本都是使用的这个缓存组件,简单回顾一下用法吧hZN站长之家-易采站长站-Easck.Com

using System.Web;
using System.Web.Caching;
namespace FrameCache
{
    class Program
    {
        static void Main(string[] args)
        {
            //1.简单缓存,value可以是任何类型
            HttpRuntime.Cache.Insert("mykey", "myvalue");
            Console.WriteLine($"Key为mykey的缓存:{HttpRuntime.Cache["mykey"]}");
            //2.使用缓存依赖项
            string path = Path.Combine(Environment.CurrentDirectory, @"someCacheData.xml");
            DataSet ds = new DataSet();
            ds.ReadXml(path);
            if (HttpRuntime.Cache.Get("myxml") == null)
            {
                //Dataset添加到缓存
                System.Web.HttpRuntime.Cache.Insert("myxml", ds, new CacheDependency(path));
            }
            //从缓存中获取Dataset
            DataSet resultDs = (DataSet)HttpRuntime.Cache.Get("myxml");
            Console.WriteLine($"food下的f1节点:{resultDs.Tables["food"].Rows[0]["f1"]}");
            Console.ReadKey();
        }
    }
}

简单的缓存就不说了,添加一下key和value就可以,缓存依赖项CacheDependency是更新缓存的重要手段,但缓存依赖项发生变化时缓存就会被清理。上边栗子中缓存只依赖一个文件,当缓存依赖多个文件时可以这样设置: CacheDependency cdp=new CacheDependency(new string []{"111.xml","222.xml"});。栗子中someCacheData.xml中的内容是:hZN站长之家-易采站长站-Easck.Com

<?xml version="1.0" encoding="utf-8" ?>
<MyCache>
  <animals>
    <a1>cat</a1>
    <a2>dog</a2>
  </animals>
  <food>
    <f1>Apple</f1>
    <f2>pear</f2>
  </food>
</MyCache>

运行程序结果如下:hZN站长之家-易采站长站-Easck.Com

hZN站长之家-易采站长站-Easck.Com

hZN站长之家-易采站长站-Easck.Com

1.2>

Net Framework中的MemoryCache类就是来自于这个类库,也是开发中经常用到的类库,net core中的缓存用法和这个类库十分相似。简单看一下用法吧hZN站长之家-易采站长站-Easck.Com

using System.Runtime.Caching;
namespace FrameCache
{
    class Program
    {
        static void Main(string[] args)
        {
            //缓存的配置
            CacheItemPolicy policy = new CacheItemPolicy()
            {
                //缓存被删除是的回调
                RemovedCallback = (arguments) => { Console.WriteLine($"缓存被移除的原因:{arguments.RemovedReason}"); },
                //滑动过期时间
                SlidingExpiration = TimeSpan.FromSeconds(5),
                //绝对过期时间
                //AbsoluteExpiration = DateTime.Now.AddSeconds(5),
                //优先级有两种:Default,NotRemovable(不可移除)
                Priority = System.Runtime.Caching.CacheItemPriority.NotRemovable
            };

            //添加缓存,key为mykey,值是myvalue ,
            System.Runtime.Caching.MemoryCache.Default.Add("mykey", "myvalue", policy);
            Thread.Sleep(6000);
            Console.WriteLine(MemoryCache.Default.Get("mykey"));
            Console.ReadKey();
        }
    }
}

CacheItemPolicy 对象用于对缓存项做一个设置,如设置绝对/滑动过期时间,优先级,缓存被清理时的回调函数等。程序运行结果如下,如果我们把线程休眠的代码注释掉,则输出为 “myvlaue”。hZN站长之家-易采站长站-Easck.Com

hZN站长之家-易采站长站-Easck.Com

hZN站长之家-易采站长站-Easck.Com

2>

netcore中的缓存用户和System.Runtime.Caching很相似,但是在功能上做了增强:缓存的key可以支持object类型(.netframework中缓存key只支持string);提供了泛型支持;可以对缓存和单个缓存项的大小做限定,可以设定缓存的压缩比例(如缓存最大设置为100M,压缩比例为0.2,那么缓存达到一百兆时会清除20M的缓存数据,清除时优先级低的缓存项会被优先清除);此外微软提供了Sqlserver和Redis的缓存支持,可以让我们更方便地实现分布式缓存。hZN站长之家-易采站长站-Easck.Com

hZN站长之家-易采站长站-Easck.Com

2.1>

1.过期时间  hZN站长之家-易采站长站-Easck.Com

netcore中缓存相关的类库都在Microsoft.Extensions.Caching,使用MemoryCache首先安装包hZN站长之家-易采站长站-Easck.Com

Install-Package Microsoft.Extensions.Caching.Memory

使用的方式和基本一样,我们简单看一下代码hZN站长之家-易采站长站-Easck.Com

using Microsoft.Extensions.Caching.Memory;
namespace CacheDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions() { });
            //1.最简单使用方式
            memoryCache.Set("mykey", "myvalue");

            //2.绝对过期时间,3秒后过期
            memoryCache.Set("key1", "value1", new DateTimeOffset(DateTime.Now.AddSeconds(3)));
            //3.绝对过期时间,效果同上
            memoryCache.Set("key2", "value2", TimeSpan.FromSeconds(3));
            //4.滑动过期时间,3秒后,即三秒钟内被访问,则重新刷新缓存时间为3秒后
            memoryCache.Set("key3", "value3", new MemoryCacheEntryOptions
            {
                SlidingExpiration = TimeSpan.FromSeconds(3),
            });

            Console.WriteLine("-----------暂停2秒");
            Thread.Sleep(2000);//暂停2秒
            Console.WriteLine($"key1的值:{memoryCache.Get("key1") ?? "key1被清除"}");
            Console.WriteLine($"key2的值:{memoryCache.Get("key2") ?? "key2被清除"}");
            Console.WriteLine($"key3的值:{memoryCache.Get("key3") ?? "key3被清除"}");

            Console.WriteLine("-----------暂停2秒");
            Thread.Sleep(2000);//再次暂停2秒
            Console.WriteLine($"key1的值:{memoryCache.Get("key1") ?? "key1被清除"}");
            Console.WriteLine($"key2的值:{memoryCache.Get("key2") ?? "key2被清除"}");
            Console.WriteLine($"key3的值:{memoryCache.Get("key3") ?? "key3被清除"}");
        }
    }
}

在栗子中key1,key2都是使用的绝对过期时间,key3使用的相对过期时间,2秒后第一次访问key1、key2、key3都没过期,其中key3的过期时间刷新了,重新设置为3秒后,所以再次暂停2秒后,key1、key2都过期了,key3仍然存在。程序运行结果如下:hZN站长之家-易采站长站-Easck.Com

hZN站长之家-易采站长站-Easck.Com

2.常用配置hZN站长之家-易采站长站-Easck.Com

上边我们知道了netcore中缓存的简单用法,下边的栗子介绍netcore中缓存的常用配置,直接看代码hZN站长之家-易采站长站-Easck.Com

class Program
    {
        static void Main(string[] args)
        {
            //缓存的配置
            MemoryCacheOptions cacheOps = new MemoryCacheOptions()
            {
                //缓存最大为100份
                //##注意netcore中的缓存是没有单位的,缓存项和缓存的相对关系
                SizeLimit = 100,
                //缓存满了时,压缩20%(即删除20份优先级低的缓存项)
                CompactionPercentage = 0.2,
                //两秒钟查找一次过期项
                ExpirationScanFrequency = TimeSpan.FromSeconds(3)
            };
            MemoryCache myCache = new MemoryCache(cacheOps);

            //单个缓存项的配置
            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}】");
            });

            myCache.Set("mykey", "myvalue", cacheEntityOps);
            Console.WriteLine($"mykey的值:{myCache.Get("mykey") ?? "mykey缓存被清除了"}");
            Console.WriteLine("------------------暂停3秒");
            Thread.Sleep(3000);
            Console.WriteLine($"mykey的值:{myCache.Get("mykey") ?? "mykey缓存被清除了"}");

            Console.ReadKey();
        }
    }
}

这里需要注意netcore中设置缓存和缓存项大小是没有单位的,缓存被清空的回调函数可以注册多个(System.Runtime.Caching清除缓存的回调只能是一个)。程序执行结果hZN站长之家-易采站长站-Easck.Com

hZN站长之家-易采站长站-Easck.Com

3.IChangeTokenhZN站长之家-易采站长站-Easck.Com

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

public interface IChangeToken
    {
        // 是否有变化发生
        bool HasChanged { get; }

        // token是否会调用回调函数,为true时才会有效 
        bool ActiveChangeCallbacks { get; }

       // 注册一个回调函数,当有变化时触发回调
        IDisposable RegisterChangeCallback(Action<object> callback, object state);
    }

看一下IChangeToken实现缓存过期策略的两个例子:hZN站长之家-易采站长站-Easck.Com

① 监控文件hZN站长之家-易采站长站-Easck.Com

class Program
    {
        static void Main(string[] args)
        {
            string fileName = Path.Combine(Environment.CurrentDirectory, "someCacheData.xml");
            FileInfo 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通过轮询来监控文件有没有发生变化,如果文件中的内容发生改变,缓存就会自动过期。hZN站长之家-易采站长站-Easck.Com

② 通过代码控制缓存过期hZN站长之家-易采站长站-Easck.Com

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方法灵活的实现自定义的缓存策略。程序执行结果如下:hZN站长之家-易采站长站-Easck.Com

hZN站长之家-易采站长站-Easck.Com

hZN站长之家-易采站长站-Easck.Com

2.2>

微软给netcore的缓存提供了Redis和Sqlserver的实现,通过Sqlserver来缓存的场景比较少,这里我们简单看一下官方提供的Redis缓存用法。hZN站长之家-易采站长站-Easck.Com

准备工作:我已经在一台Linu虚拟机上部署了Redis服务,虚拟机IP为192.168.70.99,Redis采用默认端口6379,密码是xxxxx。我开发使用的电脑可以连接到虚拟机上的Redis服务器。hZN站长之家-易采站长站-Easck.Com

首先添加包hZN站长之家-易采站长站-Easck.Com

Install-Package Microsoft.Extensions.Caching
Install-Package Microsoft.Extensions.Caching.Redis

然后我们写一个简单的控制台程序实现一下netcore中的redis缓存实现,代码如下:hZN站长之家-易采站长站-Easck.Com

static void Main(string[] args)
        {
            //获取RedisCache实例
            RedisCache redisCache = new RedisCache(new RedisCacheOptions()
            {
                Configuration = "192.168.70.99:6379,password=xxxxx",
                InstanceName = "MyData"
            });
            //在redis中是以hash表的模式存放的
            redisCache.SetString("Name", "jack");
            redisCache.SetString("Age", "20");
            redisCache.SetString("Address", "上海", new DistributedCacheEntryOptions()
            {
                //SlidingExpiration = TimeSpan.FromSeconds(3)
                AbsoluteExpiration = DateTimeOffset.Now.AddDays(1)
            });
            //获取缓存
            //Console.WriteLine(redisCache.GetString("Name"));
        }

执行完成,缓存数据以Hash表形式存储在redis中,如下:hZN站长之家-易采站长站-Easck.Com

hZN站长之家-易采站长站-Easck.Com

这里只是介绍了netcore中redis缓存的简单用法,其实官方提供的Redis缓存扩展中的Api很少,远没有MemoryCache那么多,我们使用netcore中的Redis缓存时,更多要使用Redis自身提供的功能。hZN站长之家-易采站长站-Easck.Com

到此这篇关于.Net core中的缓存介绍的文章就介绍到这了,更多相关.netcore缓存介绍内容请搜索易采站长站以前的文章或继续浏览下面的相关文章希望大家以后多多支持易采站长站!hZN站长之家-易采站长站-Easck.Com

如有侵权,请联系QQ:279390809 电话:15144810328

相关文章

  • [Asp.Net Core] 浅谈Blazor Server Side

    [Asp.Net Core] 浅谈Blazor Server Side

    在2016年, 本人就开始了一个内部项目, 其特点就是用C#构建DOM树, 然后把DOM同步到浏览器中显示. 并且在一些小工程中使用. 3年下来, 效果很不错, 但因为是使用C#来构建控件树, 在没有特定
    2020-07-01
  • asp.net生成Excel并导出下载五种实现方法

    asp.net生成Excel并导出下载五种实现方法

    方法一 通过GridView(简评:方法比较简单,但是只适合生成格式简单的Excel,且无法保留VBA代码),页面无刷新 aspx.cs部分 代码如下: using System; using System.Collections; using System.Configuration; usi
    2019-05-16
  • Asp.Net Core用NLog记录日志操作方法

    Asp.Net Core用NLog记录日志操作方法

    需求 1.日志自动写入到数据库、写入到文件 2.appsettings.json数据库连接更改后,不需要去改NLog中的连接地址,启动网站或项目时自动检测变动然后去更改,以appsettings.json为准,保持同步
    2019-11-19
  • 使用vs2019加.net core 对WeiApi的创建过程详解

    使用vs2019加.net core 对WeiApi的创建过程详解

    vs2019创建webapi 1.创建新的项目 2.选择.NET CORE的ASP .NET CORE WEB应用程序 3.定义项目名称和存放地点 4.选择API创建项目 5.删除原本的无用的类 6.添加新的方法类 7.设置路由 using Microsoft.AspNe
    2020-07-03
  • 教你Asp.net下使用mysql数据库的步骤

    教你Asp.net下使用mysql数据库的步骤

    1. 首先需要安装mysql, 易采站长站下载地址: //www.jb51.net/softs/2193.html 或者去mysql.com官网都可以,一路next,安装好后,有个简单配置,提示有个设置登录密码和服务名称, 默认localhost,用
    2019-05-16
  • [Asp.Net Core]用Blazor Server Side实现图片验证码

    [Asp.Net Core]用Blazor Server Side实现图片验证码

    关于Blazor 由于在国内, Blazor一点都不普及, 在阅读此文前, 建议读者先翻看我之前写的随笔, 了解Blazor Server Side的特点. 在一段时间内, 我会写一些解说分析型的 "为什么选择 Blazor Server
    2020-07-01
  • 详解ASP.NET Razor 语法

    详解ASP.NET Razor 语法

    Razor 同时支持 C# (C sharp) 和 VB (Visual Basic)。 主要的 Razor C# 语法规则 Razor 代码块包含在 @{ ... } 中 内联表达式(变量和函数)以 @ 开头 代码语句用分号结束 变量使用 var 关键字声明 字符
    2020-07-07
  • .Net Core中使用ExceptionFilter过滤器的方法

    .Net Core中使用ExceptionFilter过滤器的方法

    .Net Core中有各种Filter,分别是AuthorizationFilter、ResourceFilter、ExceptionFilter、ActionFilter、ResultFilter。可以把他们看作是.Net Core自带的AOP的扩展封装。 今天来看其中的一种:ExceptionFilter(用于
    2020-03-03