Cache-Aside Pattern解析
使用这种模式,可以帮助我们维护Cache中的数据。
使用Cache容易遇到的问题:
使用缓存,主要是为了将一些重复访问的数据存到缓存,开发者希望缓存中的数据和数据源中的保持一致,这就需要程序中有相应的策略:
- 如果缓存中的数据被更新了,能尽可能快的同步到数据源中
- 如果数据源的数据被修改了,缓存的数据被更新或者删除
解决方案
一些商用的Cache会提供读穿透(read-through)和写穿透(write-through/write-behind)模式:
- 读穿透:程序尝试从缓存中读取数据,如果缓存中没有相应的数据,则会继续从数据源中读取并将其加入到缓存中
- 写穿透:如果尝试更新缓存中的数据,则后台的数据源也会被自动的更新
通过实现Cache-Aside Pattern来模拟读穿透:

当程序更新了信息后,模拟写穿透功能:
- 确保更新的数据存入到数据源中
- 将缓存中的数据标记为无效
适合使用Cache-Aside Pattern的场景:
- 缓存没有提供读穿透和写穿透功能
- 按需加载的数据不可预测
可能不适合使用Cache-Aside Pattern的场景:
- 缓存的对象是静态的(在程序启动的时候就在缓存中添加一个静态对象并长期有效)
- Web应用缓存Session状态,在这种情况下,应该避免客户端和服务器的sticky session
如果使用的Cahce没有提供这2种模式,需要我们在代码中实现,例子如下:
通过Azure Cache,我们可以创建分布式的缓存集群,这样一个应用的多个实例都可以访问。
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();
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;
}
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);
}
注意:操作的顺序很重要,一定是先更新数据源中的信息,在将Cache中的数据删除掉;如果先删除Cache的数据而后更新数据源,会有小概率发生尝试从缓存获取这个数据,因为它已经被删除掉了,而从数据源读出还没有被更新的旧数据并且将这个旧数据存放到了缓存中。
如果想使用Azure Cache的API,可以参考Using Microsoft Azure Cache
Cache-Aside Pattern解析的更多相关文章
- Cache Aside Pattern
Cache Aside Pattern 即旁路缓存是缓存方案的经验实践,这个实践又分读实践,写实践 对于读请求 先读cache,再读db 如果,cache hit,则直接返回数据 如果,cache m ...
- 缓存实践Cache Aside Pattern
Cache Aside Pattern旁路缓存,是对缓存应用的一个总结,包括读数据方案和写数据方案. 读数据方案 先读cache,如果命中则返回 如果miss则读db 将db的数据存入缓存 写数据方案 ...
- Google guava cache源码解析1--构建缓存器(1)
此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 1.guava cache 当下最常用最简单的本地缓存 线程安全的本地缓存 类似于ConcurrentHas ...
- 第二章 Google guava cache源码解析1--构建缓存器
1.guava cache 当下最常用最简单的本地缓存 线程安全的本地缓存 类似于ConcurrentHashMap(或者说成就是一个ConcurrentHashMap,只是在其上多添加了一些功能) ...
- CSAPP-Lab05 Cache Lab 深入解析
本文首发于我的知乎专栏:https://zhuanlan.zhihu.com/p/484657229 实验概览 Cache Lab 分为两部分,编写一个高速缓存模拟器以及要求优化矩阵转置的核心函数,以 ...
- Guava Cache源码解析
概述: 本次主要是分析cache的源码,基本概念官方简介即可. 基本类图: 在官方的文档说明中,Guava Cache实现了三种加载缓存的方式: LoadingCache在构建缓存的时候,使用buil ...
- Google guava cache源码解析1--构建缓存器(3)
此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 下面介绍在LocalCache(CacheBuilder, CacheLoader)中调用的一些方法: Ca ...
- Google guava cache源码解析1--构建缓存器(2)
此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. CacheBuilder-->maximumSize(long size) /** ...
- Spring Cache 源码解析
这个类实现了Spring的缓存拦截器 org.springframework.cache.interceptor.CacheInterceptor @SuppressWarnings("se ...
随机推荐
- Android:View随手指移动
View的自动移动,我们可以设置动画,如之类提到的 ViewCompat,Animation. 如何是View随着手指的移动而移动呢? 在onTouch事件实现 @Overridepublic boo ...
- 路由知识之ip route 命令中的疑惑
1.基础知识 1.1 路由 (Routing) 1.1.1 路由策略 (使用 ip rule 命令操作路由策略数据库) 基于策略的路由比传统路由在功能上更强大,使用更灵活,它使网络管理员不仅能够根据目 ...
- jquery 获取Select option 选择的Text和Value
jquery radio取值,checkbox取值,select取值,radio选中,checkbox选中,select选中,及其相关设置 获取一组radio被选中项的值:var item = $(' ...
- js call与apply方法
js中所有函数都默认定义了Call()与apply()两个方法,call与apply的第一个参数都是需要调用的函数对象,在函数体内这个参数就是this的值,剩余的参数是需要传递给函数的值,call与a ...
- mysql-异常
1.Subquery returns more than 1 row 返回的集合应该是一条才能用,但你返回了多条.
- 控件(文本类): RichTextBlock, RichTextBlockOverflow, RichEditBox
介绍背水一战 Windows 10 之 控件(文本类) RichTextBlock RichTextBlockOverflow RichEditBox 示例1.RichTextBlock 的示例Con ...
- perl 哈希 连接符
#!/usr/bin/perl -w use strict; my $test_1 = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; my $test_2 ...
- js-JavaScript高级程序设计学习笔记12
第十五章 使用canvas绘图 1.要使用<canvas>元素,必须先设置其width和height属性. 2.要在这块画布上绘图,需要先取得绘图上下文,取得绘图上下文对象的引用,需要调用 ...
- 【BZOJ-1552&3506】robotic sort&排序机械臂 Splay
1552: [Cerc2007]robotic sort Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 806 Solved: 329[Submit][ ...
- 【BZOJ-1103】大都市meg 树状数组 + DFS序
1103: [POI2007]大都市meg Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2009 Solved: 1056[Submit][Sta ...