.NET Core緩存

目錄

緩存的概念

客戶端響應緩存

cache-control

服務器端響應緩存

內存緩存(In-memory cache)

用法

GetOrCreateAsync

緩存過期時間策略

緩存的過期時間

解決方法:

兩種過期時間策略:

絕對過期時間

滑動過期時間

兩種過期時間混用

總結

?封裝內存緩存操作的幫助類

使用


緩存的概念

緩存(Caching)是用來保存數據的區域,從緩存區域讀取數據的速度比從數據源讀取數據的速度快很多,從數據源獲取數據后,我們可以把數據保存到緩存中,下次再需要獲取同樣數據時,可以直接從緩存中獲取之前保存的數據,是系統優化中簡單又有效的工具,投入小收效大。數據庫中的索引等簡單有效的優化功能本質上都是緩存。

  1. 緩存命中:從緩存中獲取了要獲取的數據
  2. 緩存命中率:多次請求中,命中的請求占全部請求的百分比
  3. 緩存數據不一致:數據源中數據保存到緩存后,發生了變化
  4. 多級緩存:在Web開發中,存在多級緩存,瀏覽器存在“瀏覽器端緩存”,網關節電服務器存在“節點緩存”,,Web服務器上可能存在“服務器端緩存”,只要在任何一個節點上命中緩存,請求就會直接返回,而不會繼續向后傳遞。

?

?

客戶端響應緩存

cache-control

  1. RFC7324是HTTP協議中對緩存進行控制的規范,其中重要的是cache-control這個響應報文頭。服務器如果返回cache-control:max-age=60,則表示服務器指示瀏覽器端“可以緩存這個響應內容60秒”。
  2. 我們只要給需要進行緩存控制的控制器的操作方法添加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;}
}

服務器端響應緩存

  1. 如果ASP.NET Core中安裝了“響應緩存中間件” ,那么ASP.NET Core不僅會繼續根據[ResponseCache]設置來生成cache-control響應報文頭來設置客戶端緩存,而且服務器端也會按照[ResponseCache]的設置來對響應進行服務器端緩存。和客戶端端緩存的區別?來自多個不同客戶端的相同請求。
  2. “響應緩存中間件”的好處:對于來自不同客戶端的相同請求或者不支持客戶端緩存的客戶端,能降低服務器端的壓力。
  3. 用法:app.MapControllers()之前加上app.UseResponseCaching()。請確保app.UseCors()寫到app.UseResponseCaching()之前。

缺點:

  1. 無法解決惡意請求給服務器帶來的壓力。
  2. 服務器端響應緩存還有很多限制,包括但不限于:響應狀態碼為200的GET或者HEAD響應才可能被緩存;報文頭中不能含有Authorization、Set-Cookie等。
  3. 可以采用內存緩存、分布式緩存等。

由于服務器端響應緩存開發調試的麻煩以及過于苛刻的限制,因此除非開發人員能夠靈活掌握并應用,否則不建議啟用“響應緩存中間件”。對于只需要進行客戶端響應緩存處理的操作方法,標注ResponseCache即可,如果還需要在服務器端進行緩存處理,建議采用ASP.NET Core提供的內存緩存、分布式緩存等機制來編寫程序。

內存緩存(In-memory cache)

把緩存數據放到應用程序的內存。內存緩存中保存的是一系列的鍵值對,就像Dictionary類型一樣。

內存緩存的數據保存在當前運行的網站程序的內存中,是和進程相關的。因為在Web服務器中,多個不同網站是運行在不同的進程中的,因此不同網站的內存緩存是不會互相干擾的,而且網站重啟后,內存緩存中的所有數據也就都被清空了。

用法

  1. 添加服務:builder.Services.AddMemoryCache()
  2. 注入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);}}}
}

?查詢兩次結果

緩存過期時間策略

緩存的過期時間

上面的例子中的緩存不會過期,除非重啟服務器。

解決方法:

  1. 在數據改變的時候調用Remove或者Set來刪除或者修改緩存(優點:及時);
  2. 過期時間(只要過期時間比較短,緩存數據不一致的情況也不會持續很長時間。)

兩種過期時間策略:

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);
});
兩種過期時間混用

使用滑動過期時間策略,如果一個緩存項一直被頻繁訪問,那么這個緩存項就會一直被續期而不過期。可以對一個緩存項同時設定滑動過期時間和絕對過期時間,并且把絕對過期時間設定的比滑動過期時間長,這樣緩存項的內容會在絕對過期時間內隨著訪問被滑動續期,但是一旦超過了絕對過期時間,緩存項就會被刪除。

總結

  1. 無論用那種過期時間策略,程序中都會存在緩存數據不一致的情況。部分系統(博客等)無所謂,部分系統不能忍受(比如金融)。
  2. 可以通過其他機制獲取數據源改變的消息,再通過代碼調用IMemoryCache的Set方法更新緩存。

?封裝內存緩存操作的幫助類

  1. IQueryable、IEnumerable等類型可能存在著延遲加載的問題,如果把這兩種類型的變量指向的對象保存到緩存中,在我們把它們取出來再去執行的時候,如果它們延遲加載時候需要的對象已經被釋放的話,就會執行失敗。因此緩存禁止這兩種類型。
  2. 實現隨機緩存過期時間

使用

Install-Package Zack.ASPNETCore
NETBookMaterials/最后大項目代碼/YouZack-VNext/Zack.ASPNETCore/MemoryCacheHelper.cs at main · yangzhongke/NETBookMaterialshttps://github.com/yangzhongke/NETBookMaterials/blob/main/%E6%9C%80%E5%90%8E%E5%A4%A7%E9%A1%B9%E7%9B%AE%E4%BB%A3%E7%A0%81/YouZack-VNext/Zack.ASPNETCore/MemoryCacheHelper.cshttps://github.com/yangzhongke/NETBookMaterials/blob/main/%E6%9C%80%E5%90%8E%E5%A4%A7%E9%A1%B9%E7%9B%AE%E4%BB%A3%E7%A0%81/YouZack-VNext/Zack.ASPNETCore/MemoryCacheHelper.cshttps://github.com/yangzhongke/NETBookMaterials/blob/main/%E6%9C%80%E5%90%8E%E5%A4%A7%E9%A1%B9%E7%9B%AE%E4%BB%A3%E7%A0%81/YouZack-VNext/Zack.ASPNETCore/MemoryCacheHelper.cshttps://github.com/yangzhongke/NETBookMaterials/blob/main/%E6%9C%80%E5%90%8E%E5%A4%A7%E9%A1%B9%E7%9B%AE%E4%BB%A3%E7%A0%81/YouZack-VNext/Zack.ASPNETCore/MemoryCacheHelper.cs

services.AddMemoryCache();
services.AddScoped<IMemoryCacheHelper,MemoryCacheHelper>();public TestController(IMemoryCache memoryCache, MyDbContext ctx, MemoryCacheHelper memoryCacheHelper)
{this.memoryCache = memoryCache;this.ctx = ctx;this.memoryCacheHelper = memoryCacheHelper;
}[HttpGet]
public async Task<ActionResult<Book?>> Test(long id)
{var b = memoryCacheHelper.GetOrCreateAsync("Book" + id, async (e) =>{return await ctx.Set<Book>().SingleOrDefaultAsync(o => o.Id == id);}, 10);if (b.Result == null){return NotFound("不存在");}else{return Ok(b.Result);}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/67556.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/67556.shtml
英文地址,請注明出處:http://en.pswp.cn/web/67556.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

自動駕駛---蘇箐對智駕產品的思考

1 前言 對于更高級別的自動駕駛&#xff0c;很多人都有不同的思考&#xff0c;方案也好&#xff0c;產品也罷。最近在圈內一位知名的自動駕駛專家蘇箐發表了他自己對于自動駕駛未來的思考。 蘇箐是地平線的副總裁兼首席架構師&#xff0c;同時也是高階智能駕駛解決方案SuperDri…

Sklearn 中的邏輯回歸

邏輯回歸的數學模型 基本模型 邏輯回歸主要用于處理二分類問題。二分類問題對于模型的輸出包含 0 和 1&#xff0c;是一個不連續的值。分類問題的結果一般不能由線性函數求出。這里就需要一個特別的函數來求解&#xff0c;這里引入一個新的函數 Sigmoid 函數&#xff0c;也成…

FPGA|使用quartus II通過AS下載POF固件

1、將開發板設置到AS下載擋位&#xff0c;或者把下載線插入到AS端口 2、打開quartus II&#xff0c;選擇Tools→Programmer→ Mode選擇Active Serial Programming 3、點擊左側Add file…&#xff0c;選擇 .pof 文件 →start 4、勾選program和verify&#xff08;可選&#xff0…

.Net / C# 分析文件編碼 并將 各種編碼格式 轉為 另一個編碼格式 ( 比如: GB2312→UTF-8, UTF-8→GB2312)

相關庫 .Net 8 編碼識別: github.com/CharsetDetector/UTF-unknown <PackageReference Include"UTF.Unknown" Version"2.5.1" />代碼 using UtfUnknown;var dir_path "D:\\Desktop\\新建文件夾2\\新建文件夾"; var dir_new_path &quo…

32. C 語言 安全函數( _s 尾綴)

本章目錄 前言什么是安全函數&#xff1f;安全函數的特點主要的安全函數1. 字符串操作安全函數2. 格式化輸出安全函數3. 內存操作安全函數4. 其他常用安全函數 安全函數實例示例 1&#xff1a;strcpy_s 和 strcat_s示例 2&#xff1a;memcpy_s示例 3&#xff1a;strtok_s 總結 …

淺談網絡 | 容器網絡之Flannel

目錄 云原生網絡架構深度解構&#xff1a;Flannel的設計哲學與實現機制Flannel架構解析&#xff1a;三層核心設計原則UDP模式&#xff08;用戶態隧道&#xff09;VXLAN模式&#xff08;內核態隧道&#xff09;Host-GW模式&#xff08;直連路由&#xff09; 生產環境架構選型與調…

autosar bsw 的關鍵模塊

AUTOSAR&#xff08;AUTomotive Open System ARchitecture&#xff09;的**基礎軟件層&#xff08;BSW&#xff0c;Basic Software&#xff09;**是汽車電子系統標準化的核心&#xff0c;負責提供硬件抽象、通信、診斷、安全等基礎服務。以下是BSW的關鍵模塊及其功能分類&#…

hive:基本數據類型,關于表和列語法

基本數據類型 Hive 的數據類型分為基本數據類型和復雜數據類型 加粗的是常用數據類型 BOOLEAN出現ture和false外的其他值會變成NULL值 沒有number,decimal類似number 如果輸入的數據不符合數據類型, 映射時會變成NULL, 但是數據本身并沒有被修改 創建表 創建表的本質其實就是在…

2025創業思路和方向有哪些?

創業思路和方向是決定創業成功與否的關鍵因素。以下是一些基于找到的參考內容的創業思路和方向&#xff0c;旨在激發創業靈感&#xff1a; 一、技術創新與融合&#xff1a; 1、智能手機與云電視結合&#xff1a;開發集成智能手機功能的云電視&#xff0c;提供通訊、娛樂一體化體…

航空客戶價值的數據挖掘與分析(numpy+pandas+matplotlib+scikit-learn)

航空客戶價值的數據挖掘與分析(numpy+pandas+matplotlib+scikit-learn) K-Means聚類:https://en.wikipedia.org/wiki/K-means_clustering寫在前面 實現目的:基于K-Means聚類分析模型實現航空客戶價值大數據分析。 電腦系統:Windows 使用軟件:Anaconda(Jupyter Notebook)…

Three.js實戰項目02:vue3+three.js實現汽車展廳項目

文章目錄 實戰項目02項目預覽項目創建初始化項目模型加載與展廳燈光加載汽車模型設置燈光材質設置完整項目下載實戰項目02 項目預覽 完整項目效果: 項目創建 創建項目: pnpm create vue安裝包: pnpm add three@0.153.0 pnpm add gsap初始化項目 修改App.js代碼&#x…

年化19.3%策略集|ctpbee_api替換成openctp整合backtrader實盤方案(代碼+數據)

原創內容第782篇&#xff0c;專注量化投資、個人成長與財富自由。 昨天我們把backtraderctpbee的實盤整合代碼跑通了&#xff0c;年化19.3%&#xff0c;回撤僅8%的實盤策略&#xff0c;以及backtrader整合CTPBee做實盤&#xff08;附python代碼和數據&#xff09; 這兩周我們加…

Android Studio 正式版 10 周年回顧,承載 Androider 的崢嶸十年

Android Studio 1.0 宣發于 2014 年 12 月&#xff0c;而現在時間來到 2025 &#xff0c;不知不覺間 Android Studio 已經陪伴 Androider 走過十年歷程。 Android Studio 10 周年&#xff0c;也代表著了我的職業生涯也超十年&#xff0c;現在回想起來依然覺得「唏噓」&#xff…

OpenEuler學習筆記(十四):在OpenEuler上搭建.NET運行環境

一、在OpenEuler上搭建.NET運行環境 基于包管理器安裝 添加Microsoft軟件源&#xff1a;運行命令sudo rpm -Uvh https://packages.microsoft.com/config/centos/8/packages-microsoft-prod.rpm&#xff0c;將Microsoft軟件源添加到系統中&#xff0c;以便后續能夠從該源安裝.…

詳解python的修飾符

Python 中的修飾符&#xff08;Decorator&#xff09;是一種用于修改或擴展函數或類行為的工具。它們本質上是一個函數&#xff0c;接受另一個函數或類作為參數&#xff0c;并返回一個新的函數或類。修飾符通常用于在不修改原函數或類代碼的情況下&#xff0c;添加額外的功能。…

低代碼產品插件功能一覽

下圖是統計的目前市面上流行的低代碼、零代碼產品的插件功能。 產品名稱 產品類型 官方插件數量 支持拓展 官方插件功能 宜搭 零代碼 3 暫不支持 云打印、CAD看圖、打印表單詳情 微搭 低代碼 1 暫不支持 小程序 明道云 低代碼 2 支持 視圖、工作流節點 簡道…

Vscode編輯器下 Markdown無法顯示圖片

1.問題 在vscode 編輯器中無法預覽 markdon 文件中的圖片 2.解決方案 大部分出現這種情況是因為新版本的vscode會阻攔有風險的資源顯示&#xff0c;將安全等級調低即可。 方式一&#xff1a; 1.打開任意 MD 文件&#xff0c;ctrl&#xff0c;調出設置 2. 輸入 markdown.ch…

前端axios攔截器

1. 在main.js導入axios 2. 通過axios對象定義攔截器 import {createApp} from vue import App from ./App.vue import Antd from ant-design-vue; import ant-design-vue/dist/antd.css; import axios from "axios"; import router from ./router import store from …

php-phar打包避坑指南2025

有很多php腳本工具都是打包成phar形式&#xff0c;使用起來就很方便&#xff0c;那么如何自己做一個呢&#xff1f;也找了很多文檔&#xff0c;也遇到很多坑&#xff0c;這里就來總結一下 phar安裝 現在直接裝yum php-cli包就有phar文件&#xff0c;很方便 可通過phar help查看…

自動化運維的未來:從腳本到AIOps的演進

點擊進入IT管理資料庫 一、自動化運維的起源&#xff1a;腳本時代 &#xff08;一&#xff09;腳本在運維中的應用場景 在自動化運維的發展歷程中&#xff0c;腳本扮演著至關重要的角色&#xff0c;它作為最初的操作入口&#xff0c;廣泛應用于諸多日常運維工作場景里。 在系統…