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 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。