首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

ASP.NET 快取失效三大策略:檔案依賴、絕對過期、滑動過期完整指南

     編輯:關於C

前言:快取三大核心問題

ASP.NET Cache 物件提供伺服器端資料快取,核心挑戰在於:**何時讓快取失效,重新從資料來源載入?** 本文詳細解析三種內建失效策略:檔案依賴、絕對過期、滑動過期,並提供實戰程式碼與選型建議。

快取插入基礎 API

// 完整簽名
public void Insert(
    string key,           // 快取鍵
    object value,         // 快取物件
    CacheDependency dependencies, // 依賴關係 (檔案、鍵、聚合)
    DateTime absoluteExpiration,  // 絕對過期時間
    TimeSpan slidingExpiration,   // 滑動過期間隔
    CacheItemPriority priority,   // 優先級 (記憶體壓力下淘汰順序)
    CacheItemRemovedCallback onRemoveCallback // 移除回呼
);

策略一:檔案依賴 — 外部變更即時失效

適用場景

  • 設定檔 (web.config、appSettings.json、XML、JSON)
  • 靜態資源 (CSV、SQL 腳本、範本檔)
  • 需**即時生效**的業務規則檔

程式碼實作

protected void Page_Load(object sender, EventArgs e) {
    if (!IsPostBack) {
        if (Cache["news"] == null) {
            DataTable dt = LoadData();

            // 關鍵:建立檔案依賴
            // 當 d:\cache.txt 任何變更 (修改時間、大小、刪除),快取立即失效
            CacheDependency dep = new CacheDependency(@"d:\cache.txt");

            Cache.Insert("news", dt, dep);  // 無時間限制,純依賴驅動
            // 等價: Cache.Insert("news", dt, dep, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration);

            GridView1.DataSource = dt;
            GridView1.DataBind();
        } else {
            GridView1.DataSource = (DataTable)Cache["news"];
            GridView1.DataBind();
        }
    }
}

原理

  • ASP.NET 背景執行緒定期輪詢檔案 LastWriteTime (預設 20 秒間隔,可透過 pollTime 設定)
  • 檔案變更 → 依賴觸發 → 快取項目移除 → 下次請求 Cache["news"] == null → 重新載入
  • 注意:網路路徑 (UNC) 需應用程式池身分具備讀取權限

策略二:絕對過期 — 固定時間點強制失效

適用場景

  • 資料有明確「有效期限」 (如每日更新的報表、匯率、新聞快照)
  • 需保證**最晚**在某時間點刷新
  • 不希望因頻繁存取而無限延長壽命

程式碼實作

// 20 秒後絕對過期
Cache.Insert("news", dt, null, 
    DateTime.Now.AddSeconds(20),  // absoluteExpiration
    Cache.NoSlidingExpiration);   // slidingExpiration = TimeSpan.Zero

// 或指定具體時間點 (如每天凌晨 3 點)
Cache.Insert("daily_report", report, null,
    DateTime.Today.AddDays(1).AddHours(3),  // 明天 03:00
    Cache.NoSlidingExpiration);

特性

  • 時間到即失效,**不論是否被存取**
  • 適合「資料時效性」要求高、存取頻率不固定的場景

策略三:滑動過期 — 閒置超時淘汰

適用場景

  • 熱門資料:常被存取 → 留住;冷門資料:久未存取 → 釋放記憶體
  • Session 快取、使用者偏好、權限緩存
  • 配合 LRU 淘汰機制,優化記憶體使用

程式碼實作

// 30 秒內未被存取則過期
Cache.Insert("news", dt, null,
    Cache.NoAbsoluteExpiration,           // absoluteExpiration = DateTime.MaxValue
    TimeSpan.FromSeconds(30));            // slidingExpiration

// 每次存取 (Cache["news"]) 都會重置 30 秒計時器

關鍵行為

  • 讀取 (Cache["key"])、**寫入** (Cache["key"] = val)、**Insert** 都會重置滑動計時器
  • 移除回呼 不會重置計時器
  • 若同時設定絕對 + 滑動,**以先到者為準** (通常不建議混用)

三大策略對比表

維度檔案依賴絕對過期滑動過期
觸發條件外部檔案變更固定時間點到達閒置時間超過間隔
時間可預測性不可預測 (視檔案寫入)完全可控視存取模式動態
資料新鮮度極高 (檔案改即更新)固定窗口內可能過舊熱資料新、冷資料舊
記憶體效率視檔案變更頻率固定佔用至過期優 (冷資料自動釋放)
典型用途設定檔、外部資料源同步定時刷新報表、每日快照Session、熱門查詢結果

進階:web.config 設定 SQL 快取依賴 (資料庫變更觸發)



  
      
      
        
      
    
  
// 程式碼中使用 (需資料表啟用通知: aspnet_regsql -et -E -d DB -t Table)
CacheDependency sqlDep = new SqlCacheDependency("sqldependency", "TableName");
Cache.Insert("data", dt, sqlDep);

最佳實踐清單

  1. 快取 Key 命名規範:Module:Entity:Id:Version (如 News:List:2024:v3),便於群組清除。
  2. 永遠檢查 null:var dt = Cache["key"] as DataTable; if (dt == null) { reload; }
  3. 避免快取大型物件圖:序列化後大小 > 1MB 考慮分割或改用分散式快取 (Redis)。
  4. 設定移除回呼記錄日誌:Cache.Insert(..., onRemoveCallback: (k,v,r) => Log.Info($"Cache removed: {k}, reason: {r}"));
  5. 記憶體壓力測試:模擬高負載觀察 CacheItemPriority 淘汰行為。
  6. 分散式部署:多伺服器場景改用 Redis / Memcached / NCache,本機 Cache 不支援跨節點同步。

總結

  • 檔案依賴:外部觸發,**資料源可控、需即時性**首選。
  • 絕對過期:時間觸發,**固定刷新週期、合規要求**首選。
  • 滑動過期:存取觸發,**熱/冷資料分層、記憶體優化**首選。
  • 實務上常**組合使用**:核心設定檔用檔案依賴,報表用絕對過期,Session 用滑動過期。

理解三者機制與適用場景,能讓你在「資料新鮮度」與「系統效能」之間找到最佳平衡點。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved