簡介
快取是指可以進行高速資料交換的記憶體,它先於記憶體與 CPU 交換資料,因此速率很快。由於 CPU 從記憶體中讀取資料的速度比從磁碟讀取快幾個數量級,並且存在記憶體中,減小了資料庫存取的壓力,所以快取幾乎每個專案都會用到。一般常用的有 MemoryCache、Redis,今天就給大家帶來 MemoryCache 的使用介紹!
類別
記憶體快取過期時間有 4 種
- 永不過期
- 絕對過期時間
- 相對現在的過期時間
- 滑動過期時間
當然也可以透過這三種過期時間衍生出 滑動視窗+絕對過期時間等等
官方網站
我們也可以查看官方文件 來詳細了解 MemoryCache,這裡就不做過多解讀了
- MemoryCache 地址: https://docs.microsoft.com/zh-cn/dotnet/api/system.runtime.caching.memorycache?redirectedfrom=MSDN&view=dotnet-plat-ext-6.0
使用
回到剛才的問題 我們來介紹怎麼設定過期時間!
永不過期
就是在我程式發佈後只要我們不去清理該快取,該快取會一直有效!
/// <summary>
/// 永不過期時間
/// </summary>
static void NeverExpire()
{
_cache.Set("NeverExpire", "1");
}
絕對過期時間
用的是絕對時間點 可以理解成「截止日期」
static void AbsoluteExpiration()
{
DateTime time = new DateTime(2022, 04, 01, 23, 59, 59);
_cache.Set("AbsoluteExpiration", "20220401235959", time);
}
相對現在的過期時間
相對現在的過期時間,就是說我們設定快取後的一分鐘內有效,可以參考我們常見的 簡訊登入,後端隨機產生一個驗證碼並存入 redis,並且設定該 key 的過期時間,然後就是校驗了,發送手機號碼和驗證碼到後台,從 redis 中取出對應的驗證碼就行校驗,如果正確就把該驗證碼刪掉,防止可以驗證多次
static void ExpirationTimeRelativeToThePresent()
{
_cache.Set("AbsoluteExpiration", "123456", new TimeSpan(0, 0, 60));
}
滑動過期時間
快取在設定的時間內沒有被使用,則失效,使用後快取的過期時間重新被刷新
static void SlidingExpirationTime()
{
_cache.Set("SlidingExpirationTime", "3", new MemoryCacheEntryOptions()
{
SlidingExpiration = new TimeSpan(0, 0, 2),
AbsoluteExpiration = DateTimeOffset.Now.AddMilliseconds(1000)
});
}
我們來看看官網的定義如圖所示 !

然後再來解釋第二個參數 MemoryCacheEntryOptions,設定快取項的絕對到期日期: 是當前快取設定後的 1000 秒(或許應該是分鐘?開玩笑,正常場景一般 5 分鐘、10 分鐘之類的,看實際業務設計)。像我們經常玩的英雄聯盟手遊,我們一天不登入,快取的 token 失效,就要重新登入取得 token,我們每天都在玩觸發了滑動過期時間,就不需要每次啟動 app 時登入帳號,但是 玩了一段時間後,發現我們還是需要重新登入我們的帳號這個就是滑動過期時間中絕對過期時間!
取得快取值
ConcurrentDictionary<object, CacheEntry> _entries:一個多執行緒安全的字典型別,其實快取的本質就是這個字典,將所有快取都放入這個字典中,然後透過字典的 key(字典的 key 其實和快取實體 CacheEntry 的 key 值一樣)取得 CacheEntry 實體(CacheEntry 實體包含 key 和 value,也就是我們程式碼中設定的 key 和 value)。
static void GetCache()
{
//方式一
_cache.Get("NeverExpire").ToString();
//方式二
string value = "";
if (!_cache.TryGetValue("NeverExpire", out value))
{
throw new Exception("不存在該快取或者已過期");
}
}
清除快取值
static void GetCache()
{
string value = "";
if (_cache.TryGetValue("NeverExpire", out value))
{
_cache.Remove("NeverExpire");
}
}
可能大家發現了,我們在移除時根本就不需要 value 值,再去使用暫存變數,是不是有點痛苦!
其實 C# 也考慮到了這個問題,那麼 C# 從 7.0 開始支援捨棄,捨棄不只是書寫和語義上的提升,它還可以減少記憶體配置。
將上面程式碼進行一個簡化
static void GetCache()
{
if (_cache.TryGetValue("NeverExpire", out _))
{
_cache.Remove("NeverExpire");
}
}
完整程式碼
class Program
{
public static IMemoryCache _cache = new MemoryCache(new MemoryCacheOptions());
static void Main(string[] args)
{
_cache.Get("NeverExpire").ToString();
string value = "";
if (!_cache.TryGetValue("NeverExpire", out value))
{
throw new Exception("不存在該快取或者已過期");
}
if (_cache.TryGetValue("NeverExpire", out value))
{
_cache.Remove("NeverExpire");
}
if (_cache.TryGetValue("NeverExpire", out _))
{
_cache.Remove("NeverExpire");
}
}
/// <summary>
/// 永不過期時間
/// </summary>
static void NeverExpire()
{
_cache.Set("NeverExpire", "1");
}
/// <summary>
/// 絕對過期時間
/// </summary>
static void AbsoluteExpiration()
{
DateTime time = new DateTime(2022, 04, 01, 23, 59, 59);
_cache.Set("AbsoluteExpiration", "20220401235959", time);
}
/// <summary>
/// 相對現在的過期時間
/// </summary>
///
static void ExpirationTimeRelativeToThePresent()
{
_cache.Set("AbsoluteExpiration", "123456", new TimeSpan(0, 0, 60));
}
/// <summary>
/// 滑動過期時間
/// </summary>
static void SlidingExpirationTime()
{
_cache.Set("key3", "3", new MemoryCacheEntryOptions()
{
SlidingExpiration = new TimeSpan(0, 0, 2),
AbsoluteExpiration = DateTimeOffset.Now.AddMilliseconds(1000)
});
}
}
最後大家如果喜歡我的文章,還麻煩給個關注並點個讚,希望 net 生態圈越來越好!