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;
}

参考文档

作者:捞月亮的猴子  https://www.cnblogs.com/wyy1234/p/10519681.html
官方教程:https://docs.microsoft.com/zh-cn/aspnet/core/performance/caching/memory?view=aspnetcore-5.0

微信公众号

.Net缓存之MemoryCahe的更多相关文章

  1. .Net Core缓存组件(Redis)源码解析

    上一篇文章已经介绍了MemoryCache,MemoryCache存储的数据类型是Object,也说了Redis支持五中数据类型的存储,但是微软的Redis缓存组件只实现了Hash类型的存储.在分析源 ...

  2. 探究javascript对象和数组的异同,及函数变量缓存技巧

    javascript中最经典也最受非议的一句话就是:javascript中一切皆是对象.这篇重点要提到的,就是任何jser都不陌生的Object和Array. 有段时间曾经很诧异,到底两种数据类型用来 ...

  3. 哪种缓存效果高?开源一个简单的缓存组件j2cache

    背景 现在的web系统已经越来越多的应用缓存技术,而且缓存技术确实是能实足的增强系统性能的.我在项目中也开始接触一些缓存的需求. 开始简单的就用jvm(java托管内存)来做缓存,这样对于单个应用服务 ...

  4. ASP.NET Core 中间件之压缩、缓存

    前言 今天给大家介绍一下在 ASP.NET Core 日常开发中用的比较多的两个中间件,它们都是出自于微软的 ASP.NET 团队,他们分别是 Microsoft.AspNetCore.Respons ...

  5. ASP.NET Core 折腾笔记二:自己写个完整的Cache缓存类来支持.NET Core

    背景: 1:.NET Core 已经没System.Web,也木有了HttpRuntime.Cache,因此,该空间下Cache也木有了. 2:.NET Core 有新的Memory Cache提供, ...

  6. [Java 缓存] Java Cache之 DCache的简单应用.

    前言 上次总结了下本地缓存Guava Cache的简单应用, 这次来继续说下项目中使用的DCache的简单使用. 这里分为几部分进行总结, 1)DCache介绍; 2)DCache配置及使用; 3)使 ...

  7. [原创]mybatis中整合ehcache缓存框架的使用

    mybatis整合ehcache缓存框架的使用 mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓 ...

  8. 探索ASP.NET MVC5系列之~~~5.缓存篇(页面缓存+二级缓存)

    其实任何资料里面的任何知识点都无所谓,都是不重要的,重要的是学习方法,自行摸索的过程(不妥之处欢迎指正) 汇总:http://www.cnblogs.com/dunitian/p/4822808.ht ...

  9. 深究标准IO的缓存

    前言 在最近看了APUE的标准IO部分之后感觉对标准IO的缓存太模糊,没有搞明白,APUE中关于缓存的部分一笔带过,没有深究缓存的实现原理,这样一本被吹上天的书为什么不讲透彻呢?今天早上爬起来赶紧找了 ...

  10. 缓存工厂之Redis缓存

    这几天没有按照计划分享技术博文,主要是去医院了,这里一想到在医院经历的种种,我真的有话要说:医院里的医务人员曾经被吹捧为美丽+和蔼+可亲的天使,在经受5天左右相互接触后不得不让感慨:遇见的有些人员在挂 ...

随机推荐

  1. wap2app下拉刷新

    支持全局刷新,支持vue项目 目前支持wap2app,uin-app全局下拉刷新 戳我阅读原文 --转载自微信公众号:酿俗

  2. 小白学k8s(10)-k8s中ConfigMap理解

    理解ConfigMap 什么是ConfigMap ConfigMap的创建 使用key-value 字符串创建 从env文件创建 从目录创建 通过Yaml/Json创建 ConfigMap使用 用作环 ...

  3. Flask 实现文件上传下载

    Flask 针对文件的上传下载相关代码片段,多种方法,包括限制文件格式,大小等. 实现图片文件上传 # name: 简单的实现文件上传任务. import os from flask import F ...

  4. Flask 框架:运用Ajax实现数据交互

    使用Ajax技术网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载刷新整个页面,这使得程序能够更快地回应用户的操作,如下笔记将简单介绍使用AJAX如何实现前后端数据通信. 前后端发送字符串 前 ...

  5. Java注解之获取注解内部数据的原因分析

    我们都知道从JDK1.5开始,注解开始被支持使用,当我们在使用注解的时候感觉比配置文件用起来更加简便和清爽.配置文件是通过解析配置文件的内容获取到数据,那么为什么仅仅在类.方法或者属性上添加注解被注解 ...

  6. shell find 根据时间获取文件列表

    根据时间得到文件,可以使用find进行查找,支持查找: find以时间为条件查找可用选项: -amin n:查找n分钟以前被访问过的所有文件. -atime n:查找n天以前被访问过的所有文件. -c ...

  7. Python内置小工具(非常实用!)

    一.1秒钟启动一个下载服务器在工作中时不时会有这样的一个需求:将服务器(或者自己电脑)上的文件传给其他同事.将文件传给同事本身并不是一个很繁琐的工作,现在的聊天工具一般都支持文件传输.但是,如果需要传 ...

  8. let与const

    let与const ES2015(ES6)新增加了两个重要的JavaScript关键字: let和const. 块级作用域 代码块内如果存在let或者const,代码块会对这些命令声明的变量从块的开始 ...

  9. Jsp+Servlet实现文件上传下载(四)--下载文件

    接着上一篇讲: Jsp+Servlet实现文件上传下载(三)--删除上传文件    点击打开链接 本章来实现一下下载文件功能,同时优化了一下上一章中的代码. 废话少说,上代码 ------------ ...

  10. duilib 入坑

    记录 duilib 开发遇到的问题 当前最新的 duilib 版本更新是在  2019-4-28-2,从 vcpkg 查询得知 我的机器是 windows 10,vs2019 我是从 duilib 库 ...