[設計案例] 清除Cache物件 #2. Create Custom CacheDependency
問題與答案 (FAQ)
Q&A 類別 A: 概念理解類
Q1: 什麼是 CacheDependency?
- A簡: CacheDependency 定義快取與外部資源的相依關係,當相依資源變更時,快取項目自動失效,避免手動清除,確保資料一致性。
- A詳: CacheDependency 是 ASP.NET 快取機制中的相依性描述物件。它讓快取項目與某些資源(檔案、目錄、資料庫或自訂條件)建立相依關係。一旦相依資源發生變化,快取會自動將相關項目標記為無效並移除。這種設計避免手動以 key 一個個清除,提高一致性與維護性。常見應用包含:文件變更失效、資料庫通知失效,以及本文示範的「標籤式失效」。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q2, A-Q7, B-Q1
Q2: 什麼是自訂 CacheDependency?
- A簡: 自訂 CacheDependency 透過繼承 CacheDependency,實作自定義的變更通知機制,控制快取何時因自定條件而失效。
- A詳: 自訂 CacheDependency 指從 CacheDependency 衍生子類別,根據業務需求建立相依性的判斷與觸發機制。例如本文的 TaggingCacheDependency 以「標籤」建立關聯,當指定標籤被「發佈失效」時,所有帶該標籤的快取項目即刻失效。實作上常涉及:初始化(SetUtcLastModified、FinishInit)、管理相依項目集合,以及在條件達成時呼叫 NotifyDependencyChanged 來通知快取失效。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q4, B-Q1, B-Q6
Q3: 為什麼需要標籤式(Tagging)快取失效?
- A簡: 標籤式失效可群組清除多筆快取,避免逐一以 key 清除,適合依主機、類別、資料來源批次失效控制。
- A詳: 當快取項目量大、key 難以一致命名、或需依來源屬性(如網站主機、資料類別、Schema)批次清除時,傳統以 key 移除非常低效且易遺漏。標籤式失效讓每個快取項目綁定一或多個語意化標籤,當資料源變更或運維要求清空特定範圍時,只需針對該標籤發布失效,即可自動移除所有相關快取,降低複雜度、風險與維護成本。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q6, A-Q14, B-Q2
Q4: 什麼是 TaggingCacheDependency?
- A簡: TaggingCacheDependency 是自訂 CacheDependency,透過標籤與快取關聯,調用 DependencyDispose(tag) 即批次使其失效。
- A詳: TaggingCacheDependency 繼承自 CacheDependency,內部以靜態 Dictionary<string, List
> 維護「標籤→相依實例清單」對應。建立快取時以若干 tags 初始化相依物件,登錄到字典。當需清除某標籤時,呼叫 DependencyDispose(tag) 逐一對清單內相依物件呼叫 NotifyDependencyChanged,使所有綁定該標籤的快取項目立刻失效。此設計提供簡潔、語意化的群組快取清理能力。 - 難度: 初級
- 學習階段: 基礎
- 關聯概念: B-Q1, B-Q9, C-Q1
Q5: 什麼是 HttpRuntime.Cache?與快取項目有何關係?
- A簡: HttpRuntime.Cache 是 ASP.NET 應用域的全域快取集合,儲存快取項目並支援相依性、到期與優先級策略。
- A詳: HttpRuntime.Cache 提供應用程式層級的記憶體快取。可透過 Add/Insert 設定 key、值、CacheDependency、Absolute/Sliding 期限、CacheItemPriority 及移除回呼。快取項目(Cache Item)即以 key 存放的資料物件。當到期或相依性變更,快取會移除項目並可觸發回呼以便觀測或收斂後續行為。本文示例在 Console/ASP.NET 皆可存取 HttpRuntime.Cache 進行演示。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: B-Q3, A-Q11, C-Q2
Q6: 用 key 移除與用 Tagging 失效有何差異?
- A簡: key 移除需逐一指定,易遺漏;Tagging 依語意群組一次清空相關快取,維護成本低且不須知道全部 key。
- A詳: 以 key 移除時,必須知道所有相關快取的 key,對動態或跨模組情境難以完整掌握;且多 key 操作程序繁瑣。Tagging 失效則以語意化標籤(如 host、scheme、類別)建立群組,當目標範圍需清空時只需針對標籤發布失效,系統自動散播到所有相依快取項目。這能顯著降低耦合、簡化操作並避免殘留舊資料。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q3, A-Q4, B-Q2
Q7: CacheDependency 的核心價值是什麼?
- A簡: 自動化失效控制,以變更驅動快取移除,維持資料正確與一致,減少手動維運風險與程式複雜度。
- A詳: 核心價值在於「正確性與自動化」。透過相依性監控外部資源或自定條件,快取能即時跟隨真實資料狀態更新,避免提供過時結果。同時免去逐一清除的機械作業,有利於模組化、跨團隊協作與運維自動化。對高併發讀取場景,可在不犧牲一致性的前提下延伸快取命中率,提升整體效能。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q1, A-Q6, B-Q7
Q8: 什麼是 NotifyDependencyChanged?
- A簡: NotifyDependencyChanged 是 CacheDependency 用來通知快取「相依已變」的方法,觸發綁定項目立即失效與回呼。
- A詳: 在自訂 CacheDependency 中,當判定相依性條件成立(例如發布某標籤失效)時,呼叫 NotifyDependencyChanged(sender, EventArgs) 會告知快取系統此相依已改變。快取隨即將所有綁定該相依的項目移除,並以 CacheItemRemovedReason.DependencyChanged 觸發回呼。這是自訂相依變更的標準入口,務必在初始化完成後才會有效。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q2, B-Q7, D-Q2
Q9: SetUtcLastModified 與 FinishInit 在自訂相依中扮演何種角色?
- A簡: 它們完成相依初始化流程,設定初始狀態並告訴快取「可用」,之後才能正確發出變更通知。
- A詳: CacheDependency 的生命週期需經過初始化。SetUtcLastModified 設定相依最後更新時間(本文以 DateTime.MinValue 做初始),FinishInit 則標記相依初始化結束並註冊必要內部狀態。少了這兩步,快取可能不接受後續的變更通知或行為未定義。慣例是在自訂相依的建構子中完成「登錄→設定時間→FinishInit」的順序。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q6, B-Q19, D-Q8
Q10: 什麼是 CacheItemRemovedReason?
- A簡: 表示快取項目被移除的原因枚舉,如 Expired、Removed、Underused、DependencyChanged,用於回呼判斷處置。
- A詳: CacheItemRemovedReason 是移除原因的列舉型別。在移除回呼中可依值決策:Expired(到期)、Removed(主動移除)、Underused(記憶體壓力回收)、DependencyChanged(相依變更)。本文示例透過回呼打印被移除的 key,實務上可依原因記錄或重建快取。理解原因有助於診斷行為與優化策略。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: B-Q5, D-Q6, D-Q9
Q11: 快取移除回呼(callback)有何用途?
- A簡: 回呼在項目移除時觸發,可記錄、告警、重建或鏈結後續流程,提升觀測與恢復能力。
- A詳: 在 Cache.Add/Insert 可提供 CacheItemRemovedCallback。當快取移除時,回呼取得 key、值與移除原因。本案例打印移除訊息以驗證標籤失效是否覆蓋正確範圍。實務上可用於:記錄審計、埋點監控、觸發重算、更新下游快取、主動預熱等。注意回呼執行環境與例外處理,避免阻塞或二次例外。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q10, B-Q5, C-Q7
Q12: 標籤(tag)應如何選取與設計粒度?
- A簡: 依據清除需求設計語意清楚的 tag,如主機、業務類別或資料來源;粒度適中以避免過清或漏清。
- A詳: Tag 設計須回到失效策略。若常以來源主機批次清理,可用 host;若依資料類別或租戶管理,用類別或租戶 ID;若需跨維度清除,可多 tag 組合。粒度過粗易過度清理影響命中;過細會增高管理成本且清不乾淨。建議先盤點清除場景,再定義可組合的標籤集合。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: C-Q5, B-Q8, D-Q3
Q13: 範例中為何選擇 host 與 scheme 作為標籤?
- A簡: 以 host、scheme 能按來源站點或協定批次清除,符合下載任務的主要分群與維運需求。
- A詳: 範例緩存的是多個 URL 的下載結果。以 host 作為標籤,可輕易對特定來源站點(如 funp.com)全站清空;以 scheme(http/https)則能按協定批次管理。這兩種屬性簡單、穩定且易於從 URI 取值,能滿足最常見的維運清除場景,降低實作複雜度。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: C-Q2, B-Q1, D-Q2
Q14: TaggingCacheDependency 使用的資料結構是什麼?為何如此設計?
- A簡: 使用 Dictionary<string, List
> 映射標籤到相依清單,便於快速找到需通知的相依。 - A詳: 透過字典以標籤作 key,value 為綁定該標籤的相依物件清單,建立 O(1) 查找。當呼叫 DependencyDispose(tag) 時,直接取出清單並逐一通知,效率高且實作簡單。此結構也天然支援一個相依物件同時登錄到多個標籤(在建構子內 for-each 逐一加入)。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q9, B-Q8, D-Q5
Q15: 多個標籤是如何被支援的?
- A簡: 以 params string[] tags 建構子接收多標籤,逐一將相依物件加入各標籤對應清單,即可同時關聯多群組。
- A詳: 類別建構子簽名為 params string[] tags,呼叫端可傳入一或多個字串標籤。內部對每個 tag 檢查字典是否存在,不在則建立,再將 this 加入對應 List。之後任何一個標籤被發布失效,都會使該相依(與其綁定的快取項目)被移除,實現 OR 邏輯的群組清除。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: B-Q8, C-Q5, D-Q3
Q16: 本設計案例的應用場景是什麼?
- A簡: 批次下載多組網址並快取結果,需能一鍵清空特定來源(如某主機)的快取以確保資料新鮮。
- A詳: 程式維護一份 URL 清單,逐一下載並將資料放入快取,附上以 host、scheme 為標籤的 TaggingCacheDependency。當需要清理特定來源(如 funp.com)之所有下載結果,只需呼叫 DependencyDispose(“funp.com”),快取立即移除所有相關項目,並透過回呼印出被移除的鍵,驗證行為正確。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: C-Q2, B-Q5, D-Q2
Q17: 何謂時間到期與相依失效的差異?
- A簡: 時間到期依時效自動移除;相依失效由外部條件觸發。兩者可並存,以先到者為準。
- A詳: 快取可同時設定 Absolute/Sliding 到期與 CacheDependency。時間到期適合預估有效期的資料;相依失效適合資料來源不可預測變更的情境。當兩者並存,任何一個條件達成都會移除項目。本例中設定 600 秒滑動時效與標籤相依,既保證最長存活,又可隨時批次清理。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: B-Q15, D-Q9, A-Q10
Q18: CacheItemPriority.NotRemovable 表示什麼?
- A簡: 表示在記憶體回收壓力下優先保留此項目,不因「使用率低」而被清除,但仍會因到期或相依失效移除。
- A詳: CacheItemPriority 定義了在記憶體壓力情境中的回收優先級。NotRemovable 表示除非到期、相依變更或手動移除,否則不要因 Underused 被回收。這對關鍵資料有用,但也需謹慎,避免阻礙系統釋放記憶體。本文示例將下載資料設為 NotRemovable,確保主要由失效策略而非壓力驅動移除。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: B-Q16, D-Q4, D-Q10
Q19: 為什麼要用回呼印出移除資訊?
- A簡: 便於驗證標籤失效範圍與行為,並做觀測與除錯,確保設計如預期運作。
- A詳: 在導入新失效機制時,回呼提供即時可觀測性。透過列印被移除的 key 與原因,可確認是否只清除了期望的主機資料(如 funp.com),並評估是否有意外波及。此做法也能快速定位錯誤標籤、重複關聯或未被清除的項目,有助於測試與運維。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: B-Q5, D-Q2, C-Q7
Q20: 相依驅動的失效與時間驅動的核心價值比較?
- A簡: 相依驅動精準、即時;時間驅動簡單、可預期。常需混搭,以平衡正確性與成本。
- A詳: 相依驅動能在資料變動瞬間同步清理快取,提供高一致性;但需建置通知機制。時間驅動實作簡單,適合容忍短暫過期的情境;但可能在過期前提供舊資料。實務上多用混合策略:以相依確保正確性、以時間限制最長存活,兼顧穩定與效能。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q17, B-Q15, D-Q9
Q21: 何時應選擇自訂 CacheDependency 而非現成類型?
- A簡: 當現成依賴(檔案、目錄、SQL)無法表達你的失效條件,或需語意化群組清理時,適合自訂。
- A詳: 現成類型如 File/CacheDependency、SqlCacheDependency 針對特定來源有效。當你的失效需求與業務語意高度綁定(如標籤、租戶、版本),或資料源變更無法由檔案或資料庫通知涵蓋,自訂相依可提供彈性與正確性。本文標籤式失效即屬典型情境。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q23, B-Q24, C-Q1
Q22: 標籤式失效的核心價值是什麼?
- A簡: 以語意群組批次清除,解耦快取 key 與清理流程,降低漏清風險,提升維運效率與可理解性。
- A詳: 標籤將清理意圖從「列舉所有 key」轉為「宣告語意範圍」。這種宣告式管理使清理更可讀、可重用,並支持一鍵覆蓋多模組快取。對跨系統資料源,標籤能對齊業務概念(站點、租戶、產品線),減少跨團隊溝通成本,提高正確性。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q3, A-Q6, C-Q5
Q23: 這種設計的限制與風險是什麼?
- A簡: 需處理執行緒安全、記憶體釋放與重複通知;標籤設計不當會過度或不足清理。
- A詳: 風險包含:靜態字典非執行緒安全,並發登錄/清理可能拋例外或產生競態;相依對象被通知後需從索引移除避免記憶體洩漏;標籤粒度錯誤導致影響範圍不精確;回呼內長耗時造成阻塞。需以 thread-safe 容器或鎖、弱參考或註冊清理、嚴謹的標籤規約與觀測改善。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q11, D-Q4, D-Q5
Q24: 何謂群組式快取失效(Group Invalidation)?
- A簡: 將多個快取以群組或標籤關聯,發布一次失效指令即可移除整組項目,簡化維運。
- A詳: 群組式失效是一種將多筆快取以共同語意綁定的策略。TaggingCacheDependency 即以「標籤」作為群組鍵。相較於逐 key 操作,群組失效使操作語意化、原子化且可擴充,特別適合多來源、多模組的快取系統。它常與層級、前綴、或複合條件搭配。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q3, C-Q5, B-Q22
Q25: 本案例與 ASP.NET 應用程式快取的關係?
- A簡: 本案例直接使用 HttpRuntime.Cache,適用於 ASP.NET 應用域,示範如何擴充依賴機制以支援標籤清理。
- A詳: 雖以簡化 Console 形式呈現,核心 API 與 ASP.NET 應用一致。實際 Web 專案可在控制器、服務層使用相同做法,以 TaggingCacheDependency 為快取項目標記標籤,並透過管理介面或運維腳本調用 DependencyDispose 來批次清理,配合回呼進行觀測。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: C-Q6, B-Q3, D-Q6
Q&A 類別 B: 技術原理類
Q1: TaggingCacheDependency 的運作機制是什麼?
- A簡: 以靜態字典建立「標籤→相依清單」索引,初始化登錄;發布失效時逐一通知相依,使綁定快取移除。
- A詳: 技術原理說明:類別繼承 CacheDependency。建構子接收多標籤,對每個標籤在靜態 Dictionary 建立或取得 List,將當前相依實例加入;之後呼叫 SetUtcLastModified 與 FinishInit 完成初始化。關鍵流程:DependencyDispose(tag) 取出該標籤清單,迭代清單呼叫 NotifyDependencyChanged,快取系統即移除相依項目。核心組件:靜態字典、相依實例、通知 API。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q4, B-Q2, B-Q9
Q2: DependencyDispose(tag) 的執行流程為何?
- A簡: 檢查標籤存在→迭代清單呼叫 NotifyDependencyChanged→清空清單並自字典移除該鍵,完成一次失效。
- A詳: 技術原理說明:方法先以 ContainsKey 判斷標籤是否存在。若存在,for-each 該 List,對每個 TaggingCacheDependency 呼叫 NotifyDependencyChanged(null, EventArgs.Empty)。快取收到通知即移除綁定項目並觸發回呼。關鍵步驟或流程:1) 取清單;2) 通知;3) 清空清單;4) 從字典移除鍵。核心組件:字典、相依清單、通知 API。清理集合可避免重複通知與記憶體滯留。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q8, B-Q7, D-Q2
Q3: Cache.Add 中各參數與流程是什麼?
- A簡: key、value、CacheDependency、Absolute/Sliding 到期、Priority、回呼;快取登錄後,依策略與相依控制存活。
- A詳: 技術原理說明:Add(key, value, dependency, absoluteExpiration, slidingExpiration, priority, onRemoveCallback)。關鍵步驟:1) 建立值與相依;2) 設定到期策略(本文用 NoAbsoluteExpiration + 600 秒 Sliding);3) 設定 Priority(NotRemovable);4) 註冊回呼。核心組件:快取儲存體、時效管理、相依管理、回呼機制。運作時,任一到期或相依變更會移除項目並執行回呼。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q5, A-Q17, A-Q18
Q4: DownloadData 方法如何配合快取運作?
- A簡: 先查快取,無則下載並加入快取、附加 TaggingCacheDependency;有則直接回傳快取資料。
- A詳: 技術原理說明:以 URL 字串作為 key。關鍵步驟或流程:1) 嘗試從 HttpRuntime.Cache 取 byte[];2) 若為 null,執行下載取得 buffer;3) 以 host、scheme 建構 TaggingCacheDependency;4) 設定時效與優先級,附回呼;5) 加入快取並回傳。核心組件:Cache API、相依建構子、回呼。如此將 I/O 成本轉為快取讀取,並保留可控的群組清理能力。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: C-Q2, A-Q13, D-Q1
Q5: 移除回呼如何被觸發與運作?
- A簡: 快取移除項目時自動調用回呼,傳入 key、值與移除原因,便於記錄、修復或鏈結後續流程。
- A詳: 技術原理說明:回呼在移除階段由快取執行緒呼叫,保證在項目從快取消失之後。關鍵步驟或流程:1) 觸發事件(到期、相依或主動移除);2) 快取構造 CacheItemRemovedReason;3) 調用委派。核心組件:回呼委派、原因枚舉、快取移除流程。需避免在回呼中做長耗時操作,並注意捕捉例外。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q10, A-Q11, D-Q6
Q6: 自訂 CacheDependency 的初始化機制是什麼?
- A簡: 在建構子中登錄相依、SetUtcLastModified 設定初始時間,呼叫 FinishInit 完成初始化,方可通知變更。
- A詳: 技術原理說明:CacheDependency 期望繼承者完成兩件事:建立變更來源與狀態、宣告初始化完成。關鍵步驟或流程:1) 準備內部資料結構(標籤字典、清單);2) SetUtcLastModified(初始值);3) FinishInit()。核心組件:基底類別初始化協定、時間戳、內部狀態。若遺漏步驟,NotifyDependencyChanged 可能無效或行為未定。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q9, D-Q8, B-Q1
Q7: 當呼叫 NotifyDependencyChanged 時內部會發生什麼?
- A簡: 快取標記相依已變,移除綁定項目、釋放資源並觸發回呼,移除原因為 DependencyChanged。
- A詳: 技術原理說明:快取保存項目與相依之關聯表。通知到達時,快取找到綁定項目,將其從儲存體移除,釋放關聯資源(相依對象可能被 Dispose),並召回回呼。關鍵步驟:更新狀態→移除→回呼。核心組件:關聯表、儲存體、回呼系統。對呼叫者來說,這是一個同步的「播報」動作,應避免頻繁大規模呼叫造成阻塞。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q8, D-Q7, B-Q2
Q8: 多標籤登錄的內部關聯如何維護?
- A簡: 相依實例會加入多個標籤清單,標籤任一被失效即通知同一相依,實現 OR 關係的群組清理。
- A詳: 技術原理說明:建構子對 tags 陣列迭代,對每個字串在字典建立或取出 List,將 this 加入。關鍵步驟:for-each tags→Add(this)。核心組件:字典、清單、相依實例。若需 AND 行為,需自訂計數或條件聚合;本文實作為 OR 行為,任一標籤失效即移除。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q15, C-Q5, D-Q3
Q9: 靜態字典在此扮演何種角色?
- A簡: 提供全域索引,讓任意處呼叫 DependencyDispose 可找到所有相依實例,實現跨範圍控制。
- A詳: 技術原理說明:使用 static Dictionary 確保同一 AppDomain 共享一份「標籤→相依」索引。關鍵步驟:初始化時寫入、清理時依標籤讀出並遍歷。核心組件:字典鍵值對、標籤字串、相依清單。注意執行緒安全與 AppDomain 重啟行為(IIS 回收),必要時引入鎖或 Concurrent 容器。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q14, B-Q11, D-Q5
Q10: 為何在 DependencyDispose 後要清空清單並移除字典鍵?
- A簡: 避免重複通知、釋放參考降低記憶體占用,防止日後誤用造成不一致。
- A詳: 技術原理說明:已通知的相依通常已完成使命。不清空清單將保留對相依的強參考,可能導致記憶體滯留;重複發布失效會再通知已處理的實例,造成多餘工作或例外。關鍵步驟:Clear→Remove(tag)。核心組件:清單、字典。這也是良好資源管理與冪等性的體現。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: D-Q4, D-Q7, B-Q2
Q11: 此實作存在哪些執行緒安全考量?
- A簡: 靜態字典與清單非執行緒安全,並發登錄與清理可能競態;需加鎖或改用並行容器。
- A詳: 技術原理說明:多執行緒同時新增/讀取/清除會造成集合修改例外或遺漏通知。關鍵步驟:在寫入與遍歷時加鎖,或以 ConcurrentDictionary<string, ConcurrentBag
> 替代;通知時可快照清單以避免遍歷期間修改。核心組件:鎖、並行集合、快照策略。 - 難度: 高級
- 學習階段: 進階
- 關聯概念: D-Q5, C-Q4, B-Q9
Q12: 這種設計如何擴充以支援層級/前綴標籤?
- A簡: 可在索引中加入字首樹或前綴比對,或設計層級命名規約,發佈時比對匹配多個標籤。
- A詳: 技術原理說明:建立前綴檢索(Trie)或維護輔助索引以快速查出所有匹配前綴的標籤清單。關鍵步驟:標籤規約設計(如 tenant:site:category)、建立層級索引、發佈時展開匹配集再逐一通知。核心組件:索引資料結構、比對演算法、批次通知流程。可大幅提升語意表達能力。
- 難度: 高級
- 學習階段: 進階
- 關聯概念: C-Q5, A-Q12, B-Q22
Q13: 標籤查找效率如何影響整體效能?
- A簡: 單標籤 O(1) 查找,通知成本與清單長度成正比;清單過長會拉高失效延遲。
- A詳: 技術原理說明:Dictionary 查找是 O(1)。瓶頸在於遍歷清單與對快取的移除操作。關鍵步驟:控制清單長度(適當粒度)、分批通知、後台任務化。核心組件:字典、清單、快取移除。若長清單常見,考慮拆分標籤或引入分散式策略。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: D-Q10, A-Q12, B-Q10
Q14: 相依與快取項目的生命週期關係為何?
- A簡: 項目存在期間相依存活;相依變更則項目移除,相依通常隨之釋放,不再重用。
- A詳: 技術原理說明:快取項目持有 CacheDependency。當項目被移除,相依可能由快取釋放(Dispose)。關鍵步驟:新增項目→綁定相依→正常命中→相依變更→移除項目/回呼→釋放。核心組件:快取儲存體、相依物件、回呼。重用相依需謹慎,避免跨項目共享造成不可預期。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q7, D-Q7, A-Q4
Q15: Absolute 與 Sliding 到期如何與相依並存?
- A簡: 可同時設定;任一條件達成即移除。Sliding 每次命中延長壽命,Absolute 不會延長。
- A詳: 技術原理說明:快取維護兩種時效與相依條件。關鍵步驟:新增時設定 NoAbsoluteExpiration 或具體時間,再設定 Sliding 期間;命中時更新 Sliding 計時;到期或相依變更即移除。核心組件:時鐘、時效管理、相依通知。混搭能平衡新鮮度與成本。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q17, D-Q9, B-Q3
Q16: CacheItemPriority 如何影響回收策略?
- A簡: 設置優先級影響記憶體壓力下的淘汰順序;NotRemovable 最後才被壓力回收,但仍受時效與相依控制。
- A詳: 技術原理說明:當系統壓力觸發回收時,快取會依 Priority 決定候選移除集合。關鍵步驟:評估壓力→挑選低優先級與使用率低項目→移除。核心組件:優先級列舉、使用率統計。應避免全面使用 NotRemovable,防止阻礙健康回收。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q18, D-Q10, A-Q10
Q17: 相依變更時回呼的 Reason 值為何?
- A簡: 為 DependencyChanged,可在回呼中據此分流處理,如記錄標籤失效或觸發重建。
- A詳: 技術原理說明:快取在處理 NotifyDependencyChanged 路徑時,設定 Reason=DependencyChanged。關鍵步驟:變更→移除→回呼。核心組件:回呼委派、Reason 枚舉。應用場景:根據原因做監控分類與決策,例如相依失效觸發預熱,時間到期則僅記錄。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q10, A-Q11, C-Q7
Q18: 為什麼 SetUtcLastModified(DateTime.MinValue) 合理?
- A簡: 作為初始化的「最初修改時間」,確保相依已設定狀態,後續通知才有效且行為一致。
- A詳: 技術原理說明:自訂相依不依賴檔案時間戳,仍需初始化最後修改時間。以 MinValue 作為「初始」語意,標示當前狀態有效。關鍵步驟:設定時間→FinishInit。核心組件:時間戳、初始化協定。更嚴謹可用當下 UTC 時間,本文採簡化。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q9, B-Q6, D-Q8
Q19: 為何必須呼叫 FinishInit()?
- A簡: 宣告初始化完成,使快取接受後續通知;缺漏可能導致通知無效或狀態未定。
- A詳: 技術原理說明:CacheDependency 在初始化前後內部狀態不同。FinishInit 會鎖定初始參數、註冊必要掛鉤。關鍵步驟:準備→SetUtcLastModified→FinishInit。核心組件:基底初始化流程。未呼叫將導致不可預期行為,是常見踩雷點。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q9, D-Q8, B-Q6
Q20: HttpRuntime.Cache 與 HttpContext.Current.Cache 差異?
- A簡: 兩者指向同一快取,但 HttpRuntime 不依賴目前 HTTP 請求,較適合非請求情境使用。
- A詳: 技術原理說明:兩者最終引用同一 Cache 實例。HttpContext 需存在有效請求;在背景工作、Console 測試或非請求執行緒中,建議用 HttpRuntime.Cache。關鍵步驟:存取全域快取。核心組件:應用域快取、執行緒上下文。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q5, C-Q6, D-Q6
Q21: 自訂相依如何與多層快取(如分散式)協作?
- A簡: 可將標籤失效事件外放(如訊息總線),由各層接收後本地通知,實現跨節點一致清理。
- A詳: 技術原理說明:在本地 TaggingCacheDependency 外,增加失效事件散播(Redis Pub/Sub、MQ)。關鍵步驟:本地發布→發佈事件→各節點接收→本地 DependencyDispose。核心組件:事件匯流排、本地相依。可擴至分散式一致性。
- 難度: 高級
- 學習階段: 進階
- 關聯概念: C-Q6, D-Q10, B-Q12
Q22: 如何設計可組合的標籤策略?
- A簡: 採用規約化命名、支援多標籤、前綴/層級,並提供批次匹配與統一發布介面。
- A詳: 技術原理說明:以命名規約規範維度(如 env:tenant:domain),實作多標籤 OR、前綴展開與群組 API。關鍵步驟:規約→索引→匹配→通知。核心組件:字典/Trie、批次處理、API 設計。提升表達力與操作便利性。
- 難度: 高級
- 學習階段: 進階
- 關聯概念: A-Q12, B-Q12, C-Q5
Q23: 與 SqlCacheDependency 的比較與取捨?
- A簡: SqlCacheDependency 提供資料庫變更通知;自訂相依更彈性,能表達非資料庫與語意化群組情境。
- A詳: 技術原理說明:SqlCacheDependency 依賴資料庫通知或輪詢,對資料表/查詢有效;自訂相依可包裝任意條件(標籤、權限、版本)。關鍵取捨:一致性來源、部署複雜度、可觀測性。若變更源於 DB 且可用通知,選 SQL;否則採自訂或兩者混用。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q21, B-Q24, C-Q1
Q24: 與檔案/目錄相依的比較?
- A簡: 檔案/目錄相依監看檔案系統變更;自訂相依擴充語意與群組能力,涵蓋更多非檔案情境。
- A詳: 技術原理說明:File/Directory 依賴 FileSystemWatcher 或時間戳,適合靜態內容。自訂相依可將業務事件轉為通知。關鍵取捨:變更來源、延遲、部署成本。若內容生成於檔案較穩定,選檔案;需語意化批次清理,選自訂。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q21, B-Q23, C-Q1
Q25: 如何觀測與測試標籤失效是否正確?
- A簡: 使用移除回呼與日誌,針對目標標籤發布失效,驗證被移除 key 集合是否與預期匹配。
- A詳: 技術原理說明:在回呼打印 key 與 Reason,並收集至測試斷言。關鍵步驟:準備多組標籤與項目→發布失效→比對集合。核心組件:回呼、測試斷言、日誌。可用自動化測試覆蓋多標籤、前綴與競態情境,降低回歸風險。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: C-Q8, D-Q2, A-Q19
Q&A 類別 C: 實作應用類
Q1: 如何實作一個最小可用的 TaggingCacheDependency?
- A簡: 繼承 CacheDependency,維護標籤索引,建構子登錄並完成初始化,提供 DependencyDispose 通知失效。
- A詳: 實作步驟: 1) 宣告 static Dictionary<string, List
>; 2) 建構子接收 params string[] tags,逐一加入字典;3) 呼叫 SetUtcLastModified 與 FinishInit;4) 提供 public static DependencyDispose(tag)。程式碼片段: public class TaggingCacheDependency: CacheDependency { static Dictionary<string,List > map = new(); public TaggingCacheDependency(params string[] tags){ foreach(var t in tags){ if(!map.ContainsKey(t)) map[t]=new(); map[t].Add(this);} SetUtcLastModified(DateTime.MinValue); FinishInit();} public static void DependencyDispose(string tag){ if(map.TryGetValue(tag,out var list)){ foreach(var d in list) d.NotifyDependencyChanged(null,EventArgs.Empty); list.Clear(); map.Remove(tag);} } } 注意事項: 初始化順序、清單清理、例外處理。 - 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q1, B-Q2, C-Q4
Q2: 如何將下載資料以 host/scheme 標籤加入快取?
- A簡: 先查快取;無則下載,建構 TaggingCacheDependency(host, scheme),設定到期與回呼後加入快取。
- A詳: 實作步驟: 1) var key=url.ToString(); var data=Cache[key] as byte[]; 2) 若 null,下載資料;3) var dep=new TaggingCacheDependency(url.Host,url.Scheme); 4) Cache.Add(key,data,dep,Cache.NoAbsoluteExpiration,TimeSpan.FromSeconds(600),CacheItemPriority.NotRemovable,OnRemoved)。程式碼片段: HttpRuntime.Cache.Add(key, buffer, new TaggingCacheDependency(uri.Host, uri.Scheme), Cache.NoAbsoluteExpiration, TimeSpan.FromSeconds(600), CacheItemPriority.NotRemovable, OnRemoved); 注意: key 唯一性、錯誤處理、回呼勿長耗時。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q13, B-Q4, C-Q7
Q3: 如何發布標籤失效以清除一組快取?
- A簡: 調用 TaggingCacheDependency.DependencyDispose(tag),快取會移除所有綁定該標籤的項目並觸發回呼。
- A詳: 實作步驟: 1) 確定要清除的標籤(如 “funp.com”);2) 呼叫 DependencyDispose(“funp.com”); 3) 觀測回呼或日誌。程式碼片段: TaggingCacheDependency.DependencyDispose(“funp.com”); 注意事項: 在高併發環境建議加鎖或快照清單;避免在 request 線程做大量清理造成延遲,可移至背景工作執行。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: B-Q2, A-Q16, D-Q2
Q4: 如何為標籤索引加入執行緒安全?
- A簡: 對讀寫操作加鎖,或採用 ConcurrentDictionary 搭配 ConcurrentBag,通知時先快照清單再遍歷。
- A詳: 實作步驟: 1) 將 map 改為 ConcurrentDictionary<string,ConcurrentBag
>;2) 登錄時 bag.Add(this);3) 失效時 map.TryGetValue(tag,out var bag),var list=bag.ToArray(); foreach 通知;4) 最後 map.TryRemove(tag,out _)。程式碼片段: static ConcurrentDictionary<string,ConcurrentBag > map=new(); 注意事項: 避免遍歷期間修改;考慮相依已被處置的情形要捕捉例外。 - 難度: 高級
- 學習階段: 進階
- 關聯概念: B-Q11, D-Q5, C-Q1
Q5: 如何設計多層級/前綴標籤失效?
- A簡: 採用命名規約與前綴展開,或建立 Trie 索引;發布時比對前綴並批次對所有匹配標籤通知。
- A詳: 實作步驟: 1) 定義命名: env:tenant:domain;2) 維護額外索引(Trie 或字首表); 3) DependencyDisposePrefix(prefix){ 找出所有以 prefix 開頭的標籤,逐一呼叫 DependencyDispose(tag); } 程式碼片段: foreach(var tag in map.Keys.Where(k=>k.StartsWith(prefix))) DependencyDispose(tag); 注意事項: 批次操作需避免與單標籤同時併發;觀測與限流。
- 難度: 高級
- 學習階段: 進階
- 關聯概念: B-Q12, B-Q22, A-Q12
Q6: 如何在 ASP.NET MVC/Minimal API 中整合標籤失效?
- A簡: 於服務層封裝 TagCacheManager,控制器注入使用;提供管理端點發布標籤失效與觀測。
- A詳: 實作步驟: 1) 建立介面 ITagCacheManager,提供 AddWithTags、InvalidateTag;2) DI 容器註冊;3) 在 Controller/Endpoint 使用;4) 建立 /admin/cache/invalidate?tag=xxx 端點。程式碼片段: _tagCache.AddWithTags(key,value,new[]{host,scheme},sliding:TimeSpan.FromMinutes(10)); _tagCache.InvalidateTag(“funp.com”); 注意事項: 權限控管、節流、審計日誌。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q25, B-Q20, C-Q7
Q7: 如何記錄被移除項目的日誌與監控?
- A簡: 在移除回呼中記錄 key、原因與標籤上下文,輸出至日誌或監控平台,建立告警門檻。
- A詳: 實作步驟: 1) 在回呼 OnRemoved(key,val,reason) 寫入日誌;2) 加入標籤上下文(可在 value 或外部 map 保留 key→tags);3) 導出至 APM/Log 系統;4) 設定 DependencyChanged 數量的告警。程式碼片段: void OnRemoved(string key, object v, CacheItemRemovedReason r){ _logger.Info($”Removed:{key}, Reason:{r}”); } 注意事項: 回呼輕量化、避免阻塞;敏感資訊遮蔽。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q11, B-Q5, D-Q6
Q8: 如何為 TaggingCacheDependency 撰寫單元測試?
- A簡: 使用替身資料、短時效、回呼收集移除事件,對 DependencyDispose 發布後的鍵集合做斷言。
- A詳: 實作步驟: 1) 建立測試快取項目,附上不同標籤;2) 設回呼將被移除 key 加入 ConcurrentBag;3) 呼叫 DependencyDispose(“tagX”); 4) 斷言集合只包含預期鍵;5) 覆蓋多標籤、重複發布、未存在標籤等情境。程式碼片段:
var removed=new ConcurrentBag
(); Cache.Add("k1","v",new TaggingCacheDependency("t1"),..., (k,_,r)=>removed.Add(k)); TaggingCacheDependency.DependencyDispose("t1"); Assert.Contains("k1",removed); 注意: 測試隔離、重設靜態索引。 - 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q25, D-Q2, C-Q1
Q9: 如何避免索引造成記憶體洩漏?
- A簡: 通知後清理清單與字典鍵;可用弱參考存相依,或訂閱快取移除事件反向清理索引。
- A詳: 實作步驟: 1) 在 DependencyDispose 完整清理;2) 將清單類型改為 WeakReference
;3) 回呼時嘗試反向移除 key→tags 映射;4) 定期掃描失效弱參考。程式碼片段: list.RemoveAll(wr=>!wr.TryGetTarget(out _)); 注意事項: 弱參考複雜度提升;務必確保正確性與效能平衡。 - 難度: 高級
- 學習階段: 進階
- 關聯概念: B-Q10, D-Q4, C-Q1
Q10: 如何封裝 TagCacheManager 以簡化使用?
- A簡: 提供高階 API:Add(key,val,tags,…), InvalidateTag(tag),隱藏相依細節並統一日誌與觀測。
- A詳: 實作步驟: 1) 定義介面與實作;2) 內部建立 TaggingCacheDependency 並呼叫 Cache.Add;3) 實現 InvalidateTag 轉呼 DependencyDispose;4) 注入 Logger/Metric;5) 提供設定(Sliding、Priority)。程式碼片段: public void Add(string k,object v,string[] tags,TimeSpan slide)=>_cache.Add(k,v,new TaggingCacheDependency(tags),…,_onRemoved); public void InvalidateTag(string t)=>TaggingCacheDependency.DependencyDispose(t); 注意事項: 例外處理、泛型化、可測性。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: C-Q6, A-Q22, B-Q1
Q&A 類別 D: 問題解決類
Q1: 遇到快取命中率低怎麼辦?(下載範例)
- A簡: 檢查 key 唯一性與一致性、下載失敗回填、合適時效與標籤設計,避免頻繁重建與過度清理。
- A詳: 問題症狀描述: 幾乎每次都從來源下載。可能原因分析: key 不一致、下載失敗回 null、Sliding 時效太短、標籤過粗導致常被清理。解決步驟: 1) 統一 key(完整 URL);2) 正確處理失敗與重試;3) 調整 Sliding 時間;4) 細化標籤範圍。預防措施: 觀測命中率、設壓力測試與告警。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: B-Q4, A-Q17, D-Q10
Q2: 發布 DependencyDispose 但快取未被清除,怎麼診斷?
- A簡: 確認標籤字串一致、相依初始化正確、回呼是否觸發;加日誌與單元測試覆蓋關鍵路徑。
- A詳: 症狀描述: 呼叫 DependencyDispose(“tag”),項目仍存在。可能原因: 標籤大小寫/空白差異、未完成初始化(漏 FinishInit)、相依未被正確登錄、已被其他條件移除。解決步驟: 1) 比對標籤來源;2) 檢查建構子順序;3) 加回呼/日誌驗證;4) 單元測試重現。預防: 標籤規約與驗證、封裝 API 降低誤用。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q2, B-Q6, A-Q19
Q3: 多標籤項目清理不完全的原因?
- A簡: 標籤粒度或組合邏輯不當;實作為 OR,但期望 AND;需明確定義並實作匹配策略。
- A詳: 症狀描述: 發布 t1 失效,期望同時匹配 t1+t2 的才移除。可能原因: 目前為 OR 模型。解決步驟: 1) 明確需求;2) 實作 AND:相依內部維護計數器,需同時收到多事件才觸發;3) 提供新 API Invalidate(tags,Match.All)。預防: 文件化策略、測試覆蓋多組合。
- 難度: 高級
- 學習階段: 進階
- 關聯概念: B-Q8, A-Q12, C-Q5
Q4: 記憶體持續成長,懷疑索引洩漏,怎麼辦?
- A簡: 檢查是否清除清單與字典鍵;導入弱參考或定期清掃;觀測相依存活與回呼錯誤。
- A詳: 症狀描述: 長時間運行記憶體升高。可能原因: 失效後未清空清單/移除鍵、回呼異常中斷、強參考造成滯留。解決步驟: 1) 確保 DependencyDispose 清理;2) 加入 try/finally;3) WeakReference 優化;4) 監控相依量與 GC。預防: 程式碼審查、壓測、監控基線。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q10, C-Q9, B-Q11
Q5: 併發清理拋出 Collection was modified 例外,如何修復?
- A簡: 以鎖或並行集合保護讀寫;通知前快照清單,避免遍歷時集合被修改。
- A詳: 症狀描述: 失效時偶發例外。可能原因: 同時有新增/移除操作修改清單。解決步驟: 1) 對 map[tag] 的寫入與遍歷加鎖;2) 或改用 ConcurrentBag + ToArray 快照;3) 最後 TryRemove 鍵。預防: 設計併發策略、寫測試覆蓋競態。
- 難度: 高級
- 學習階段: 進階
- 關聯概念: B-Q11, C-Q4, B-Q9
Q6: 為何移除回呼沒有被觸發?
- A簡: 可能未注入回呼或被吞例外;確認 Add 參數、回呼簽名正確,並檢查日誌與原因枚舉。
- A詳: 症狀描述: 失效後無日誌。可能原因: 未提供回呼、回呼方法簽名錯誤、回呼內例外被忽略、項目早被移除。解決步驟: 1) 檢查 Add 呼叫;2) 用簡單回呼測試;3) 包裝 try-catch 記錄例外;4) 驗證項目存在。預防: 標準封裝 API、自動化測試。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q11, B-Q5, C-Q7
Q7: 重複通知導致錯誤,如何處理?
- A簡: 通知後清理索引、冪等處理;相依被處置後避免二次呼叫,必要時加狀態檢查。
- A詳: 症狀描述: 多次對同相依通知,拋 ObjectDisposed 或無效操作。可能原因: 未清空清單、重複發布。解決步驟: 1) 通知後立即清單.Clear 與 map.Remove(tag);2) 相依內部加旗標避免二次通知;3) 封裝 API 防重。預防: 測試重入情境、日誌比對。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q10, B-Q7, C-Q1
Q8: 漏呼 FinishInit 造成相依無效,怎麼排查?
- A簡: 檢查建構子初始化順序,補上 SetUtcLastModified 與 FinishInit,加入單元測試保障。
- A詳: 症狀描述: 通知後無移除效果。可能原因: 未完成初始化。解決步驟: 1) 檢視建構子;2) 加入必要呼叫;3) 建立測試覆蓋此流程。預防: 以工廠/封裝統一建立相依,避免手寫遺漏。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q6, B-Q19, A-Q9
Q9: 到期與標籤失效同時發生時如何影響行為?
- A簡: 任一條件會導致移除,實際回呼只觸發一次;原因依先後路徑而定,皆視為正常。
- A詳: 症狀描述: 近同時觸發兩種移除。可能原因: Sliding 到期點恰逢發布失效。解決步驟: 1) 接受單次回呼;2) 以日誌觀測原因分佈;3) 若需優先級,調整時效或發布時機。預防: 合理時效、避免頻繁廣播。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: B-Q15, A-Q17, A-Q10
Q10: 標籤失效導致效能抖動,如何優化?
- A簡: 控制清單長度、分批通知、離峰執行、監控回呼耗時,必要時分散式廣播降低單點壓力。
- A詳: 症狀描述: 發布失效時延遲飆升。可能原因: 單標籤綁定項目過多、回呼耗時、主線程執行。解決步驟: 1) 細化標籤或分群;2) 批次/節流通知;3) 移至背景工作;4) 監控與壓測。預防: 設計之初避免超大群組、建立運維手冊。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q13, C-Q6, A-Q22
學習路徑索引
- 初學者:建議先學習哪 15 題
- A-Q1: 什麼是 CacheDependency?
- A-Q5: 什麼是 HttpRuntime.Cache?與快取項目有何關係?
- A-Q6: 用 key 移除與用 Tagging 失效有何差異?
- A-Q3: 為什麼需要標籤式(Tagging)快取失效?
- A-Q4: 什麼是 TaggingCacheDependency?
- A-Q11: 快取移除回呼(callback)有何用途?
- A-Q10: 什麼是 CacheItemRemovedReason?
- A-Q13: 範例中為何選擇 host 與 scheme 作為標籤?
- A-Q17: 何謂時間到期與相依失效的差異?
- A-Q18: CacheItemPriority.NotRemovable 表示什麼?
- B-Q3: Cache.Add 中各參數與流程是什麼?
- B-Q4: DownloadData 方法如何配合快取運作?
- C-Q2: 如何將下載資料以 host/scheme 標籤加入快取?
- C-Q3: 如何發布標籤失效以清除一組快取?
- D-Q2: 發布 DependencyDispose 但快取未被清除,怎麼診斷?
- 中級者:建議學習哪 20 題
- A-Q7: CacheDependency 的核心價值是什麼?
- A-Q12: 標籤(tag)應如何選取與設計粒度?
- A-Q16: 本設計案例的應用場景是什麼?
- A-Q20: 相依驅動的失效與時間驅動的核心價值比較?
- B-Q1: TaggingCacheDependency 的運作機制是什麼?
- B-Q2: DependencyDispose(tag) 的執行流程為何?
- B-Q6: 自訂 CacheDependency 的初始化機制是什麼?
- B-Q7: 當呼叫 NotifyDependencyChanged 時內部會發生什麼?
- B-Q8: 多標籤登錄的內部關聯如何維護?
- B-Q9: 靜態字典在此扮演何種角色?
- B-Q13: 標籤查找效率如何影響整體效能?
- B-Q15: Absolute 與 Sliding 到期如何與相依並存?
- C-Q1: 如何實作一個最小可用的 TaggingCacheDependency?
- C-Q7: 如何記錄被移除項目的日誌與監控?
- C-Q8: 如何為 TaggingCacheDependency 撰寫單元測試?
- D-Q1: 遇到快取命中率低怎麼辦?(下載範例)
- D-Q6: 為何移除回呼沒有被觸發?
- D-Q7: 重複通知導致錯誤,如何處理?
- D-Q9: 到期與標籤失效同時發生時如何影響行為?
- A-Q25: 本案例與 ASP.NET 應用程式快取的關係?
- 高級者:建議關注哪 15 題
- B-Q11: 此實作存在哪些執行緒安全考量?
- C-Q4: 如何為標籤索引加入執行緒安全?
- C-Q5: 如何設計多層級/前綴標籤失效?
- B-Q12: 這種設計如何擴充以支援層級/前綴標籤?
- B-Q21: 自訂相依如何與多層快取(如分散式)協作?
- B-Q22: 如何設計可組合的標籤策略?
- B-Q23: 與 SqlCacheDependency 的比較與取捨?
- B-Q24: 與檔案/目錄相依的比較?
- C-Q9: 如何避免索引造成記憶體洩漏?
- C-Q10: 如何封裝 TagCacheManager 以簡化使用?
- D-Q4: 記憶體持續成長,懷疑索引洩漏,怎麼辦?
- D-Q5: 併發清理拋出 Collection was modified 例外,如何修復?
- D-Q10: 標籤失效導致效能抖動,如何優化?
- B-Q10: 為何在 DependencyDispose 後要清空清單並移除字典鍵?
- A-Q23: 這種設計的限制與風險是什麼?