阅读:        作者:迪克猪

Cache-AsidePattern(缓存模式)

    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.

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

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.

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

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.

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

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.

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

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.

如果一个应用程序更新信息,它可以通过如下策略来实现:

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

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.
     

在实施该模式时,以下模式和指导也可能是相关的:

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

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

Tags: 缓存   模式   SID   Pattern   pat