2011-12-11 63 views
62

我想使用System.Runtime.Caching命名空間將緩存功能添加到我的應用程序,並且可能希望在多個位置和不同的上下文中使用緩存。 爲此,我想使用多個MemoryCache實例。使用MemoryCache的多個實例

但是,我看到here,使用的MemoryCache的多個實例氣餒:

的MemoryCache不是單身,但你應該創建只有少數或可能只緩存的項目之一的MemoryCache實例和代碼應該使用這些實例。

多個MemoryCache實例如何影響我的應用程序? 我覺得這種奇怪,因爲在我看來,在應用程序中使用多個緩存是一種非常常見的情況。

編輯:更具體地說,我有一個類應該保持每個實例的緩存。我應該避免使用MemoryCache並尋找不同的緩存解決方案嗎?在這種情況下使用MemoryCache被認爲是不好的,如果是這樣,爲什麼?

+1

單個緩存和多個緩存之間有什麼區別?畢竟,他們都會做同樣的事情。 – spender

+9

首先,我不必擔心重要的碰撞事件。另外,我認爲它比有一個包含應用程序緩存的所有對象更有組織和更易於調試。 –

+5

這意味着您不應該創建緩存相同內容的許多緩存。一箇中央緩存儘可能緩存要好得多。但是創建緩存不同事物的許多緩存是完全正確的。 –

回答

57

我最近自己也經歷過這個。考慮到內存緩存將是特定於流程的(不是跨多個網站或本地商業應用程序或多個服務器實例共享),除了代碼組織原因(可以通過其他方式實現)之外,實際上沒有多個MemoryCache實例的益處, 。

內存緩存旨在單獨使用,主要是因爲其內存管理功能。除了性能計數器(其確實存在一些開銷)之外,MemoryCache在耗盡分配的內存時也能夠使項目過期。

如果緩存的當前實例超出內存設置限制 由CacheMemoryLimit屬性,緩存實現消除 緩存條目。應用程序中的每個緩存實例都可以使用由CacheMemoryLimit屬性指定的內存量的 。

MemoryCache.CacheMemoryLimit Property

通過使用的MemoryCache它只有一個實例可以在整個應用程序實例有效地應用這個內存管理。在整個應用程序中使最不重要的項目到期。這可確保最大限度地利用內存,而不會超出硬件功能。通過限制任何一個MemoryCache的範圍(比如一個類的一個實例),它不能再有效地管理你的應用程序的內存(因爲它不能「看到」所有東西)。如果所有這些緩存都「忙碌」,則可能難以管理內存,並且它永遠不會有效。

這對於沒有專用服務器的應用程序特別敏感。想象一下,您正在共享服務器上運行您的應用程序,而您只需分配150MB RAM(常見便宜10美元/月託管),則需要指望您的緩存使用該緩存而不超過該緩存。如果你超過了這個內存使用量,你的應用程序池將被回收,你的應用程序會丟失所有內存緩存! (常見的廉價主機實踐)這同樣適用於在某些共享企業服務器上主持的非Web應用程序。同樣的事情,你被告知不要在該機器上佔用所有內存,並與其他業務應用程序和平共處。

內存限制,應用程序池回收,丟失緩存東西是網絡應用程序常見的「致命弱點」。當應用程序是最繁忙的應用程序時,由於超出內存分配,它們會最常重置,從而丟失所有緩存條目,因此最重要的工作是重新獲取應該首先緩存的內容。這意味着應用程序實際上在最大負載下失去性能,而不是獲得性能。

我知道MemoryCache是​​System.Web.Caching.Cache實現的非web特定版本,但是這說明了緩存實現背後的邏輯。如果您沒有獨佔使用硬件,則可以在非Web項目中應用相同的邏輯。請記住,如果您的緩存強制機器開始進行頁面文件交換,那麼緩存不再比磁盤緩存更快。即使該限制是2GB或某個東西,你總是會在某個地方想要一個限制。

在閱讀完本文後,我轉而在應用程序中使用一個「公共靜態MemoryCache」,並簡單地通過它們的緩存鍵分隔了緩存項目。例如,如果要緩存每個實例,可以使用緩存鍵,如「instance- {instanceId} -resourceName- {resourceId}」。把它看作是名字間隔你的緩存條目。

希望有幫助!

+2

謝謝,那是很有幫助。不過,我並不想根據內存大小來限制緩存,但可能是通過容量限制 - 我希望每個實例都具有一定的容量,我不關心組合緩存。通過命名約定分離緩存項目對於這種情況並不好,並且似乎有點被迫。 –

+1

@AdiLester你已經知道了。理想情況下,微軟將爲他們的「MemoryCache」完成緩存「Regions」的實現,這樣你就不需要這些強制的「命名空間」鍵,並且你可以查詢任何Region中的緩存項目的數量。但目前不支持非Web緩存實現。 :-(與此同時,聽起來你知道自己的侷限性,並且對他們有好處。 – BenSwayne

+0

你能舉出一些代碼示例來解釋上述用法在單實例上的好處嗎?在這裏它會變得更有幫助和更受歡迎 –

4

我也使用了幾個。通常每個類型一個。

看着MemoryCache我看到它掛鉤到AppDomain事件並維護性能計數器。我懷疑,通過使用多於一個(例如CPU,計數器和內存),在資源方面存在一些開銷,這就是爲什麼它不受歡迎。