第十一節:Asp.Net Core 之內容緩存(IMemoryCache)


1. 整體說明

  ASP.NET Core 支持多種不同的緩存,最簡單的緩存基於 IMemoryCache,它表示存儲在 Web 服務器內存中的緩存,內存緩存可以存儲任何對象,存儲形式鍵值對,需要 .net standard 2.0 或者 .Net framework 4.5 或更高版本。

本節主要介紹:依賴注入的方式使用、全局封裝單例配置、緩存幾個方法和性質。

2. 常規使用步驟

  (1) 安裝程序集:System.Runtime.Caching 和 Microsoft.Extensions.Caching.Memory,如果是是Core MVC程序自帶的Microsoft.AspNetCore.App包里已經涵蓋了

 Microsoft.Extensions.Caching.Memory,無需重復下載。

  (2) 在ConfigureService中注冊內存緩存服務: services.AddMemoryCache();

 1 using Microsoft.AspNetCore.Builder;
 2 using Microsoft.AspNetCore.Mvc;
 3 using Microsoft.Extensions.DependencyInjection;
 4 
 5 public class Startup
 6 {
 7     public void ConfigureServices(IServiceCollection services)
 8     {
 9         services.AddMemoryCache();
10         services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
11     }
12 
13 
14 }

  (3) 通過屬性注入的方式在控制器中注入IMemoryCache對象。

1  public class FirstController : Controller
2     {
3         private IMemoryCache _cache1;
4         public FirstController(IMemoryCache memoryCache)
5         {
6             _cache1 = memoryCache;
7         }
8     }

  (4) 通過get、set方法實現常規緩存的讀取和寫入,如下 案例①。

1    {
2        string nowTime1 = _cache1.Get<string>("t1");
3        if (String.IsNullOrEmpty(nowTime1))
4        {
5            nowTime1 = DateTime.Now.ToString();
6            _cache1.Set("t1", nowTime1);
7        }
8        ViewBag.t1 = nowTime1;
9   }

3. 全局封裝單例的形式

 (1)新建一個memoryCacheHelp類,聲明一個IMemoryCache屬性,並在構造函數中進行初始化,實例化的時候可以通過SizeLimit設置全局緩存的最大Size。

特別注意:如果在這全局設置了最大Size,凡是使用的時候都需要通過SetSize進行設置,且必須 "小於等於" 這個最大Size,不設置會報錯,設置的比這個大,緩存會失效。

 1  public class memoryCacheHelp
 2     {
 3         public IMemoryCache _cache { get; set; }
 4         public memoryCacheHelp()
 5         {
 6             _cache = new MemoryCache(new MemoryCacheOptions {
 7                 SizeLimit = 1024
 8             });
 9         }
10     }

 (2)在ConfigureService將該類注冊成單例的:services.AddSingleton<memoryCacheHelp>();

1 public void ConfigureServices(IServiceCollection services)
2 {
3     services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
4     services.AddSingleton<memoryCacheHelp>();
5 }

 (3)通過屬性注入的方式在控制器中注入IMemoryCache對象

1  public class FirstController : Controller
2     {
3         private IMemoryCache _cache2;
4         public FirstController(memoryCacheHelp cache)
5         {
6             _cache2 = cache._cache;
7         }
8    }

 (4)通過TryGetValue、set方法實現緩存的讀取和寫入,如下 案例②

注: 這里通過依賴注入的形式將memoryCacheHelp注冊成單例類,和直接聲明成單例類道理是一樣的。

 1  {
 2      string nowTime2 = null;
 3      if (!_cache2.TryGetValue("t2", out nowTime2))
 4      {
 5          nowTime2 = DateTime.Now.ToString();
 6          //設置緩存的大小
 7          var cacheOptions = new MemoryCacheEntryOptions()
 8                                       .SetSize(100)
 9                                       .SetAbsoluteExpiration(TimeSpan.FromSeconds(5));
10           _cache2.Set("t2", nowTime2, cacheOptions);
11      }
12     ViewBag.t2 = nowTime2;
13 }

4. 方法、屬性詳解

(1) 獲取數據

 A. Get<T>方法:根據鍵名獲取指定類型的值,將返回值做判斷,比如根據是否為null,來判斷有沒有值。 如下面的案例①

 B. TryGetValue(object key, out TItem value);根據key獲取指定類型值,通過out參數進行輸出,如果拿到值返回true,如果拿不到值返回false,相比Get<T>方法 如下面案例②

 C. GetOrCreate(object key, Func<ICacheEntry, TItem> factory);適用場景:key有值則獲取該值,沒有值為它賦值(通過return直接返回)。如下面案例③

(2) 寫入數據

 A. Set方法:有很多重載,重點看下面兩個

  ①:Set<TItem>(object key, TItem value); 最簡單的鍵值模式

  ②:Set<TItem>(object key, TItem value, MemoryCacheEntryOptions options); 通過MemoryCacheEntryOptions設置緩存的性質,詳見下面

 B. GetOrCreate方法:當key對應的值為空則通過return返回來賦值,如下面的:案例③,通過第二個參數在Func委托中設置ICacheEntry屬性進行緩存性質的設置。 詳見下面(5)

 1 {
 2     string nowTime3 = _cache1.GetOrCreate("t3", entry =>
 3     {
 4       entry.Size = 100;
 5       //滑動過期時間設置為2秒
 6       entry.SlidingExpiration = TimeSpan.FromSeconds(2);
 7       //絕對和滑動只能設置一個
 8       //entry.AbsoluteExpiration = new DateTimeOffset(DateTime.Parse("2019-07-16 16:33:10"));
 9       entry.Priority = CacheItemPriority.High;
10       entry.RegisterPostEvictionCallback(MyCallback, this);
11       return DateTime.Now.ToString();
12     });
13     ViewBag.t3 = nowTime3;
14 }

(3) 移除數據

 A. Remove方法:Remove(object key); 移除緩存

(4) MemoryCacheEntryOptions類

 用來設置緩存的一些性質,可以通過方法或者屬性進行設置,在Set方法中使用。

 A. 緩存大小(SetSize方法和Size屬性):如果全局單例設置緩存的最大值,則每個使用的地方都需要顯式的設置,必須小於等於最大值,如果不設置報錯,如果設置比最大值還大,緩存不生效。

 B. 絕對過期時間(SetAbsoluteExpiration方法和AbsoluteExpiration屬性):絕對指的是到了這個時間就過期,不管這期間有沒有人訪問。

 絕對過期有兩種設置方式:① 通過TimeSpan設置距離當前時間的間隔 ② 通過DateTimeOffset設置具體到某一時刻。 詳見下面案例④

 C. 滑動過期時間(SetSlidingExpiration方法和SlidingExpiration屬性):相對是指以最后一次訪問來計算,每訪問一次重新計算過期時間。

 D. 緩存級別(SetPriority方法和Priority屬性):有Low、Normal、High、NeverRemove。

 E. 緩存移除時回調(RegisterPostEvictionCallback方法和屬性):緩存過期或者手動移除時調用,該方法有四個參數,調用的時候自動賦值,分別是: 鍵、值、消失原因、狀態。

 1   {
 2                 string nowTime4 = null;
 3                 if (!_cache2.TryGetValue("t4", out nowTime4))
 4                 {
 5                     nowTime4 = DateTime.Now.ToString();
 6                     MemoryCacheEntryOptions cacheOptions = null;
 7 
 8                     //設置緩存方式一:(通過方法)
 9                     {
10                         cacheOptions = new MemoryCacheEntryOptions()
11                          .SetSize(100)
12                          //.SetSlidingExpiration(TimeSpan.FromSeconds(5))
13                          //絕對和滑動只能設置一個
14                          .SetAbsoluteExpiration(TimeSpan.FromSeconds(60))
15                          .SetPriority(CacheItemPriority.Normal)
16                          .RegisterPostEvictionCallback(MyCallback, this);
17 
18                     }
19 
20                     //設置緩存方式二:(通過屬性)
21                     //{
22                     //    cacheOptions = new MemoryCacheEntryOptions();
23                     //    cacheOptions.Size = 100;
24                     //    //cacheOptions.SlidingExpiration = TimeSpan.FromSeconds(5);
25                     //    //絕對和滑動只能設置一個
26                     //    cacheOptions.AbsoluteExpiration = new DateTimeOffset(DateTime.Parse("2019-07-16 16:33:10"));
27                     //    cacheOptions.Priority = CacheItemPriority.High;
28                     //    cacheOptions.RegisterPostEvictionCallback(MyCallback, this);
29                     //}
30                     _cache2.Set("t4", nowTime4, cacheOptions);
31 
32                 }
33                 ViewBag.t4 = nowTime4;
34             } 
35 
36         /// <summary>
37         /// 失敗回調
38         /// </summary>
39         /// <param name="key"></param>
40         /// <param name="value"></param>
41         /// <param name="reason">緩存消失的原因,比如移除、過期,是個枚舉類型</param>
42         /// <param name="state"></param>
43         private static void MyCallback(object key, object value, EvictionReason reason, object state)
44         {
45             var message = $"Cache entry was removed : key={key},value={value}, reason={reason}, state={state}";
46         }

(5) ICacheEntry

 通過屬性的形式設置:緩存大小、絕對過期、滑動過期、緩存級別、緩存移除回調,詳見案例③

5.即時創建調用 VS 全局單例調用

 首先需要明白,不管即時創建調用還是全局單例調用,MemoryCache都是存在服務器內存中的,這一點是毋庸置疑的。

 (1) 即時創建調用:多個客戶端每次訪問該方法的時候,都需要現創建一個IMemoryCache對象,然后進行讀取或寫入。

 (2) 全局單例調用:只要有一個客戶端訪問該方法,創建IMemoryCache對象,后續不管誰訪問,都是使用的同一個對象進行讀取或寫入。

 

很傻瓜的一個問題:內存緩存是以鍵值對的形式進行存儲,同一個鍵如果多次設置會覆蓋,但是不同鍵之間設置過期時間是互相不影響的。

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鵬飛)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 聲     明1 : 本人才疏學淺,用郭德綱的話說“我是一個小學生”,如有錯誤,歡迎討論,請勿謾罵^_^。
  • 聲     明2 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM