說到內存緩存MemoryCache不由的讓我想起.Net Framework中的MemoryCache,它位於 System.Runtime.Caching 程序集中。
接下來我們來看看.net core中的MemoryCache又有什么與眾不同的地方吧。
一、基本實現
1、打開NuGet包管理器搜索並安裝 Microsoft.Extensions.Caching.Memory 包,或者從程序包管理控制台執行 Install-Package Microsoft.Extensions.Caching.Memory 命令
2、接下來看實現代碼
static void Main(string[] args) { MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()); memoryCache.Set("name","tom"); var value = memoryCache.Get("name"); Console.WriteLine(value); Console.ReadKey(); }
結果如下:

二、緩存容量控制:SizeLimit
1、當你用SizeLimit屬性設置了這個緩存大小之后,你就必須為你緩存中的每一項設置大小,否則則報錯。當然,當你的大小達到你設置的SizeLimit時,你再設置緩存,它會自動清理一些緩存再緩存你設置的值
2、代碼如下:
static void Main(string[] args) { MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions() { SizeLimit = 100 }); for (int i = 0; i < 1000; i++) { memoryCache.Set<int>(i.ToString(), i, new MemoryCacheEntryOptions() { Size = 1 }); } Console.WriteLine(memoryCache.Count); Console.ReadKey(); }
結果如下:

實際結果不是1000,而是100
我們來看看它設置值的過程是什么樣的:

由於設置的大小為100,達到100時再設置緩存項就會自動清理掉一部分
三、緩期的過期問題
1、被動過期
代碼如下:
static void Main(string[] args) { MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()); memoryCache.Set("name", "jack", new MemoryCacheEntryOptions() { AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(5)//設置為5秒后過期 }); while (true) { System.Threading.Thread.Sleep(1000); string value; if (!memoryCache.TryGetValue("name", out value)) { value = "已過期"; } Console.WriteLine(value); } //Console.ReadKey(); }
結果如下:

2、主動過期
static void Main(string[] args) { MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()); CancellationTokenSource tokenSource = new CancellationTokenSource(); var cacheOptins = new MemoryCacheEntryOptions() { AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10)//設置為10秒后過期 }; cacheOptins.AddExpirationToken(new CancellationChangeToken(tokenSource.Token)); memoryCache.Set("name", "jack", cacheOptins); tokenSource.CancelAfter(2000);//主動設置為2秒過期 while (true) { Thread.Sleep(1000); string value; if (!memoryCache.TryGetValue("name", out value)) { value = "已過期"; } Console.WriteLine(value); } //Console.ReadKey(); }
結果如下:

3、過期后回調:
static void Main(string[] args) { MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()); CancellationTokenSource tokenSource = new CancellationTokenSource(); var cacheOptins = new MemoryCacheEntryOptions() { AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10)//設置為10秒后過期 }; cacheOptins.AddExpirationToken(new CancellationChangeToken(tokenSource.Token)); cacheOptins.RegisterPostEvictionCallback((key, value, reason, state) => { Console.WriteLine(reason); }); memoryCache.Set("name", "jack", cacheOptins); tokenSource.CancelAfter(2000);//主動設置為2秒過期 while (true) { Thread.Sleep(1000); string value; if (!memoryCache.TryGetValue("name", out value)) { value = "已過期"; } Console.WriteLine(value); } //Console.ReadKey(); }
結果如下:

四、其它的一些設置
1、原子性操作
memoryCache.GetOrCreate("name", entry => "lucy");
2、優先級設置,這個設置是為了配合壓縮緩存的
以下是系統定義的優先級的枚舉
public enum CacheItemPriority { Low = 0, Normal = 1, High = 2, NeverRemove = 3 }
接下來設定優先級
var cacheOptins = new MemoryCacheEntryOptions() { Priority= CacheItemPriority.Low, AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10)//設置為10秒后過期 };
3、緩存壓縮
static void Main(string[] args) { MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions() { SizeLimit = 100 }); for (int i = 0; i < 100; i++) { CacheItemPriority priority = CacheItemPriority.Low; if (25 < i && i < 50) priority = CacheItemPriority.Normal; else if (50 < i && i < 75) priority = CacheItemPriority.High; else priority = CacheItemPriority.NeverRemove; memoryCache.Set(i.ToString(), i.ToString(), new MemoryCacheEntryOptions() { Size = 1, Priority = priority, AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10)//設置為10秒后過期 }); } memoryCache.Compact(0.2);//壓縮20% Console.WriteLine(memoryCache.Count); for (int i = 0; i < 100; i++) { Console.WriteLine(memoryCache.Get(i.ToString())); } Console.ReadKey(); }
結果如下:
壓縮后的緩存項數:

被壓縮的緩存項:

根據結果可知道,優先級為 CacheItemPriority.Normal 的數據被壓縮掉了,由此可見,優先級為 CacheItemPriority.Low 的並沒有參加壓縮。
壓縮的優先級順序是 CacheItemPriority.Normal>CacheItemPriority.High>CacheItemPriority.NeverRemove
