平時都只會用 ConcurrentDictionary 自己刻 In-MemoryCache,玩了一下 MemoryCache 發現挺有趣的,筆記一下幾種做法
MemoryCache 在 ASP.NET Core是支援DI的,在 Startup 加上後就可以從建構式注入使用
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
services.AddControllers();
}
Get
- 直接取得 object
var val = (string)_cache.Get(key);
- 取得後轉為指定型別
var val = _cache.Get<string>(key);
- 嘗試取得
bool tryGetValue = _cache.TryGetValue(key, out var val);
- 取得並轉為指定型別,如果沒有就會用第二個參數的方法產生 value
var val = _cache.GetOrCreate<string>(key, entry => "new Value");
var val = await _cache.GetOrCreateAsync<string>(key, entry => "new Value");
Remove
就是刪除
_cache.Remove(key);
Set
- Add 並設定到期時間(Time、TimeSpan、IChangeToken)
_cache.Set(key, val);
_cache.Set(key, val, TimeSpan.FromSeconds(5));
_cache.Set(key, val, DateTimeOffset.Now);
_cache.Set(key, val, new CancellationChangeToken(new CancellationTokenSource(TimeSpan.FromSeconds(5)).Token));
- 指定優先度(在記憶體不足時,會依照優先度設定自動刪除資料)
_cache.Set(key, val, new MemoryCacheEntryOptions()
{
Priority = CacheItemPriority.NeverRemove,
});
- 透過兩種方式限制 MemoryCache 的資料上限
services.AddMemoryCache(options => options.SizeLimit = 1000);
var cache = new MemoryCache(new MemoryCacheOptions() { SizeLimit = 1000 });
_cache.Set(key, val, new MemoryCacheEntryOptions()
{
Size = 1
});
- 在指定的時間後自動刪除資料(不是立即、不是立即、不是立即,很重要所以說三次)
_cache.Set(key, val, new MemoryCacheEntryOptions()
{
AbsoluteExpiration = DateTimeOffset.UtcNow.AddSeconds(5),
});
_cache.Set(key, val, new MemoryCacheEntryOptions()
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(5)
});
- 檢查過期資料的刪除時間點會在執行 Set、Get、Remove時觸發,而每兩次的檢查是有時間間隔的,可以從 MemoryCacheOptions 裡面的參數 ExpirationScanFrequency 設定間隔時間
var memoryCache = new MemoryCache(new MemoryCacheOptions()
{
ExpirationScanFrequency = TimeSpan.FromMinutes(1),
});
services.AddMemoryCache(options =>
{
options.ExpirationScanFrequency = TimeSpan.FromMinutes(1)
})
- 在指定的時間內沒有被訪問就會刪除,被訪問就重新計時
_cache.Set(key, val, new MemoryCacheEntryOptions()
{
SlidingExpiration = TimeSpan.FromSeconds(5)
});
- 在資料刪除後,執行指定的方法
_cache.Set(key, value, new MemoryCacheEntryOptions()
{
SlidingExpiration = TimeSpan.FromSeconds(5),
PostEvictionCallbacks =
{
new PostEvictionCallbackRegistration()
{
EvictionCallback = (key, o, reason, state) =>
{
Console.WriteLine(key + "remove");
}
}
}
});
- 上述的所有過期方式都會在檢查程序執行時刪除資料,若需要過期即時刪除,可改用 IChangeToken 實現,過期時就會立即刪除資料並執行callback的方法
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
_cache.Set(key, value, new MemoryCacheEntryOptions()
{
ExpirationTokens = { new CancellationChangeToken(cts.Token) },
PostEvictionCallbacks =
{
new PostEvictionCallbackRegistration()
{
EvictionCallback = (key, o, reason, state) => Console.WriteLine(key + " remove")
}
}
});
Microsoft Docs ASP.NET Core 中的記憶體快取
MemoryCache 在 ASP.NET Core是支援DI的,在 Startup 加上後就可以從建構式注入使用
public void ConfigureServices(IServiceCollection services) { services.AddMemoryCache(); services.AddControllers(); }
Get
var val = (string)_cache.Get(key);
var val = _cache.Get<string>(key);
bool tryGetValue = _cache.TryGetValue(key, out var val);
var val = _cache.GetOrCreate<string>(key, entry => "new Value"); var val = await _cache.GetOrCreateAsync<string>(key, entry => "new Value");
Remove
就是刪除
_cache.Remove(key);
Set
_cache.Set(key, val); _cache.Set(key, val, TimeSpan.FromSeconds(5)); _cache.Set(key, val, DateTimeOffset.Now); _cache.Set(key, val, new CancellationChangeToken(new CancellationTokenSource(TimeSpan.FromSeconds(5)).Token));
_cache.Set(key, val, new MemoryCacheEntryOptions() { Priority = CacheItemPriority.NeverRemove, });
services.AddMemoryCache(options => options.SizeLimit = 1000);
var cache = new MemoryCache(new MemoryCacheOptions() { SizeLimit = 1000 });
Startup上設定的是Singleton的instance,在設定大小時要注意下,全專案使用的都是同一份實體
接著再使用時,都必須設定這筆筆資料的size,否則會在 Set 時發生exception
_cache.Set(key, val, new MemoryCacheEntryOptions() { Size = 1 });
_cache.Set(key, val, new MemoryCacheEntryOptions() { AbsoluteExpiration = DateTimeOffset.UtcNow.AddSeconds(5), }); _cache.Set(key, val, new MemoryCacheEntryOptions() { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(5) });
// new var memoryCache = new MemoryCache(new MemoryCacheOptions() { ExpirationScanFrequency = TimeSpan.FromMinutes(1), }); // startup services.AddMemoryCache(options => { options.ExpirationScanFrequency = TimeSpan.FromMinutes(1) })
_cache.Set(key, val, new MemoryCacheEntryOptions() { SlidingExpiration = TimeSpan.FromSeconds(5) });
_cache.Set(key, value, new MemoryCacheEntryOptions() { SlidingExpiration = TimeSpan.FromSeconds(5), PostEvictionCallbacks = { new PostEvictionCallbackRegistration() { EvictionCallback = (key, o, reason, state) => { Console.WriteLine(key + "remove"); } } } });
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)); _cache.Set(key, value, new MemoryCacheEntryOptions() { ExpirationTokens = { new CancellationChangeToken(cts.Token) }, PostEvictionCallbacks = { new PostEvictionCallbackRegistration() { EvictionCallback = (key, o, reason, state) => Console.WriteLine(key + " remove") } } });
Microsoft Docs ASP.NET Core 中的記憶體快取