应用程序使用的快速缓存来优化反复訪问的数据存储中保持的信息。然而,它通常是不切实际的指望缓存的数据将始终与在数据存储器中的数据全然一致。应用程序要实现一种策略,有助于确保在快速缓存中的数据是最新的,仅仅要有可能,但也可以检測和处理的过程当中出现,当在快速缓存中的数据已经变得陈旧的状况。
设计模式
不少商业缓存系统提供通读和直写式/后写操做。在这些系统中,应用程序经过引用快速缓存中检索数据。假设数据不在缓存中,它被透明地从数据存储中检索并加入到快速缓存。不论什么改动在快速缓存中保持的数据被本身主动地写入到数据存储区以及。
为缓存不提供此功能,则使用该缓存保持在快速缓存中的数据的应用程序的责任。
一个应用程序可以经过实现快速缓存预留战略模拟的读式快速缓存的功能。这样的策略有效地将数据载入需求的快速缓存。图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云计算