Asp.Net Core 輕鬆學-在.Net Core 使用緩存和配置依賴策略

来源:https://www.cnblogs.com/viter/archive/2018/12/20/10146312.html
-Advertisement-
Play Games

幾乎在所有的應用程式中,緩存都是一個永恆的話題,恰當的使用緩存可以有效提高應用程式的性能;在某些業務場景下,使用緩存依賴會有很好的體驗;在 Asp.Net Core 中,支持了多種緩存組件,下麵要介紹的內容就是基於 IMemoryCache 的緩存依賴。 ...


前言

    幾乎在所有的應用程式中,緩存都是一個永恆的話題,恰當的使用緩存可以有效提高應用程式的性能;在某些業務場景下,使用緩存依賴會有很好的體驗;在 Asp.Net Core 中,支持了多種緩存組件,這其中最基礎也最易用的當屬 IMemoryCache,該介面表示其存儲依賴於托管程式伺服器的記憶體,下麵要介紹的內容就是基於 IMemoryCache 的緩存依賴。

1. IMemoryCache 的實現

Asp.Net Core 內部實現了一個繼承自 IMemoryCache 介面的類 MemoryCache
這幾乎已成慣例,一旦某個介面被列入 SDK 中,其必然包含了一個預設實現

1.1 使用 IMemoryCache

在 Asp.Net Core 中要使用 IMemoryCache 非常簡單,只需要在 Startup 的 ConfigureServices 方法加入一句代碼 services.AddMemoryCache() 即可

    public void ConfigureServices(IServiceCollection services)
        {
            services.AddMemoryCache();
            ...
        }
1.2 在控制器中使用 IMemoryCache
    [Route("api/[controller]")]
    [ApiController]
    public class HomeController : ControllerBase
    {
        private IMemoryCache cache;
        public HomeController(IMemoryCache cache)
        {
            this.cache = cache;
        }

        [HttpGet]
        public ActionResult<IEnumerable<string>> Get()
        {
            cache.Set("userId", "0001");
            return new string[] { "value1", "value2" };
        }

        [HttpGet("{id}")]
        public ActionResult<string> Get(int id)
        {
            return cache.Get<string>("userId");
        }
    }

上面的代碼表示在 HomeController 控制器的構造方法中使用註入的方式獲得了一個 IMemoryCache 對象,在 Get() 方法中增加了一條緩存記錄 "userId=0001",然後在 Get(int id) 介面中提取該緩存記錄
運行程式,分別調用 Get() 和 Get(int id) 介面,獲得下麵的輸出信息

  • 調用 Get() 介面

  • 調用 Get(int id) 介面

這看起來非常容易,幾乎不用什麼思考,你就學會了在 Asp.Net Core 中使用緩存,容易使用,這非常重要,這也是一門語言廣泛推廣的根本態度

2. 應用緩存策略

IMemoryCache 還包含了一個帶參數的構造方法,讓我們可以對緩存進行靈活的配置,該配置由類 MemoryCacheOptions 決定

2.1 MemoryCacheOptions 配置,MemoryCacheOptions的配置項目不多,看下麵的代碼
    public class MemoryCacheOptions : IOptions<MemoryCacheOptions>
    {
        public MemoryCacheOptions();

        public ISystemClock Clock { get; set; }

        [Obsolete("This is obsolete and will be removed in a future version.")]
        public bool CompactOnMemoryPressure { get; set; }

        public TimeSpan ExpirationScanFrequency { get; set; }

        public long? SizeLimit { get; set; }

        public double CompactionPercentage { get; set; }
    }
  • ISystemClock:系統時鐘,預設值為 null,官方文檔對此屬性沒有說明,我也不知道是乾什麼用的,哪位大神求告知其作用和原理
  • ExpirationScanFrequency:對過期緩存的掃描間隔時間
  • SizeLimit:緩存區可存儲記錄條目數量
  • CompactionPercentage:在緩存過期策略生效的時候,對緩存進行壓縮的百分比

上面的這個配置非常簡單,在系統中應用類似下麵的代碼這樣

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddMemoryCache(options =>
            {
                options.CompactionPercentage = 0.02d;
                options.ExpirationScanFrequency = TimeSpan.FromMinutes(5);
                options.SizeLimit = 1024;
            });
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

上面的緩存策略設置為緩存壓縮比為 2%,每 5 分鐘進行一次過期緩存的掃描,最大緩存空間大小限製為 1024
使用方法不變

2.1 單個鍵緩存策略

由於緩存的所有鍵其緩存過期優先順序都是預設的 Normal,可能我們需要在某些業務場景下,讓某些緩存值設置一個較高的優先順序,比如設置永遠都不過期,這樣即使緩存達到最大限制條數以後也不會對其進行清理

  • 緩存優先順序,該值為一個枚舉類型,分別是 低、普通、高、永不移除,開發者可以根據不同的業務場景靈活設置
    public enum CacheItemPriority
    {
        Low = 0,
        Normal = 1,
        High = 2,
        NeverRemove = 3
    }
  • 設置策略,下麵就使用 MemoryCacheEntryOptions 對單個鍵值進行應用策略
        [HttpGet]
        public ActionResult<IEnumerable<string>> Get()
        {
            MemoryCacheEntryOptions entry = new MemoryCacheEntryOptions
            {
                Priority = CacheItemPriority.NeverRemove
            };
            cache.Set("userId", "0001", entry);

            return new string[] { "value1", "value2" };
        }

上面的代碼表示,我們對緩存鍵 "userId" 應用了一個 “永不移除” 的策略,當然,還可以對單個值做非常多的策略,比如現在 "userId" 的值大小等等,有興趣的同學可以深入瞭解 MemoryCacheEntryOptions 類

3. 使用緩存依賴策略

緩存依賴的意思是表示,一個或者多個緩存依賴於某個緩存,當某個緩存過期的時候,對其有依賴條件的其它緩存也會過期,在某些應用場景下,緩存依賴非常有用

3.1 創建 TokenController 並登錄後註冊依賴、獲取緩存、移除緩存介面

以下示例使用一個模擬用戶登錄/登出的業務場景

    [Route("api/[controller]")]
    [ApiController]
    public class TokenController : ControllerBase
    {
        private IMemoryCache cache;
        public TokenController(IMemoryCache cache)
        {
            this.cache = cache;
        }

        // 創建註冊依賴
        [HttpGet("login")]
        public ActionResult<string> Login()
        {
            var cts = new CancellationTokenSource();
            cache.Set(CacheKeys.DependentCTS, cts);
            using (var entry = cache.CreateEntry(CacheKeys.UserSession))
            {
                entry.Value = "_x0123456789";
                entry.RegisterPostEvictionCallback(DependentEvictionCallback, this);
                cache.Set(CacheKeys.UserShareData, "這裡是共用的數據", new CancellationChangeToken(cts.Token));
                cache.Set(CacheKeys.UserCart, "這裡是購物車", new CancellationChangeToken(cts.Token));
            }
            return "設置依賴完成";
        }

        // 獲取緩存
        [HttpPost("getkeys")]
        public IActionResult GetKeys()
        {
            var userInfo = new
            {
                UserSession = cache.Get<string>(CacheKeys.UserSession),
                UserShareData = cache.Get<string>(CacheKeys.UserShareData),
                UserCart = cache.Get<string>(CacheKeys.UserCart)
            };

            return new JsonResult(userInfo);
        }

        // 移除緩存
        [HttpPost("logout")]
        public ActionResult<string> LogOut()
        {
            cache.Get<CancellationTokenSource>(CacheKeys.DependentCTS).Cancel();

             var userInfo = new
            {
                UserSession = cache.Get<string>(CacheKeys.UserSession),
                UserShareData = cache.Get<string>(CacheKeys.UserShareData),
                UserCart = cache.Get<string>(CacheKeys.UserCart)
            };

            return new JsonResult(userInfo);
        }

        // 過期通知
        private static void DependentEvictionCallback(object key, object value, EvictionReason reason, object state)
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("Key:{0} 已過期,依賴於該 Key 的所有緩存都將過期而處於不可用狀態", key);
            Console.ForegroundColor = ConsoleColor.Gray;
        }
    }

上面的代碼使用 CancellationTokenSource 用作事件通知源,當移除 CacheKeys.DependentCTS 並觸發 CancellationTokenSource.Cancel() 方法後,將非同步觸發 DependentEvictionCallback(object key, object value, EvictionReason reason, object state)委托;此時,托管程式收到一個通知,用戶已登出,已移除用戶相關緩存,任何移除介面嘗試再次讀取 CacheKeys 項,此時,返回值為空

3.2 運行程式,分別調用 login/getkeys/logout 介面,分別得到以下輸出結果
  • login 登錄後註冊依賴

  • getkeys 獲取緩存

  • logout 移除緩存,嘗試再次讀取 CacheKeys 項,此時,返回值為空

  • 控制台輸出移除通知(黃色字體部分信息)

可以看到,在用戶登錄登出這個業務場景下,使用緩存依賴項對其相關緩存進行管理,還是非常方便的,當用戶退出登錄後,即清空其所有相關緩存

結束語

  • 本文通過實例介紹了 IMemoryCache 的簡單使用方法
  • 針對單個緩存鍵,也可以對其進行應用策略
  • 通過使用緩存依賴策略,可以在某些業務場景中有非常好的應用體驗
  • 註意:當使用全局緩存策略 SizeLimit 時,每個鍵都需要設置一個大小
  • IMemoryCache 依賴於托管伺服器等記憶體,一旦重啟,緩存數據將立即被釋放

示例代碼下載

https://files.cnblogs.com/files/viter/Ron.MemoryCacheDemo.zip


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 本篇主要講述是Java中JDK1.8的一些新語法特性使用,主要是Lambda、Stream和LocalDate日期的一些使用講解。 Lambda Lambda介紹 Lambda 表達式(lambda expression)是一個匿名函數,Lambda表達式基於數學中的λ演算得名,直接對應於其中 ...
  • 1.變數名 命名規則: 在名稱中只能使用字母字元、數字和下劃線; 名稱的第一個字元不能是數字; 不能將C++關鍵詞用作名稱。 常用的首碼:n-整數,str/sz-字元串,b-布爾值,p-指針,c-單個字元,m-類成員值 2.整形 short 至少16位; int至少與short一樣長; long至少 ...
  • 1.文件讀模式 r f = open("helloworld", 'r', encoding="utf-8") 文件句柄: "helloworld" 表示讀的文件的文件名, 'r' 代表讀模式, encoding="utf-8" 表示字元編碼形式為utf-8。 有open就有close,不管是讀文件 ...
  • Python基礎知識(37):訪問資料庫(Ⅱ) 因臨近考試,本人即將進入複習階段,從明天12月19號至2019年的1月二十多號暫停更新 二、MySQL MySQL是Web世界中使用最廣泛的資料庫伺服器。SQLite的特點是輕量級、可嵌入,但不能承受高併發訪問,適合桌面和移動應用。而MySQL是為服務 ...
  • 在我們的世界中事物和事物之間總會有一些聯繫. 在面向對象中. 類和類之間也可以產生相關的關係 1. 依賴關係 執行某個動作的時候. 需要xxx來幫助你完成這個操作. 此時的關係是最輕的. 隨時可以更換另外一個東西來完成此操作 2. 關聯關係 在對象裡面埋對象 1. 一對一關係 2. 一對多關係 類中 ...
  • 本文說明瞭如何定製化JHipster-Registry,增加消息匯流排功能。 ...
  • 前言: 最近有人在Twisted郵件列表中提出諸如”為任務緊急的人提供一份Twisted介紹”的的需求。值得提前透露的是,這個序列並不會如他們所願.尤其是介紹Twisted框架和基於Python 的非同步編程而言,可能短時間無法講清楚。因此,如果你時間緊急,這恐怕不是你想找的資料。 我相信如果對非同步編 ...
  • 一、前言 瞭解過flask的python開發者想必都知道flask中核心機制莫過於上下文管理,當然學習flask如果不瞭解其中的處理流程,可能在很多問題上不能得到解決,當然我在寫本篇文章之前也看到了很多博文有關於對flask上下文管理的剖析都非常到位,當然為了學習flask我也把對flask上下文理 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...