Cache-Aside

该模式是从数据仓库中将数据加载到缓存中,从而提高访问速度的一种模式。该模式可以有效的提高性能,同时也能一定程度上保证缓存中的数据和数据仓库中的数据的一致性,和同步数据到数据仓库中。

问题

应用通过缓存来优化针对数据仓库的重复访问。当然,令缓存中的数据永远和数据仓库中数据保持一致是不切实际的。应用中的缓存应该事先一些策略来辅助更新缓存保证数据的一致,当然,也需要检测数据过期等情况来进行一定的处理。

解决方案

很多商业化的缓存系统都提供read-through和write-through/write-behind的操作。在这些系统中应用从缓存的引用中获得数据。如果数据不再缓存中,请求将透过缓存到数据仓库来获取数据,然后将数据写入到缓存中。任何对缓存中的数据的修改,在之后也会写会到数据仓库之中。

对于那些不提供这个功能的缓存系统,就轮到应用来自己将数据保持在缓存之中了。

应用可以通过实现Cache-Aside策略来实现read-through的功能。这个策略会根据需要来从数据仓库获取数据。下图则是Cache-Aside模式的基本运行方式:

  1. 判断读取的项目是否在缓存中
  2. 如果项目不再缓存中,从数据仓库中将数据读出来
  3. 将新的项目写入缓存

如果应用不是读取信息而是更新信息,它可以模仿write-through的策略:

  1. 将信息的更新同步到数据仓库
  2. 令缓存中关联的过期数据失效

当这个数据在下一次需要的时候,使用Cache-Aside模式将会在获取数据的时候,同时从数据仓库中获取数据,并且写到Cache之中。

需要考虑的问题

当在实现如下模式的时候,需要考虑一些问题:

  1. 缓存数据的生存时间:很多Cache实现了过期的策略的,这些过期的策略可以实现数据的更新,将旧数据失效化,同事也令一定时间没有访问的数据失效。为了让Cache-Aside模式能够生效,开发者必须确保过期策略能够正确匹配应用所访问的数据。同时注意不能让过期时间太短,因为太短的过期时间会令应用频繁的从数据仓库中来获取数据来添加到Cache之中。当然,也不要配置超时的时间太长,过长的超时时间会让缓存的数据荣誉。Cache的性能是跟其相关的数据的读取周期等信息高度相关的。
  2. 去除数据:绝大多数的缓存跟数据仓库比起来,容量是很有限的,所以,如果可以的话,Cache会移除数据。多数的Cache会采用LRU的策略来移除缓存中的数据,当然,移除的策略也是可以自定义的。配置全局的过期属性和缓存的其他属性,可以确保Cache消耗的内存资源是搞笑的。当然,通常不会只配置一个全局的过期策略,。举例来说,不同的缓存从数据仓库中获取资源很昂贵的时候而经常访问的话。
  3. 准备Cache:很多的解决方案会多数情况在应用启动的过程中,就将数据仓库中的数据写入到缓存之中。Cache-Aside模式就算在一些数据过期或者移除的情况下仍然很多时候是很有用的。
  4. 一致性:实现Cache-Aside模式并不能保证Cache和数据仓库之间的数据一致性。因为数据仓库中的数据可能在任何的时候都可能由其他程序锁修改,而这个修改不会及时的反映到Cache上,只有在下一次Cache从数据仓库中更新数据的时候才会有解决这个数据不一致的问题。如果数据仓库中数据频繁由非Cahce程序更新的话,这种问题同步问题hi变得更加明显。
  5. 本地(内存)缓存:Cache也是可以做到应用本身里面的。Cache-Aside模式在一些应用频繁访问相同的数据的时候尤其有效。然而,本地Cache都是应用私有的,是属于每个应用中独有的额外的拷贝。所以这个数据可能很快在不同的应用中就不一致了,所以刷新的频率最好更快来保证一致。在有些情况下可以使用共享的缓存,有的时候也可以使用本地Cache,具体使用哪一种就需要根据实际的场景来判断。

什么时候使用Cache-Aside模式

什么时候使用:

  • 当Cache不提供原生的Read-Through和Write-Through操作的时候
  • 资源的需求是不可预测的时候。Cache-Aside模式令应用可以根据需求来加载数据。对于应用需求什么数据,不需要提前做出假设。

代码举例

在Windows Azure中开发者可以使用Windows Azure Cache来创建一个分布式的由多个应用实例共享的缓存。下面代码中的GetMyEntityAsync方法的实现就是一个基于Windows Azure Cache的Cache-Aside模式的实现。这个方法通过Read-Through的方式从缓存中获取数据。

一个对象通过一个整数ID作为Key来限定。GetMyEntityAsync方法根据这个key生成了一个字符串Key(Windows Azure Cache API是通过字符串来作为Key值的),然后尝试通过这个缓存来获取对应的对象。如果找到了匹配条目,那么就直接返回匹配条目,如果缓存中没有匹配条目,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;
}

上面的例子使用了 Windows Azure Cache的API来访问数据仓库和从Cache中获取数据。想了解更多关于Windows Azure Cache API的信息,可以参考MSDN上面的使用Windows Azure 缓存

下面展示的UpdateEntityAsync方法展示了如何令应用修改缓存的数据失效的。这也是Write-Through方法的一个举例。其中的代码会更新数据仓库,然后通过调用Remove方法来移除数据仓库中的数据。

注意:在下面的一些操作的顺序是十分重要的。如果缓存先被移除了,然后缓存才更新的话,客户端在获取数据的时候会有一定的概率

直接从数据仓库里面获取还没有更新的过期数据。

//C#
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);
}

Cache-Aside模式的更多相关文章

  1. 十二:SpringBoot-基于Cache注解模式,管理Redis缓存

    SpringBoot-基于Cache注解模式,管理Redis缓存 1.Cache缓存简介 2.核心API说明 3.SpringBoot整合Cache 3.1 核心依赖 3.2 Cache缓存配置 3. ...

  2. SpringBoot2.0 基础案例(13):基于Cache注解模式,管理Redis缓存

    本文源码 GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base 一.Cache缓存简介 从Spring3开始定义Cache和Cac ...

  3. 《JavaScript模式》第4章 函数

    @by Ruth92(转载请注明出处) 第4章:函数 一.JavaScript 中函数的两个重要特征 函数是第一类对象,可以作为带有属性和方法的值以及参数进行传递: 函数提供了局部作用域,而其他大括号 ...

  4. Cache的原理、设计及实现

    Cache的原理.设计及实现 前言 虽然CPU主频的提升会带动系统性能的改善,但系统性能的提高不仅仅取决于CPU,还与系统架构.指令结构.信息在各个部件之间的传送速度及存储部件的存取速度等因素有关,特 ...

  5. oracle 11g 之 result cache

    oracle 11g 之 result cache 今天是2013-10-12,打算最近时间研究一下shared pool的相关原理以及awr报告分析.今天学习一下在oracle 11g shared ...

  6. [z]计算机架构中Cache的原理、设计及实现

    前言 虽然CPU主频的提升会带动系统性能的改善,但系统性能的提高不仅仅取决于CPU,还与系统架构.指令结构.信息在各个部件之间的传送速度及存储部件的存取速度等因素有关,特别是与CPU/内存之间的存取速 ...

  7. 记一个bootloader的cache问题

    问题背景 最近往一个armv7板子的bootloader中移植了解压算法,移植本身还比较顺利,但移植完了发现,功能是正常的,但效率大打折扣.解压同样的数据,耗时大约是uboot的10倍. 初步定位 从 ...

  8. Spring Cache Redis结合遇到的坑

    业务上需要把一些数据放到redis里面,但是系统逻辑代码差不多编写完成了,怎么整?用Spring Cache啊,对既有业务逻辑侵袭极小. 于是尝试调查了一下,遇到一些问题分享一下(本文使用Spring ...

  9. 11g新特性-查询缓存(1)

    众所周知,访问内存比访问硬盘快得多,除非硬盘体系发生革命性的改变.可以说缓存在Oracle里面无处不在,结果集缓存(Result Cache)是Oracle Database 11g新引入的功能,引入 ...

  10. GPS部标平台的架构设计(九)-GPS监控客户端设计

    交通部的部标过检,所有的测试都是从客户端发起的,也是在客户端体现的,在客户端承载了部标标准所要求的所有的功能,是整个部标平台当中工作量最大的部分,也是最繁琐的部分. 客户端设计面临两个问题: 1.基于 ...

随机推荐

  1. cgic程序的编写遇到的问题

    cgic程序的编写 今天使用cgic库编写了一些cgi的代码,结果在编译的时候出了很多错误,在这里分享出来算是给自己做个笔记,虽然都是小问题但是急需解决的时候还是很麻烦的. 代码结构: login_c ...

  2. PhoneGap 介绍

    一.PhoneGap 是什么 1.PhoneGap 是一个用基于 HTML,CSS 和 JavaScript 的,创建移动跨平台移动应用程序的快速开发框架. 2.它使开发者能够利用 iPhone,An ...

  3. 使用tidylib解决不规则网页问题

    windows 下安装tidylib 先去https://pypi.python.org/pypi/pytidylib 下载pytidylib 跑官方提供的测试用例报错 ition 0: unexpe ...

  4. Nginx之动静分离

    为什么要动静分离呢? 拿Nginx来说,Nginx是Web服务器,仅仅只能处理静态资源(例如js,img,css等等),而Tomcat属于应用服务器既能处理静态资源又能处理动态资源(例如jsp,fre ...

  5. Dubbo实践(二)架构

    架构 节点角色说明 节点 角色说明 Provider 暴露服务的服务提供方 Consumer 调用远程服务的服务消费方 Registry 服务注册与发现的注册中心 Monitor 统计服务的调用次数和 ...

  6. PAT——1060. 爱丁顿数

    英国天文学家爱丁顿很喜欢骑车.据说他为了炫耀自己的骑车功力,还定义了一个“爱丁顿数”E,即满足有E天骑车超过E英里的最大整数E.据说爱丁顿自己的E等于87. 现给定某人N天的骑车距离,请你算出对应的爱 ...

  7. 使用Fiddler监控来自手机客户端的请求

    环境配置组成: 1 手机 2 安装Fiddler的PC 设置要点: 1 手机和PC应在同一个局域网内 我的做法是:PC安装WIFI热点,手机连接热点上网 PC的IP是192.168.95.1  手机的 ...

  8. 使用mongodb提供的dotnet core sdk进行地理位置运算

    mongodb提供地理位置运算功能,比较常用的场景比如,先判断用户所在的街道,然后看看街道附近有啥餐厅,然后算算用户与餐厅的距离什么的,官网里提供了比较详细的demo介绍不同api的用法 此处记录下d ...

  9. XAMPP启动mysql问题

    Problem detected!21:57:44 [mysql] Port 3306 in use by ""E:\MySQL\bin\mysqld" --defaul ...

  10. 分布式架构学习-Consul集群配置

    简介 之前公司用的是Consul进行服务发现以及服务管理,自己一直以来只是用一下,但是没有具体的深入,觉得学习不可以这样,所以稍微研究了一下. 网上有很多关于Consul的介绍和对比,我这里也不献丑了 ...