2017-01-30

使用 .NET Framework 內建的 MemoryCache 來 Cache 常用資料 - Part 1 極簡做法

程式多多少少有些資料或設定是經常需要使用的,如果這些資料異動頻率低的特性就可以考慮將其加入 cache,以節省每次使用都要 access 資料庫或是 call api 取得的成本,讓程式執行效能獲得提升。


一、加入參考

  1. 專案視窗 Reference 右鍵 --> Add Reference...

    1reference

  2. 在 Assemblies tab 下,搜尋 System.Runtime.Caching
    • 注意:要使用 4.0.0.0 版本(有些環境可能有 2.0.0.0 版本)

      2addref

二、加入 CacheHelper.cs

  1. 將 class 改為 static public static class CacheHelper

  2. 引用 System.Runtime.Caching using System.Runtime.Caching;

  3. 定義 MemoryCache 的私有欄位 (field) private static MemoryCache _cache = MemoryCache.Default;

  4. 定義所需資料屬性 (property)

    • 僅需 getter
    /// <summary>
    ///  TableData
    /// </summary>
    public static List<Table> TableData
    {
        get
        {
            if (!_cache.Contains("TableData"))
             RefreshTableData();
         return _cache.Get("TableData") as List<Table>;
     }
    }
    
  5. 加上更新方法

    • 取資料時只取常使用的欄位以節省資源
    /// <summary>
    /// 更新 TableData
    /// </summary>
    public static void RefreshTableData()
    {
        //移除 cache 中資料
        _cache.Remove("TableData");
    
        //存取資料
        TestEnumEntities db = new TestEnumEntities();
        var listAgency = db.Table.ToList();
    
        //設定 cache 過期時間
        CacheItemPolicy cacheItemPolicy = new CacheItemPolicy() {AbsoluteExpiration = DateTime.Now.AddDays(1) };
        //加入 cache
        _cache.Add("TableData", listAgency, cacheItemPolicy);
    }
    

三、實際使用

  • 引用 CacheHelper 的 namespace 後直接使用 var tableData=CacheHelper.TableData;

四、心得與缺陷

我一直以來都是使用上面介紹的方法來實現簡易 Cache ,使用上相當便利,經歷幾個較大專案考驗後發現問題,接著又看到黑大的文章 改良式GetCachableData可快取查詢函式 驚覺有重大缺陷, 為了解決缺點,會透過後面的文章來逐步改善上面程式碼的問題。

  1. 沒有加上 lock 機制

    可能造成程式會去大量去 DB 取資料 ,形成 DDOS

  2. 沒有使用泛型

    需要加入新資料到 Cache 時,會有重複的 code 出現

參考資料

  1. MemoryCache 方法
  2. 改良式GetCachableData可快取查詢函式

沒有留言:

張貼留言