缓存旁路模式

【博文目录>>>】


缓存旁路模式

根据需要从数据存储区将数据加载到缓存中。这种模式可以提高性能,并有助于保持缓存中的数据与基础数据存储中的数据之间的一致性。

语境与问题

应用程序使用缓存优化对数据存储中保存的信息的重复访问。然而,期望缓存的数据始终与数据存储中的数据完全一致是不切实际的。应用程序应该实现一种策略,以帮助确保缓存中的数据尽可能地更新,但也可以检测和处理缓存中的数据已经过时时出现的情况。

解决方案

许多商业缓存系统提供通读和写/写操作。在这些系统中,应用程序通过引用缓存来检索数据。如果数据不在缓存中,则从数据存储中透明地检索数据并添加到缓存中。对缓存中保存的数据的任何修改也会自动写回数据存储区。

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

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YsdlnnN4-1581213417456)(quiver-image-url/55B56FD8930E405C5BF9580E455A16C1.png “Figure 1 - Using the Cache-Aside pattern to store data in the cache”)]

图1-使用缓存备用模式将数据存储在缓存中

如果应用程序更新信息,它可以按照以下方式模拟写入策略:

  1. 对数据存储进行修改
  2. 使缓存中的相应项无效。

当下一次需要读取数据项时,使用缓存备用策略将导致从数据存储中检索更新的数据并将其添加回缓存中。

问题和思考

在决定如何实现此模式时,请考虑以下几点:

  • 缓存数据的生存期。许多缓存实现了过期策略,如果数据在指定的时间段内未被访问,则导致数据失效并从缓存中删除。若要使缓存备用有效,请确保过期策略与使用数据的应用程序的访问模式相匹配。不要使过期时间太短,因为这会导致应用程序不断地从数据存储中检索数据并将其添加到缓存中。同样,不要使过期时间太长以至于缓存的数据可能会过时。请记住,缓存对于相对静态的数据或频繁读取的数据最有效。
  • 驱逐数据。与数据来源的数据存储区相比,大多数缓存只有有限的大小,如果有必要,它们将删除数据。大多数缓存采用最近使用最少的策略来选择要驱逐的数据项,但这可能是可定制的。配置缓存的全局过期属性和其他属性以及每个缓存项的过期属性,以帮助确保缓存具有成本效益。对缓存中的每个项应用全局驱逐策略并不总是合适的。例如,如果从数据存储中检索缓存项非常昂贵,则在缓存中保留此项可能有益于牺牲更频繁地访问但成本较低的项。
  • 启动缓存。许多解决方案将缓存预先填充到应用程序可能需要的数据,作为启动处理的一部分。如果其中一些数据过期或被逐出,缓存旁路模式可能仍然有用。
  • 一致性。实现缓存旁路模式并不能保证数据存储和缓存之间的一致性。数据存储中的项可能在任何时候由外部进程更改,而且在下次将该项加载到缓存之前,此更改可能不会反映在缓存中。在跨数据存储复制数据的系统中,如果同步频繁发生,则此问题可能变得特别严重。
  • 本地(内存中)缓存。缓存可以是应用程序实例的本地缓存,并存储在内存中。如果应用程序重复访问相同的数据,则缓存旁路在此环境中可能非常有用。但是,本地缓存是私有的,因此不同的应用程序实例都可以拥有相同缓存数据的副本。这些数据在缓存之间可能很快变得不一致,因此可能需要将保存在私有缓存中的数据过期并更频繁地刷新它。在这些场景中,研究共享或分布式缓存机制的使用可能是合适的。

何时使用此模式

在下列情况下使用此模式:

  • 缓存不提供本机通读通写操作.
  • 资源需求是不可预测的。此模式使应用程序能够按需加载数据。它不会预先假设应用程序需要哪些数据。

这种模式可能不合适:

  • 当缓存的数据集是静态的时。如果数据将适合可用的缓存空间,则在启动时将缓存与数据放在一起,并应用防止数据过期的策略。
  • 用于缓存托管在Web场中的web应用程序中的会话状态信息。在这种环境中,您应该避免引入基于客户机-服务器关联的依赖关系。

例子

在MicrosoftAzure中,您可以使用AzureCache创建一个分布式缓存,该缓存可以由应用程序的多个实例共享。GetMyEntityAsync方法在下面的代码示例中展示了基于Azure Cache的缓存旁路模式的实现。此方法使用通读方法从缓存中检索对象。

对象通过使用整数ID作为键来标识。GetMyEntityAsync方法根据此键(Azure Cache 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 Cache API访问存储并从缓存中检索信息。有关Azure Cache API的更多信息,请参见在MSDN上使用Microsoft Azure Cache

UpdateEntityAsync方法演示如何在应用程序更改值时使缓存中的对象失效。这是一个通写方法的例子.代码更新原始数据存储区,然后通过调用移除方法,指定键(这部分功能的代码已被省略,因为它将依赖于数据存储)。

这个顺序中步骤的顺序很重要。如果在更新缓存之前删除该项,则在数据存储中的项更改之前,客户端应用程序有一个很小的机会窗口来获取数据(因为在缓存中找不到它),从而导致缓存中包含陈旧的数据。

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

相关模式和指导

在实施这一模式时,下列模式和指导也可能相关:

  • 缓存指导。本指南提供了关于如何在云解决方案中缓存数据以及在实现缓存时应考虑的问题的其他信息。
  • 数据一致性原则。云应用程序通常使用分散在数据存储中的数据。在此环境中管理和维护数据一致性可以成为系统的一个关键方面,特别是在可能出现的并发性和可用性问题方面。本文入门描述了围绕分布式数据的一致性问题,并总结了应用程序如何实现最终的一致性以维护数据的可用性。

原文链接

https://docs.microsoft.com/en-us/previous-versions/msp-n-p/dn589799%28v%3dpandp.10%29

相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页