應用程序使用的快速緩存來優化反覆訪問的數據存儲中保持的信息。然而,它通常是不切實際的指望緩存的數據將始終與在數據存儲器中的數據全然一致。應用程序要實現一種策略,有助於確保在快速緩存中的數據是最新的,僅僅要有可能,但也可以檢測和處理的過程當中出現,當在快速緩存中的數據已經變得陳舊的狀況。
設計模式
不少商業緩存系統提供通讀和直寫式/後寫操做。在這些系統中,應用程序經過引用快速緩存中檢索數據。假設數據不在緩存中,它被透明地從數據存儲中檢索並加入到快速緩存。不論什麼改動在快速緩存中保持的數據被本身主動地寫入到數據存儲區以及。
爲緩存不提供此功能,則使用該緩存保持在快速緩存中的數據的應用程序的責任。
一個應用程序可以經過實現快速緩存預留戰略模擬的讀式快速緩存的功能。這樣的策略有效地將數據載入需求的快速緩存。圖1總結了在該過程中的步驟。緩存
圖1 - 使用Cache-除了圖案來將數據存儲在快速緩衝存儲器
假設一個應用程序將更新的信息,它可以模擬通寫策略例如如下:
1.依據改動到數據存儲
2.做廢相應的項在緩存中。
當該項目被下一個需要,可以使用快速緩存預留策略將致使從數據存儲中檢索和又一次加入到快速緩存中的更新數據。 async
在決定怎樣實現這個模式時,請考慮下面幾點:
•緩存數據的生命週期。很是多緩存實現一個過時策略,致使數據無效,並從緩存中移除假設它不是在指定時間內訪問。對於緩存一邊是有效的,確保了過時策略相匹配的訪問用於使用數據的應用程序的模式。不要使有效期限過短,因爲這會致使應用程序不斷地從數據存儲中檢索數據,並將其加入到緩存中。相同,不要使保質期這麼久,緩存的數據很是可能會變得陳舊。記住,緩存是最有效的相對靜態的數據,或者數據被頻繁地讀出。
•驅趕數據。最快速緩存具備比從當中數據源自數據存儲區僅僅有有限的大小,並在必要時它們將收回的數據。大多數緩存採用近期最少使用的政策選擇項目驅趕,但是這多是定製的。配置全局到期屬性和快速緩存的其餘性能,並且每一個快速緩存項的到期屬性,以幫助確保緩存成本效益。它可能並不老是適合於快速緩存中的應用全球驅趕政策,每一個項目。好比,假設緩存項是很昂貴的,從數據存儲中檢索,也多是故意的,保留在更頻繁地訪問但不昂貴的物品的費用此產品的快速緩存中。
•灌注緩存。不少解決方式,預填充用的應用程序可能需要做爲啓動處理的一部分的數據的快速緩存。假設某些數據已到期,被驅趕的緩存,除了圖案可能仍然是實用的。
•一致性。運行緩存除了圖案不保證數據存儲和快速緩存之間的一致性。在數據存儲中的項目可以在不論何時被改變由外部的過程當中,這樣的變化可能不反映在快速緩存中的項目被裝載到快速緩存,直到下一次。在一個系統,整個數據存儲複製數據,假設同步發生很頻繁這個問題可能會變得尤其突出。
•本地(內存)緩存。緩存可以是本地的應用程序實例,並存儲在內存中。緩存預留假設應用程序屢次訪問一樣的數據可以在該環境中是實用的。然而,本地快速緩存是私有的,所以不一樣的應用程序實例可各自具備一樣的緩存數據的副本。此數據可能很是快變成快速緩存之間不一致,因此它可能有必要在到期專用快速緩存中保存的數據和更經常地刷新。在這些場景中它多是適當的,調查使用了共享或分佈式緩存機制。
分佈式
使用這樣的模式時:
•緩存不提供原生讀經過,並經過寫操做。
•資源的需求是不可預測的。這樣的模式使應用程序能夠按需載入數據。它使不論什麼若是有關的數據的應用程序將需要提早。
這樣的模式可能不適合:
•當緩存的數據集是靜態的。假設數據將適合可用的快速緩存空間,首要的快速緩存中的數據在啓動和應用,防止數據從止政策。
•對於託管在Web場中的Web應用程序緩存會話狀態信息。在這樣的環境下,你應該避免引入基於client - server關係的依賴。
性能
在微軟的Azure,您可以使用Azure的緩存來建立一個分佈式緩存,可以經過一個應用程序的多個實例可以共享。如下的代碼演示樣例中的GetMyEntityAsync方法給出了基於Azure的緩存Cache後備模式的實現。此方法從利用讀儘管方法緩存中的對象。
一個目的是肯定用一個整數ID做爲鍵。該GetMyEntityAsync方法生成基於此鍵(在Azure緩存API使用的鍵值字符串)的字符串值,並嘗試檢索與從緩存中這一關鍵的項目。假設匹配的項目被發現,它被返回。假設在緩存中沒有匹配,則GetMyEntityAsync方法從一個數據存儲中的對象時,把它加入到緩存中,而後將其返回(即實際上得到從數據存儲中的數據的代碼已經被省略,因爲它是數據存儲依賴)。注意,緩存項被配置以防止其成爲陳舊假設是在別處更新過時。優化
private DataCache cache; ... public async Task<MyEntity> GetMyEntityAsync(int id) { // Define a unique key for this method and its parameters. var key = string.Format("StoreWithCache_GetAsync_{0}", id); var expiration = TimeSpan.FromMinutes(3); bool cacheException = false; try { // Try to get the entity from the cache. var cacheItem = cache.GetCacheItem(key); if (cacheItem != null) { return cacheItem.Value as MyEntity; } } catch (DataCacheException) { // If there is a cache related issue, raise an exception // and avoid using the cache for the rest of the call. cacheException = true; } // If there is a cache miss, get the entity from the original store and cache it. // Code has been omitted because it is data store dependent. var entity = ...; if (!cacheException) { try { // Avoid caching a null value. if (entity != null) { // Put the item in the cache with a custom expiration time that // depends on how critical it might be to have stale data. cache.Put(key, entity, timeout: expiration); } } catch (DataCacheException) { // If there is a cache related issue, ignore it // and just return the entity. } } return entity; }
注意:
該演示樣例使用了Azure的緩存API來訪問存儲和檢索的緩存信息。有關Azure的緩存API的不少其它信息,請參閱MSDN上使用微軟的Azure緩存。
如下所看到的的UpdateEntityAsync方法說明怎樣在快速緩存中的對象無效,當該值是由應用程序改變。這是一個寫通方法的實例。該代碼更新原始數據存儲,而後經過調用Remove方法,指定鍵(這部分功能的代碼已經被省略了,因爲這將是數據存儲相關)從緩存中刪除緩存項。
注意:
在這個序列中的步驟的次序是重要的。假設以前的緩存更新的項被刪除,對於client應用程序中的數據存儲中的項目以前獲取的數據(因爲它沒有在快速緩存中發現的)的機會已經改變一個小窗體,從而在緩存包括過時數據。this
public async Task UpdateEntityAsync(MyEntity entity) { // Update the object in the original data store await this.store.UpdateEntityAsync(entity).ConfigureAwait(false); // Get the correct key for the cached object. var key = this.GetAsyncCacheKey(entity.Id); // Then, invalidate the current cache object this.cache.Remove(key); } private string GetAsyncCacheKey(int objectId) { return string.Format("StoreWithCache_GetAsync_{0}", objectId); }
本文翻譯自MSDN:http://msdn.microsoft.com/en-us/library/dn589799.aspx雲計算