雲計算設計模式(一)——緩存預留模式

緩存預留模式

緩存預留模式是根據需求從數據存儲緩存加載數據。這種模式能夠提升性能,並有助於維持在基礎數據存儲在高速緩存中保持的數據和數據之間的一致性。緩存

背景和問題

應用程序使用的高速緩存來優化重複訪問的數據存儲中保持的信息。然而,它一般是不切實際的指望緩存的數據將始終與在數據存儲器中的數據徹底一致。應用程序要實現一種策略,有助於確保在高速緩存中的數據是最新的,只要有可能,但也能夠檢測和處理的過程當中出現,當在高速緩存中的數據已經變得陳舊的狀況。服務器

解決方案

許多商業緩存系統提供通讀和直寫式/後寫操做。在這些系統中,應用程序經過引用高速緩存中檢索數據。若是數據不在緩存中,它被透明地從數據存儲中檢索並添加到高速緩存。任何修改在高速緩存中保持的數據被自動地寫入到數據存儲區以及。async

爲緩存不提供此功能,則使用該緩存保持在高速緩存中的數據的應用程序的責任。分佈式

一個應用程序能夠經過實現高速緩存預留戰略模擬的讀式高速緩存的功能。這種策略有效地將數據加載需求的高速緩存。圖 1 總結了在該過程當中的步驟。性能

圖1 - 使用Cache-除了圖案來將數據存儲在高速緩衝存儲器優化

若是一個應用程序將更新的信息,它能夠模擬通寫策略以下:this

  • 根據修改到數據存儲
  • 做廢對應的項在緩存中。

當該項目被下一個須要,可以使用高速緩存預留策略將致使從數據存儲中檢索和從新添加到高速緩存中的更新數據。spa

問題和注意事項

在決定如何實現這個模式時,請考慮如下幾點:rest

  • 緩存數據的生命週期。不少緩存實現一個過時策略,致使數據無效,並從緩存中移除若是它不是在指定時間內訪問。對於緩存一邊是有效的,確保了過時策略相匹配的訪問用於使用數據的應用程序的模式。不要使有效期限過短,由於這會致使應用程序不斷地從數據存儲中檢索數據,並將其添加到緩存中。一樣,不要使保質期這麼久,緩存的數據極可能會變得陳舊。記住,緩存是最有效的相對靜態的數據,或者數據被頻繁地讀出。
  • 驅逐數據。最高速緩存具備比從其中數據源自數據存儲區只有有限的大小,並在必要時它們將收回的數據。大多數緩存採用最近最少使用的政策選擇項目驅逐,可是這多是定製的。配置全局到期屬性和高速緩存的其它性能,而且每一個高速緩存項的到期屬性,以幫助確保緩存成本效益。它可能並不老是適合於高速緩存中的應用全球驅逐政策,每個項目。例如,若是緩存項是很是昂貴的,從數據存儲中檢索,也多是有益的,保留在更頻繁地訪問但不昂貴的物品的費用此產品的高速緩存中。
  • 灌注緩存。許多解決方案,預填充用的應用程序可能須要做爲啓動處理的一部分的數據的高速緩存。若是某些數據已到期,被驅逐的緩存,除了圖案可能仍然是有用的。
  • 一致性。執行緩存除了圖案不保證數據存儲和高速緩存之間的一致性。在數據存儲中的項目能夠在任什麼時候候被改變由外部的過程當中,這種變化可能不反映在高速緩存中的項目被裝載到高速緩存,直到下一次。在一個系統,整個數據存儲複製數據,若是同步發生很是頻繁這個問題可能會變得尤其突出。
  • 本地(內存)緩存。緩存能夠是本地的應用程序實例,並存儲在內存中。緩存預留若是應用程序屢次訪問相同的數據能夠在該環境中是有用的。然而,本地高速緩存是私有的,所以不一樣的應用程序實例可各自具備相同的緩存數據的副本。此數據可能很快變成高速緩存之間不一致,因此它可能有必要在到期專用高速緩存中保存的數據和更常常地刷新。在這些場景中它多是適當的,調查使用了共享或分佈式緩存機制。

當使用這個模式

使用這種模式時:code

  • 緩存不提供原生讀經過,並經過寫操做。
  • 資源的需求是不可預測的。這種模式使應用程序可以按需加載數據。它使任何假設有關的數據的應用程序將須要提早。

這種模式可能不適合:

  • 當緩存的數據集是靜態的。若是數據將適合可用的高速緩存空間,首要的高速緩存中的數據在啓動和應用,防止數據從止政策。
  • 對於託管在 Web 場中的 Web 應用程序緩存會話狀態信息。在這種環境下,你應該避免引入基於客戶端 - 服務器關係的依賴。

例子

在微軟的 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 方法,指定鍵(這部分功能的代碼已經被省略了,由於這將是數據存儲相關)從緩存中刪除緩存項。

注意

在這個序列中的步驟的次序是重要的。若是以前的緩存更新的項被刪除,對於客戶端應用程序中的數據存儲中的項目以前獲取的數據(由於它沒有在高速緩存中發現的)的機會已經改變一個小窗口,從而在緩存包含過時數據。

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); } 
相關文章
相關標籤/搜索