.NET Core缓存
目录
缓存的概念
客户端响应缓存
cache-control
服务器端响应缓存
内存缓存(In-memory cache)
用法
GetOrCreateAsync
缓存过期时间策略
缓存的过期时间
解决方法:
两种过期时间策略:
绝对过期时间
滑动过期时间
两种过期时间混用
总结
缓存的概念
缓存(Caching)是用来保存数据的区域,从缓存区域读取数据的速度比从数据源读取数据的速度快很多,从数据源获取数据后,我们可以把数据保存到缓存中,下次再需要获取同样数据时,可以直接从缓存中获取之前保存的数据,是系统优化中简单又有效的工具,投入小收效大。数据库中的索引等简单有效的优化功能本质上都是缓存。
- 缓存命中:从缓存中获取了要获取的数据
- 缓存命中率:多次请求中,命中的请求占全部请求的百分比
- 缓存数据不一致:数据源中数据保存到缓存后,发生了变化
- 多级缓存:在Web开发中,存在多级缓存,浏览器存在“浏览器端缓存”,网关节电服务器存在“节点缓存”,,Web服务器上可能存在“服务器端缓存”,只要在任何一个节点上命中缓存,请求就会直接返回,而不会继续向后传递。


客户端响应缓存
cache-control
- RFC7324是HTTP协议中对缓存进行控制的规范,其中重要的是cache-control这个响应报文头。服务器如果返回cache-control:max-age=60,则表示服务器指示浏览器端“可以缓存这个响应内容60秒”。
- 我们只要给需要进行缓存控制的控制器的操作方法添加ResponseCacheAttribute这个Attribute,ASP.NET Core会自动添加cache-control报文头。
[Route("api/[controller]/[action]")]
[ApiController]
public class TestController : ControllerBase
{[HttpGet][ResponseCache(Duration = 20)]public DateTime Now(){return DateTime.Now;}
}
服务器端响应缓存
- 如果ASP.NET Core中安装了“响应缓存中间件” ,那么ASP.NET Core不仅会继续根据[ResponseCache]设置来生成cache-control响应报文头来设置客户端缓存,而且服务器端也会按照[ResponseCache]的设置来对响应进行服务器端缓存。和客户端端缓存的区别?来自多个不同客户端的相同请求。
- “响应缓存中间件”的好处:对于来自不同客户端的相同请求或者不支持客户端缓存的客户端,能降低服务器端的压力。
- 用法:app.MapControllers()之前加上app.UseResponseCaching()。请确保app.UseCors()写到app.UseResponseCaching()之前。
缺点:
- 无法解决恶意请求给服务器带来的压力。
- 服务器端响应缓存还有很多限制,包括但不限于:响应状态码为200的GET或者HEAD响应才可能被缓存;报文头中不能含有Authorization、Set-Cookie等。
- 可以采用内存缓存、分布式缓存等。
由于服务器端响应缓存开发调试的麻烦以及过于苛刻的限制,因此除非开发人员能够灵活掌握并应用,否则不建议启用“响应缓存中间件”。对于只需要进行客户端响应缓存处理的操作方法,标注ResponseCache即可,如果还需要在服务器端进行缓存处理,建议采用ASP.NET Core提供的内存缓存、分布式缓存等机制来编写程序。
内存缓存(In-memory cache)
把缓存数据放到应用程序的内存。内存缓存中保存的是一系列的键值对,就像Dictionary类型一样。
内存缓存的数据保存在当前运行的网站程序的内存中,是和进程相关的。因为在Web服务器中,多个不同网站是运行在不同的进程中的,因此不同网站的内存缓存是不会互相干扰的,而且网站重启后,内存缓存中的所有数据也就都被清空了。
用法
- 添加服务:builder.Services.AddMemoryCache()
- 注入IMemoryCache接口,查看接口的方法:TryGetValue、Remove、Set、GetOrCreate、GetOrCreateAsync
GetOrCreateAsync
GetOrCreateAsync<TItem>(object key, Func<ICacheEntry, Task<TItem>> factory)
获取缓存键为key的缓存值,方法的返回值为获取的缓存值,如果缓存中没有缓存键为key的缓存值,则调用factory指向的回调从数据源获取数据,把获取的数据作为缓存值保存到缓存中,并且把获取的数据作为方法的返回值。
Program.cs
//添加内存缓存服务
services.AddMemoryCache();
//添加DbContext
services.AddScoped<MyDbContext>();public record Book(long Id, string Name);public class BookConfig : IEntityTypeConfiguration<Book>
{public void Configure(EntityTypeBuilder<Book> builder){builder.ToTable("T_Books");}
}public class MyDbContext:DbContext
{DbSet<Book> books { get; set; }protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){base.OnConfiguring(optionsBuilder);optionsBuilder.UseSqlServer("Server=.;Database=demo;Trusted_Connection=true;MultipleActiveResultSets=true;TrustServerCertificate=true;");}protected override void OnModelCreating(ModelBuilder modelBuilder){base.OnModelCreating(modelBuilder);modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);}
}
[Route("api/[controller]/[action]")]
[ApiController]
public class TestController : ControllerBase
{private readonly IMemoryCache memoryCache;private readonly ILogger<TestController> logger;public TestController(IMemoryCache memoryCache, ILogger<TestController> logger){this.memoryCache = memoryCache;this.logger = logger;}[HttpGet]public async Task<ActionResult<Book?>> GetById(int id){using (MyDbContext ctx = new MyDbContext()){//没加内存缓存//var result = await ctx.Set<Book>().SingleOrDefaultAsync(o => o.Id == id);//if (result == null)//{// return NotFound($"找不到id={id}的书");//}//else//{// return result;//}//内存缓存logger.LogInformation($"开始执行GetBookById,id={id}");Book? b = await memoryCache.GetOrCreateAsync("Book" + id, async (e) =>{logger.LogInformation($"缓存没找到,到数据库查询,id={id}");return await ctx.Set<Book>().SingleOrDefaultAsync(o => o.Id == id);});logger.LogInformation($"GetBookById结果:{b}");if (b == null){return NotFound($"找不到id={id}的书");}else{return Ok(b);}}}
}
查询两次结果

缓存过期时间策略
缓存的过期时间
上面的例子中的缓存不会过期,除非重启服务器。
解决方法:
- 在数据改变的时候调用Remove或者Set来删除或者修改缓存(优点:及时);
- 过期时间(只要过期时间比较短,缓存数据不一致的情况也不会持续很长时间。)
两种过期时间策略:
GetOrCreateAsync()方法的回调方法中有一个ICacheEntry类型的参数,通过ICacheEntry对当前的缓存项做设置。
绝对过期时间
设置缓存完的指定时间后,缓存项被清除。
AbsoluteExpirationRelativeToNow:用来设定缓存项的绝对过期时间。
Book? b = await memoryCache.GetOrCreateAsync("Book" + id, async (e) =>
{logger.LogInformation($"缓存没找到,到数据库查询,id={id}");//缓存有效期10se.AbsoluteExpirationRelativeToNow=TimeSpan.FromSeconds(10);return await ctx.Set<Book>().SingleOrDefaultAsync(o => o.Id == id);
});
滑动过期时间
设置缓存完的指定时间后,如果对应的缓存数据没有被访问,缓存项被清除,如果在指定时间内,被访问一次,则缓存项的过期时间会自动续期。
Book? b = await memoryCache.GetOrCreateAsync("Book" + id, async (e) =>
{logger.LogInformation($"缓存没找到,到数据库查询,id={id}");e.SlidingExpiration=TimeSpan.FromSeconds(10);return await ctx.Set<Book>().SingleOrDefaultAsync(o => o.Id == id);
});
两种过期时间混用
使用滑动过期时间策略,如果一个缓存项一直被频繁访问,那么这个缓存项就会一直被续期而不过期。可以对一个缓存项同时设定滑动过期时间和绝对过期时间,并且把绝对过期时间设定的比滑动过期时间长,这样缓存项的内容会在绝对过期时间内随着访问被滑动续期,但是一旦超过了绝对过期时间,缓存项就会被删除。
总结
- 无论用那种过期时间策略,程序中都会存在缓存数据不一致的情况。部分系统(博客等)无所谓,部分系统不能忍受(比如金融)。
- 可以通过其他机制获取数据源改变的消息,再通过代码调用IMemoryCache的Set方法更新缓存。
相关文章:
.NET Core缓存
目录 缓存的概念 客户端响应缓存 cache-control 服务器端响应缓存 内存缓存(In-memory cache) 用法 GetOrCreateAsync 缓存过期时间策略 缓存的过期时间 解决方法: 两种过期时间策略: 绝对过期时间 滑动过期时间 两…...
GA-CNN-LSTM-Attention、CNN-LSTM-Attention、GA-CNN-LSTM、CNN-LSTM四模型多变量时序预测一键对比
GA-CNN-LSTM-Attention、CNN-LSTM-Attention、GA-CNN-LSTM、CNN-LSTM四模型多变量时序预测一键对比 目录 GA-CNN-LSTM-Attention、CNN-LSTM-Attention、GA-CNN-LSTM、CNN-LSTM四模型多变量时序预测一键对比预测效果基本介绍程序设计参考资料 预测效果 基本介绍 基于GA-CNN-LST…...
git Bash通过SSH key 登录github的详细步骤
1 问题 通过在windows 终端中的通过git登录github 不再是通过密码登录了,需要本地生成一个密钥,配置到gihub中才能使用 2 步骤 (1)首先配置用户名和邮箱 git config --global user.name "用户名"git config --global…...
《企业应用架构模式》笔记
领域逻辑 表模块和数据集一起工作-> 先查询出一个记录集,再根据数据集生成一个(如合同)对象,然后调用合同对象的方法。 这看起来很想service查询出一个对象,但调用的是对象的方法,这看起来像是充血模型…...
深入理解 C 语言函数指针的高级用法:(void (*) (void *)) _IO_funlockfile
深入理解 C 语言函数指针的高级用法 函数指针是 C 语言中极具威力的特性,广泛用于实现回调、动态函数调用以及灵活的程序设计。然而,复杂的函数指针声明常常让即使是有经验的开发者也感到困惑。本文将从函数指针的基本概念出发,逐步解析复杂…...
【JavaSE】图书管理系统
前言:为了巩固之前学习的java知识点,我们用之前学习的java知识点(方法,数组,类和对象,封装,继承,多态,抽象类,接口)来实现一个简单的图书管理系统…...
【C++数论】880. 索引处的解码字符串|2010
本文涉及知识点 数论:质数、最大公约数、菲蜀定理 LeetCode880. 索引处的解码字符串 给定一个编码字符串 s 。请你找出 解码字符串 并将其写入磁带。解码时,从编码字符串中 每次读取一个字符 ,并采取以下步骤: 如果所读的字符是…...
C++/stack_queue
目录 1.stack 1.1stack的介绍 1.2stack的使用 练习题: 1.3stack的模拟实现 2.queue的介绍和使用 2.1queue的介绍 2.2queue的使用 2.3queue的模拟实现 3.priority_queue的介绍和使用 3.1priority_queue的介绍 3.2priority_queue的使用 欢迎 1.stack 1.1stack…...
浅谈APP之历史股票通过echarts绘图
浅谈APP之历史股票通过echarts绘图 需求描述 今天我们需要做一个简单的历史股票收盘价格通过echarts进行绘图,效果如下: 业务实现 代码框架 代码框架如下: . 依赖包下载 我们通过网站下载自己需要的涉及的图标,勾选之后进…...
Ubuntu 20.04 x64下 编译安装ffmpeg
试验的ffmpeg版本 4.1.3 本文使用的config命令 ./configure --prefixhost --enable-shared --disable-static --disable-doc --enable-postproc --enable-gpl --enable-swscale --enable-nonfree --enable-libfdk-aac --enable-decoderh264 --enable-libx265 --enable-libx…...
【橘子Kibana】Kibana的分析能力Analytics简易分析
一、kibana是啥,能干嘛 我们经常会用es来实现一些关于检索,关于分析的业务。但是es本身并没有UI,我们只能通过调用api来完成一些能力。而kibana就是他的一个外置UI,你完全可以这么理解。 当我们进入kibana的主页的时候你可以看到这样的布局。…...
【STM32】-TTP223B触摸开关
前言 本文章旨在记录博主STM32的学习经验,我自身也在不断的学习当中,如果文章有写的不对的地方,欢迎各位大佬批评指正。 准备工作 今天这篇文章介绍的是触摸开关这一外围硬件。 ST-link调试器STM32最小系统板单路TTP223B触摸传感器模块LE…...
三星手机人脸识别解锁需要点击一下电源键,能够不用点击直接解锁吗
三星手机的人脸识别解锁功能默认需要滑动或点击屏幕来解锁。这是为了增强安全性,防止误解锁的情况。如果希望在检测到人脸后直接进入主界面,可以通过以下设置调整: 打开设置: 进入三星手机的【设置】应用。 进入生物识别和安全&a…...
Frida使用指南(三)- Frida-Native-Hook
1.Process、Module、Memory基础 1.Process Process 对象代表当前被Hook的进程,能获取进程的信息,枚举模块,枚举范围等 2.Module Module 对象代表一个加载到进程的模块(例如,在 Windows 上的 DLL,或在 Linux/Android 上的 .so 文件), 能查询模块的信息,如模块的基址、名…...
网络安全 | F5-Attack Signatures-Set详解
关注:CodingTechWork 创建和分配攻击签名集 可以通过两种方式创建攻击签名集:使用过滤器或手动选择要包含的签名。 基于过滤器的签名集仅基于在签名过滤器中定义的标准。基于过滤器的签名集的优点在于,可以专注于定义用户感兴趣的攻击签名…...
004 mybatis基础应用之全局配置文件
文章目录 配置内容properties标签typeAlias标签mappers标签 配置内容 SqlMapConfig.xml中配置的内容和顺序如下: properties(属性) settings(全局配置参数) typeAliases(类型别名) typeHandler…...
【岛屿个数——BFS / DFS,“外海”】
题目 推荐阅读 AcWing 4959. 岛屿个数(两种解法,通俗解释) - AcWing 1.岛屿个数 - 蓝桥云课 (lanqiao.cn) 代码 #include <bits/stdc.h> using namespace std; #define x first #define y second int dx4[4] {-1, 0, 1, 0}, dy4[4] …...
MySQL常用数据类型和表的操作
文章目录 (一)常用数据类型1.数值类2.字符串类型3.二进制类型4.日期类型 (二)表的操作1查看指定库中所有表2.创建表3.查看表结构和查看表的创建语句4.修改表5.删除表 (三)总代码 (一)常用数据类型 1.数值类 BIT([M]) 大小:bit M表示每个数的位数,取值范围为1~64,若…...
2025_1_27 C语言内存,递归,汉诺塔问题
1.c程序在内存中的布局 代码段(Code Segment) 位置:通常位于内存的最低地址。 用途:存储程序的可执行指令。 特点:只读,防止程序运行时被修改。数据段(Data Segment) 位置…...
开源音乐管理软件Melody
本文软件由网友 heqiusheng 推荐。不过好像已经是一年前了 😂 简介 什么是 Melody ? Melody 是你的音乐精灵,旨在帮助你更好地管理音乐。目前的主要能力是帮助你将喜欢的歌曲或者音频上传到音乐平台的云盘。 主要功能包括: 歌曲…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...
AI语音助手的Python实现
引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...
Linux 下 DMA 内存映射浅析
序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存,但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程,可以参考这篇文章,我觉得写的非常…...
