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

ASP.NET 緩存全攻略:從頁面輸出到資料層的最佳實踐

     編輯:ASP.NET 基礎

為什麼緩存是效能銀彈?

在 ASP.NET 所有功能中,緩存對應用程式效能的潛在影響最大。善用緩存可讓您大膽使用高耗能控件(如 GridView、DataGrid)而不必擔心效能瓶頸。本文系統梳理三層緩存策略:頁面輸出緩存、片段/用戶控件緩存、資料層 Cache 物件緩存,並給出生產級的存取模式與配置建議。


一、頁面級輸出緩存

最簡單的緩存形式:將完整 HTML 輸出留在記憶體,後續請求直接服務,直到到期。

基本語法

<%@ OutputCache Duration="60" VaryByParam="*" %>

核心屬性詳解

屬性必要說明
Duration是緩存秒數,正整數
VaryByParam是依查詢字串/表單參數建立不同緩存條目;* 為每組參數建獨立條目,none 不變動
Location否Any|Client|Downstream|Server|ServerAndClient|None,預設 Any
VaryByHeader否依 HTTP 標頭變動(如 User-Agent、Accept-Language)
VaryByCustom否自定義變動邏輯,需在 Global.asax 覆寫 GetVaryByCustomString;內建 "browser" 可依瀏覽器名稱/主版本分條目

實戰範例

<!-- 產品目錄:依 categoryID 與 page 分頁緩存 1 小時 -->
<%@ OutputCache Duration="3600" VaryByParam="categoryID;page" %>

<!-- 同一 URL 需同時服務桌面版與行動版 -->
<%@ OutputCache Duration="60" VaryByParam="none" VaryByCustom="browser" %>

二、片段緩存 / 用戶控件輸出緩存

完整頁面緩存常因「個人化區塊」(如使用者名稱、購物車數量)而不可行。解法:將共用區塊(導覽列、頁尾、側邊欄)封裝為 .ascx 用戶控件 並獨立緩存。

語法與屬性差異

  • 語法同 @ OutputCache,但放在 .ascx 檔案頂端。
  • 不支援 Location 屬性(永遠在 Server 端)。
  • 新增 VaryByControl:依控件屬性值(如 DropDownList 選取值)變動緩存。
  • Shared="true":跨頁面共用同一控件緩存條目(需同 ID 引用)。

三種常見模式

<%-- 模式 A:依查詢字串變動,每頁獨立 --%>
<%@ OutputCache Duration="60" VaryByParam="*" %>

<%-- 模式 B:依控件值變動,每頁獨立 --%>
<%@ OutputCache Duration="60" VaryByParam="none" VaryByControl="CategoryDropDownList" %>

<%-- 模式 C:依瀏覽器變動,跨頁共用 --%>
<%@ OutputCache Duration="60" VaryByParam="none" VaryByCustom="browser" Shared="true" %>

三、資料層緩存:Cache 物件深度應用

System.Web.Caching.Cache 可存放任何可序列化物件,並支援豐富的相依性與到期策略。

1. 基本存取

// 簡單存放(無相依,記憶體壓力下自動淘汰)
Cache["key"] = "value";

// 檔案相依:檔案變更即失效
Cache.Insert("xmlData", xmlDoc, new CacheDependency(Server.MapPath("users.xml")));

// 鍵值相依:父鍵失效則子鍵連帶失效
Cache.Insert("child", childObj, new CacheDependency(null, new[] { "parentKey" }));

// 絕對到期:1 分鐘後必失效
Cache.Insert("timeKey", obj, null, DateTime.Now.AddMinutes(1), Cache.NoSlidingExpiration);

// 滑動到期:1 分鐘未被存取則失效(適合熱門資料)
Cache.Insert("hotKey", obj, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(1));

2. 進階選項:優先級與移除回呼

var callback = new CacheItemRemovedCallback(OnRemove);
Cache.Insert("key", obj, null,
    Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(10),
    CacheItemPriority.Default, callback);

public static void OnRemove(string key, object value, CacheItemRemovedReason reason)
{
    // 記錄淘汰原因,判斷是否需擴充記憶體或調整策略
    Log($"Cache '{key}' removed: {reason}");
}
> ⚠️ 注意:回呼在項目已從緩存移除後觸發,無法做到「背景預熱」。若需無縫熱更新,建議採用「雙緩存鍵輪換」或外部分散式緩存(Redis)。

3. 生產級資料存取模式(強型別、單次存取、可旁路)

public DataTable GetCustomers(bool bypassCache = false)
{
    const string cacheKey = "CustomersDataTable";
    var cached = Cache[cacheKey] as DataTable;

    if (bypassCache || cached == null)
    {
        cached = FetchCustomersFromDb(); // 實際資料存取
        var duration = GetCacheSecondsFromConfig(cacheKey); // 從 config 讀取
        Cache.Insert(cacheKey, cached, null,
            DateTime.Now.AddSeconds(duration), Cache.NoSlidingExpiration);
    }
    return cached;
}

關鍵點:

  1. 單次存取:as DataTable 只讀取一次,避免雙重檢查間隙失效拋 NullReferenceException。
  2. 可旁路:寫入新客戶後重導向列表頁時傳 bypassCache=true,即時看到最新資料。
  3. 持久化配置:所有到期時間集中在 web.config 或 appsettings.json,方便調優與 A/B 測試。

四、分層緩存架構建議

層級技術適用資料TTL 建議
瀏覽器HTTP Cache-Control / ETag靜態資源、不變動頁面長(天/月)
CDN/反向代理Vary 標頭、Edge 緩存公開頁面、產品圖片中(分/時)
Web 伺服器OutputCache / UserControl Cache共用片段、導覽、頁尾短~中(秒/分)
應用層Cache 物件 / MemoryCache / IDistributedCache資料實體、查詢結果、計算結果視業務而定
資料庫查詢計畫緩存、物化視圖熱門查詢、彙總報表由 DB 管理

五、緩存反模式與避坑指南

  • ❌ 緩存大型 DataSet/DataTable 且未分頁 → 記憶體暴增,Gen 2 GC 頻繁。改用 PagedDataSource 或僅緩存 DTO 陣列。
  • ❌ 滑動到期用於「必須準時失效」的資料 → 可能因持續存取而永不失效。改用絕對到期或檔案/資料庫相依。
  • ❌ 缺乏緩存擊穿防護 → 熱點鍵失效瞬間大量請求打穿 DB。採用 lock / SemaphoreSlim / 分散式鎖 單飛重建。
  • ❌ 緩存鍵硬編碼散落各處 → 維護困難。集中管理於 CacheKeys 靜態類別。

六、總結

緩存是「用 20% 功夫換 80% 效能提升」的高杠桿手段。建議採取 由外而內、漸進式 策略:

  1. 先開啟靜態資源與公開頁面的 輸出緩存;
  2. 將共用區塊抽為 用戶控件並片段緩存;
  3. 識別熱點查詢,引入 資料層 Cache 物件 並建立統一存取模式;
  4. 隨流量增長,平滑遷移至 分散式緩存(Redis/NCache)。
「盡早緩存,經常緩存;內存現在很便宜,聰明地用它換取穩定的高效能。」
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved