# 云計算設計模式(一)——緩存預留模式
緩存預留模式是根據需求從數據存儲緩存加載數據。這種模式可以提高性能,并有助于維持在基礎數據存儲在高速緩存中保持的數據和數據之間的一致性。
## 背景和問題
應用程序使用的高速緩存來優化重復訪問的數據存儲中保持的信息。然而,它通常是不切實際的期望緩存的數據將始終與在數據存儲器中的數據完全一致。應用程序要實現一種策略,有助于確保在高速緩存中的數據是最新的,只要有可能,但也可以檢測和處理的過程中出現,當在高速緩存中的數據已經變得陳舊的情況。
## 解決方案
許多商業緩存系統提供通讀和直寫式/后寫操作。在這些系統中,應用程序通過引用高速緩存中檢索數據。如果數據不在緩存中,它被透明地從數據存儲中檢索并添加到高速緩存。任何修改在高速緩存中保持的數據被自動地寫入到數據存儲區以及。
為緩存不提供此功能,則使用該緩存保持在高速緩存中的數據的應用程序的責任。
一個應用程序可以通過實現高速緩存預留戰略模擬的讀式高速緩存的功能。這種策略有效地將數據加載需求的高速緩存。圖 1 總結了在該過程中的步驟。

圖1 - 使用Cache-除了圖案來將數據存儲在高速緩沖存儲器
如果一個應用程序將更新的信息,它可以模擬通寫策略如下:
- 根據修改到數據存儲
- 作廢對應的項在緩存中。
當該項目被下一個需要,可使用高速緩存預留策略將導致從數據存儲中檢索和重新添加到高速緩存中的更新數據。
### 問題和注意事項
在決定如何實現這個模式時,請考慮以下幾點:
- 緩存數據的生命周期。很多緩存實現一個過期策略,導致數據無效,并從緩存中移除如果它不是在指定時間內訪問。對于緩存一邊是有效的,確保了過期策略相匹配的訪問用于使用數據的應用程序的模式。不要使有效期限太短,因為這會導致應用程序不斷地從數據存儲中檢索數據,并將其添加到緩存中。同樣,不要使保質期這么久,緩存的數據很可能會變得陳舊。記住,緩存是最有效的相對靜態的數據,或者數據被頻繁地讀出。
- 驅逐數據。最高速緩存具有比從其中數據源自數據存儲區只有有限的大小,并在必要時它們將收回的數據。大多數緩存采用最近最少使用的政策選擇項目驅逐,但是這可能是定制的。配置全局到期屬性和高速緩存的其它性能,并且每個高速緩存項的到期屬性,以幫助確保緩存成本效益。它可能并不總是適合于高速緩存中的應用全球驅逐政策,每一個項目。例如,如果緩存項是非常昂貴的,從數據存儲中檢索,也可能是有益的,保留在更頻繁地訪問但不昂貴的物品的費用此產品的高速緩存中。
- 灌注緩存。許多解決方案,預填充用的應用程序可能需要作為啟動處理的一部分的數據的高速緩存。如果某些數據已到期,被驅逐的緩存,除了圖案可能仍然是有用的。
- 一致性。執行緩存除了圖案不保證數據存儲和高速緩存之間的一致性。在數據存儲中的項目可以在任何時候被改變由外部的過程中,這種變化可能不反映在高速緩存中的項目被裝載到高速緩存,直到下一次。在一個系統,整個數據存儲復制數據,如果同步發生非常頻繁這個問題可能會變得尤為突出。
- 本地(內存)緩存。緩存可以是本地的應用程序實例,并存儲在內存中。緩存預留如果應用程序多次訪問相同的數據可以在該環境中是有用的。然而,本地高速緩存是私有的,因此不同的應用程序實例可各自具有相同的緩存數據的副本。此數據可能很快變成高速緩存之間不一致,所以它可能有必要在到期專用高速緩存中保存的數據和更經常地刷新。在這些場景中它可能是適當的,調查使用了共享或分布式緩存機制。
## 當使用這個模式
使用這種模式時:
- 緩存不提供原生讀通過,并通過寫操作。
- 資源的需求是不可預測的。這種模式使應用程序能夠按需加載數據。它使任何假設有關的數據的應用程序將需要提前。
這種模式可能不適合:
- 當緩存的數據集是靜態的。如果數據將適合可用的高速緩存空間,首要的高速緩存中的數據在啟動和應用,防止數據從止政策。
- 對于托管在 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);
}
~~~
- 前言
- (一)—— 緩存預留模式
- (二)—— 斷路器模式
- (三)—— 補償交易模式
- (四)——消費者的競爭模式
- (五)——計算資源整合模式
- (六)——命令和查詢職責分離(CQRS)模式
- (七)——事件獲取模式
- (八)——外部配置存儲模式
- (九)—— 聯合身份模式
- (十)——守門員模式
- (十一)—— 健康端點監控模式
- (十二)—— 索引表模式
- (十三)——領導人選舉模式
- (十四)——實體化視圖模式
- (十五)—— 管道和過濾器模式
- (十六)——優先級隊列模式
- (十七)—— 基于隊列的負載均衡模式
- (十八)—— 重試模式
- (十九)——運行重構模式
- (二十)—— 調度程序代理管理者模式
- (二十一)——Sharding 分片模式
- (二十二)——靜態內容托管模式
- (二十三)——Throttling 節流模式
- (二十四)—— 仆人鍵模式