[C#] 記憶體快取 MemoryCache

  • 3713
  • 0
  • C#
  • 2016-09-23

最近開發一個Web Api程式,它每次被呼叫都必須先讀取一份XML檔案,然後將內容反序列化成一個清單變數。但由於Web Api物件的生命週期都只維持一個Request,所以每次Request都必須要重新反序列化,這樣便會造成系統效率下降。因此為避免這樣的情況發生,便很適合導入快取的機制到此系統

快取注意事項

使用「快取」這種機制前,最該要注意的是「資料一致」的問題,也就是在「資料一致」的前提下,如何設計一種機制讓「快取」可以使用最久。

在MemoryCache中,清除「快取」資料的機制可分為「時間」及「變動」兩大類:

  1. 時間
    1. 絕對時間:當現在時間超過某個設定時間點時,此快取資料就會被清除
    2. 使用時間間隔:當此快取資料超過多久沒被使用到的話,就會被清除掉
  2. 變動
    1. 檔案:當某檔案內容有更動時,快取資料就會被清除
    2. 資料庫內容:當SQL語法的執行結果有不同時,快取資料會被清除

使用方式

MemoryCache的使用方式非常單純,當快取中找不到呼叫的key值時,會回傳object 的預設值。

CacheItemPolicy就是先前所說的快取清除機制,像下述範例程式中所使用的AbsoluteExpiration 就是「絕對時間」的設定,當時間超過現在時間的一天之後,此快取資料就會被清除。

static int GetGrade(string name)
{
    if(MemoryCache.Default[name] == default(object))
    {
        CacheItemPolicy policy = new CacheItemPolicy
        {
            AbsoluteExpiration = DateTimeOffset.Now.AddDays(1),
        };
        
        MemoryCache.Default.Add(name, new Random().Next(0, 100), policy);
    }

    return Convert.ToInt32(MemoryCache.Default[name]);
}

更改成「使用時間間隔」機制,當此快取資料超過一分鐘沒被讀取到時,這快取資料就會重新被讀取,其餘程式碼跟上述範例一樣。但要注意一點,「絕對時間」跟「使用時間間隔」只能二選一使用。

CacheItemPolicy policy = new CacheItemPolicy
{
    SlidingExpiration = new TimeSpan(0, 1, 0)
};

如果快取的內容是來自於檔案內容時,這時就是要改用「檔案變動」的清除機制了。「檔案變動」的機制可以與「時間」一起做搭配,且可同時監控多個檔案是否有變動,但監控檔案的路徑只能使用絕對路徑,不能使用相對路徑。

CacheItemPolicy policy = new CacheItemPolicy
{
    SlidingExpiration = new TimeSpan(0, 1, 1)
};

var filePaths = new List<string>() { "D://config.xml", "D://name.xml" };
policy.ChangeMonitors.Add(new HostFileChangeMonitor(monitorFilePaths));

參考資料

保哥 - ASP.NET 4 快取 API 有兩種:Cache 與 ObjectCache

搞搞就懂 - [C#] 初探 MemoryCache 及使用方式介紹