Cloud Design Pattern - Cache Aside Pattern(缓存模式)

1.开篇

运行在云中的应用和运行在本地的应用由于环境的不同,通常会带来一些差异,最常见的差异就是性能.安全性要求也比本地应用要高一些,并且由于运行在云端,系统之间的交互更加频繁了,消息队列也被列入系统架构需要考虑的清单之中,并且还需要考虑第三方接入的认证机制.诸如此类的不同,带来的是更多新的思考,如何设计出适应云环境的应用,是一个亟待思考的命题,微软的Design Pattern团队专门针对云计算设计模式推出了Cloud Design Pattern最佳实践,帮助云计算开发更好地设计云计算应用,下面就详细介绍下微软所推荐的最佳实践,欢迎大家一起学习交流.

2.简介

这一章节的主题是缓存.缓存最大的好处是提升性能,但缓存也是一把双刃剑,使用不当则后患无穷. 那么微软为什么要推荐缓存作为云计算的首要最佳实践呢?我想应该与云环境的网络延迟有关.网络延迟的弊端几乎是无法克服的,属于"外部不可抗因素",使用缓存就十分有必须要了,一方面必须要使用,一方面缓存使用不当则会出问题,那么我们该坚持什么样的原则来使用缓存呢?答案是按需加载和维护缓存与数据源的一致性!.微软推荐的缓存模式就是基于这两个原则来设计的.

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.

应用程序使用缓存来提升从数据源重复读取数据的性能,然而,缓存中的数据和数据源并非总是一致的.应用程序必须实现一种帮助确保缓存和数据源一致的策略,这种策略不仅能够确保缓存里面的数据是最新的,而且当缓存中的数据不是最新的时候,需要能够监测到并且采取相应的措施.

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.
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.

很多商用的缓存系统提供了read-through和write-through/write-behind的机制.在这样的系统中,应用从缓存中获取数据,当数据在缓存中不存在的时候,从数据源中读取,并且加入到缓存中,对缓存中的数据的修改会立即同步 到数据源中.在没有提供这种机制的缓存系统中,应用程序需要维护缓存中的数据和数据源中的数据的关系.可以通过自己实现缓存策略来达到相同的目的.

使用缓存设计模式需要考虑以下几个方面:

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.
代码示例:

数据查询时

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;
}
数据保存时

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);
}
Windows Azure 缓存服务就是这种缓存机制的最佳实践.

关于Windows Azure Caching的使用,请参考MSDN上关于Windows Azure Caching的使用博客.

https://msdn.microsoft.com/library/azure/hh914165.aspx

更多相关的话题:

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.





  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值