[ASP.NET Core]搞懂記憶體快取 Memory Cache

前言

當需要重複抓取資料時,而資料量又少且不常變動,造成效能降低,此時可以使用Memory Cache,將資料暫存記憶體中改善Web Application效能

如何設計快取

使用快取,需要注意的是資料一致性的問題,要如何確保在資料一致前提下怎麼設計快取能夠使用最長的快取 。
  • Set - 快取存在時會直接覆寫

  • Cache[key]=value - 快取已存在時一樣會直接覆寫,但無法設定清除快取機制

  • Add - 快取已存在時不會覆寫,會回傳false結果告知失敗

清除快取的機制 (CacheItemPolicy)

清除快取資料能夠分為兩種:
  • 時間到期(Expiration) :

    • 絕對時間 (AbsoluteExpiration):DateTimeOffset 時間超過設定的時間後,就會清除快取。

    • 時間空隔(SlidingExpiration) : TimeSpan 快取資料多久的時間沒有被使用,就會清除快取。

  • 資料變動 (ChangeMonitor)

    • 實體檔案變動 (HostFileChangeMonitor):檔案內容更動時就會清除快取。

    • 資料庫變動(SqlChangeMonitor):當資料庫指令結果有不同就會清除快取。

使用的擴充方法為:
 Set(IMemoryCache, Object, TItem, MemoryCacheEntryOptions)
 
 TryGetValue(Object, Object)

實作並搭配DI使用

在Startup裡的ConfigureServices裡加上程式碼,設定完即DI注入使用。
public void ConfigureServices(IServiceCollection services)
{
    services.AddMemoryCache();  // 這一行就可以了
    services.AddMvc();
}
使用IMemoryCache為注入的對象
public class AccountController : Controller
{
    private readonly IMemoryCache memoryCache;

    public AccountController(IMemoryCache _memoryCache)
    {
        this.memoryCache = _memoryCache;
    }
}

範例1 - 絕對時間測試(AbsoluteExpiration)

public IEnumerable<TimetableEnum> GetTimetableEnums()
{
IEnumerable<TimetableEnum> timetableEnumDtos;
// 檢查cache是否有時刻表,TryGetValue回傳的是bool,
// 在快取查不到資料時回傳false,所以這裡要使用反向進入if執行cache
if (!_cache.TryGetValue("TimetableEnum", out timetableEnumDtos))
{
  //拿取火車時刻表資料
  crmLogEnumDtos = _InfoDbRepo.GetTimetableEnum(); 
  //將資料儲存到快取中,並且設定一天的時間到了會清除快取的資料
  _cache.Set(
    "TimetableEnum", 
    timetableEnumDtos,
    DateTimeOffset.Now.AddDays(1)
    ); 
}
return timetableEnumDtos;
}
範例2 - 時間到了會清除快取時間空隔測試(SlidingExpiration)
public IEnumerable<TimetableEnum> GetTimetableEnums()
{
IEnumerable<TimetableEnum> timetableEnumDtos;
if (!_cache.TryGetValue("TimetableEnum", out timetableEnumDtos))
{
  crmLogEnumDtos = _InfoDbRepo.GetTimetableEnum(); 
  //將資料儲存到快取中,並且設定15分鐘內如果沒有使用到這筆快取資料則會清除快取的資料
  _cache.Set("TimetableEnum", timetableEnumDtos, TimeSpan.FromMinutes(15)); 
}
return timetableEnumDtos;
}

結尾

如果想了解更多可以至官方的快取說明