Cache-Aside Pattern(缓存模式)

    Load data on demand into a cache from a data store. This pattern can improve performance and also helps to maintain consistency between data held in the cache and the data in the underlying data store.ios

    从数据存储区加载到缓存中的数据。这种模式能够提升性能,也有助于保持在缓存中的数据之间的一致性和底层数据存储的数据。web

Context and Problem 背景与问题

Applications use a cache to optimize repeated access to information held in a data store. However, it is usually impractical to expect that cached data will always be completely consistent with the data in the data store. Applications should implement a strategy that helps to ensure that the data in the cache is up to date as far as possible, but can also detect and handle situations that arise when the data in the cache has become stale.windows

应用程序使用缓存来优化重复访问数据存储区中的信息。然而,一般是不切实际的指望,缓存的数据将永远是彻底一致的数据存储在数据存储。应用程序应该实现一个策略,以确保在缓存中的数据尽量尽量的日期,但也能够检测和处理的状况下,当缓存中的数据已成为过期。缓存

Solution 解决方案

Many commercial caching systems provide read-through and write-through/write-behind operations. In these systems, an application retrieves data by referencing the cache. If the data is not in the cache, it is transparently retrieved from the data store and added to the cache. Any modifications to data held in the cache are automatically written back to the data store as well.服务器

许多商业高速缓存系统提供read-through write-through/write-behind 等操做。在这些系统中,应用程序经过引用缓存来检索数据。若是数据不在缓存中,则从数据存储区中检索到缓存,并添加到缓存中。在缓存中保存的数据的任何修改都会自动返回到数据存储区中。网络

For caches that do not provide this functionality, it is the responsibility of the applications that use the cache to maintain the data in the cache.session

对于不提供此功能的缓存,应用程序的责任是使用缓存来维护缓存中的数据的。并发

An application can emulate the functionality of read-through caching by implementing the cache-aside strategy. This strategy effectively loads data into the cache on demand. Figure 1 summarizes the steps in this process.app

应用程序能够经过缓存策略来模拟读取缓存的功能。这个策略有效地将数据加载到缓存中的需求。图1总结了这个过程当中的步骤。less

Figure 1 - Using the Cache-Aside pattern to store data in the cache

图1 -使用高速缓存模式来存储缓存中的数据

If an application updates information, it can emulate the write-through strategy as follows:
     1.Make the modification to the data store
     2.Invalidate the corresponding item in the cache.

若是一个应用程序更新信息,它能够经过以下策略来实现:

一、修改的数据保存到数据区,

2,使缓存区的对应项无效。

When the item is next required, using the cache-aside strategy will cause the updated data to be retrieved from the data store and added back into the cache.

当该项是下一个须要时,使用缓存策略将致使更新的数据从数据存储中检索,并将其添加到缓存中。

问题和注意事项

Consider the following points when deciding how to implement this pattern:

在决定如何实现这个模式时,考虑如下几点:

Lifetime of Cached Data:Many caches implement an expiration policy that causes data to be invalidated and removed from the cache if it is not accessed for a specified period. For cache-aside to be effective, ensure that the expiration policy matches the pattern of access for applications that use the data. Do not make the expiration period too short because this can cause applications to continually retrieve data from the data store and add it to the cache. Similarly, do not make the expiration period so long that the cached data is likely to become stale. Remember that caching is most effective for relatively static data, or data that is read frequently.

缓存数据的生命周期:许多的缓存实现过时策略致使数据失效并从缓存中移除若是不在指定时间内访问。为了缓存到缓存中的有效性,确保过时策略匹配使用数据的应用程序的访问模式。不要使过时时间过短,由于这可能致使应用程序不断地从数据存储中检索数据,并将其添加到缓存中。一样,不要使过时时间过长,缓存的数据可能会变得不新鲜。请记住,缓存是最有效的相对静态的数据,或是常常读的数据。

Evicting Data: Most caches have only a limited size compared to the data store from where the data originates, and they will evict data if necessary. Most caches adopt a least-recently-used policy for selecting items to evict, but this may be customizable. Configure the global expiration property and other properties of the cache, and the expiration property of each cached item, to help ensure that the cache is cost effective. It may not always be appropriate to apply a global eviction policy to every item in the cache. For example, if a cached item is very expensive to retrieve from the data store, it may be beneficial to retain this item in cache at the expense of more frequently accessed but less costly items.

清除数据:大多数缓存具备一个规模有限的数据存储区,而且是认为是必要的数据。大多数缓存采用最近最少使用策略来清除项,但这是能够定制的。配置缓存的全局过时属性和其余属性,以及每一个缓存项目的过时属性,以帮助确保缓存的成本有效。它可能并不老是适合于全球驱逐政策的每一项在缓存。例如,若是一个缓存的项目是很是昂贵的,从数据存储检索,它多是有益的保留此项目在高速缓存中的费用更频繁访问,但成本较低的项目。

Priming the Cache:Many solutions prepopulate the cache with the data that an application is likely to need as part of the startup processing. The Cache-Aside pattern may still be useful if some of this data expires or is evicted.

启动缓存:许多方案预填充缓存,应用程序可能须要在启动处理部分的数据。缓存模式还能够一边若是这部分数据过时或是有用的是驱逐。

Consistency:Implementing the Cache-Aside pattern does not guarantee consistency between the data store and the cache. An item in the data store may be changed at any time by an external process, and this change might not be reflected in the cache until the next time the item is loaded into the cache. In a system that replicates data across data stores, this problem may become especially acute if synchronization occurs very frequently.

一致性:在缓存中,不保证数据存储和缓存的一致性。在数据存储区中的一个项目能够在任什么时候间被外部过程改变,而在下一次将该项加载到缓存中时,这种变化可能不会反映到缓存中。在整个数据存储区复制数据的系统中,若是发生频繁发生,这个问题可能会变得特别严重。

Local (In-Memory) Caching: A cache could be local to an application instance and stored in-memory. Cache-aside can be useful in this environment if an application repeatedly accesses the same data. However, a local cache is private and so different application instances could each have a copy of the same cached data. This data could quickly become inconsistent between caches, so it may be necessary to expire data held in a private cache and refresh it more frequently. In these scenarios it may be appropriate to investigate the use of a shared or a distributed caching mechanism.

本地(内存)缓存:缓存能够是本地的一个应用实例,并存储在内存中。若是一个应用程序反复访问相同的数据,缓存能够在该环境中有用。然而,本地缓存是私有的,因此不一样的应用实例能够有一个相同的缓存数据的副本。此数据可能会迅速成为不一致的高速缓存,所以它多是必要的过时数据举行的私人缓存和刷新它更频繁。在这些状况下,它多是适当的调查使用的共享或分布式缓存机制。

When to Use this Pattern 何时使用这种模式

Use this pattern when:
     •A cache does not provide native read-through and write-through operations.
     •Resource demand is unpredictable. This pattern enables applications to load data on demand. It makes no assumptions about which data an application will require in advance.

使用此模式时:

•缓存不提供本地读写操做,并经过操做。

•资源需求是不可预测的。这种模式使应用程序的负载数据的需求。它不假设数据的应用程序将须要提早。

This pattern might not be suitable:
     •When the cached data set is static. If the data will fit into the available cache space, prime the cache with the data on startup and apply a policy that prevents the data from expiring.
     •For caching session state information in a web application hosted in a web farm. In this environment, you should avoid introducing dependencies based on client-server affinity.

这种模式可能不适合:

当缓存的数据集是静态的。若是数据将融入现有的缓存空间,主要的缓存启动数据和应用的政策,防止数据失效。

在一个网络应用程序中的一个网络应用程序中缓存会话状态信息。在这种环境中,您应该避免引入基于客户机-服务器亲和力的依赖关系。

Example 例子

In Microsoft Azure you can use Azure Cache to create a distributed cache that can be shared by multiple instances of an application. The GetMyEntityAsync method in the following code example shows an implementation of the Cache-aside pattern based on Azure Cache. This method retrieves an object from the cache using the read-though approach.

在Microsoft Azure下,你可使用Azure Cache来建立一个分布式缓存,能够共享的应用程序的多个实例。下面的代码示例中的GetMyEntityAsync方法显示缓存基于Azure Cache的实现。此方法从缓存中检索一个对象。

An object is identified by using an integer ID as the key. The GetMyEntityAsync method generates a string value based on this key (the Azure Cache API uses strings for key values) and attempts to retrieve an item with this key from the cache. If a matching item is found, it is returned. If there is no match in the cache, the GetMyEntityAsync method retrieves the object from a data store, adds it to the cache, and then returns it (the code that actually retrieves the data from the data store has been omitted because it is data store dependent). Note that the cached item is configured to expire in order to prevent it from becoming stale if it is updated elsewhere.

一个对象是经过使用一个整数ID做为key。GetMyEntityAsync 方法生成一个字符串值做为key(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;
}

Note:

The examples use the Azure Cache API to access the store and retrieve information from the cache. For more information about the Azure Cache API, see Using Microsoft Azure Cache on MSDN.

The UpdateEntityAsync method shown below demonstrates how to invalidate an object in the cache when the value is changed by the application. This is an example of a write-through approach. The code updates the original data store and then removes the cached item from the cache by calling the Remove method, specifying the key (the code for this part of the functionality has been omitted as it will be data store dependent).

下面的UpdateEntityAsync方法演示了如何使一个对象在缓存中无效,当应用程序的值改变时。这是一个用写方法的例子。代码更新原始数据存储,而后经过调用删除方法删除缓存项目,指定密钥(此部分的功能的代码已被省略,由于它将数据存储依赖)。

Note:

The order of the steps in this sequence is important. If the item is removed before the cache is updated, there is a small window of opportunity for a client application to fetch the data (because it is not found in the cache) before the item in the data store has been changed, resulting in the cache containing stale data.

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);
}

Related Patterns and Guidance 相关模式和指导

The following patterns and guidance may also be relevant when implementing this pattern:

  • Caching Guidance. This guidance provides additional information on how you can cache data in a cloud solution, and the issues that you should consider when you implement a cache.
  • Data Consistency Primer. Cloud applications typically use data that is dispersed across data stores. Managing and maintaining data consistency in this environment can become a critical aspect of the system, particularly in terms of the concurrency and availability issues that can arise. This primer describes the issues surrounding consistency across distributed data, and summarizes how an application can implement eventual consistency to maintain the availability of data.
     

在实施该模式时,如下模式和指导也多是相关的:

缓存指南。本指南提供了关于如何在云解决方案中缓存数据的附加信息,以及在执行缓存时要考虑的问题。

数据一致性。云应用程序一般使用的数据是分散在数据存储。在这个环境中管理和维护数据的一致性可能成为系统的一个重要方面,特别是在并发性和可用性问题方面可能出现的问题。该引物描述了整个分布式数据的一致性问题,并总结了如何应用程序能够实现最终的一致性,以保持数据的可用性。

相关文章
相关标签/搜索