簡介
緩存是指可以進行高速數據交換的存儲器,它先於內存與 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 生態圈越來越好!