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 ...
随机推荐
- 开发错误日记 12: Unsupported major.minor version 52.0
开发错误日记 12: Unsupported major.minor version 52.0 在编译时出现如下错误: java.lang.UnsupportedClassVersionError: ...
- safe RGB colors
RGB是面向机器的一种颜色空间. 虽然它表示\(256 \times 256 \times 256\)种不同的颜色, 但在实际中, 大部分机器都只实现了256种颜色. 安全色(Safe RGB col ...
- poj1144 求不同割点的个数
Network Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 11914 Accepted: 5519 Descript ...
- 100726A
迭代深搜,从最深的地方搜,然后一个数被搜过了,标记用过,以后不再访问 #include<iostream> #include<cstring> #include<map& ...
- sublime text 如何设置”在浏览器浏览“的快捷键
sublime text编辑器极其强大 ,但在刚开始用的时候,每次在浏览器中查看非得右键鼠标----”open in browser“,着实觉得麻烦....百度之,上面的方法有很多,但是根据我自己的经 ...
- ArrayList实现线程的几种方法
第一种.给方法名加synchronized Public synchronized void method(){ //-. } 第二种 New synchronized arraylist(); 第三 ...
- 【POJ 1789】Truck History(最小生成树)
题意:距离定义为两个字符串的不同字符的位置个数.然后求出最小生成树. #include <algorithm> #include <cstdio> #include <c ...
- 关于IOS时间日历的一些注意事项 NSDateFormatter
1.时间或者日期格式化的格式化,在真机上运行的是hi,必须指定是在哪个区域的,不然在真机无法显示 // 1.日期格式化 NSDateFormatter *fmt = [[NSDateFormatter ...
- 【BZOJ-3696】化合物 树形DP + 母函数(什么鬼)
3696: 化合物 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 165 Solved: 85[Submit][Status][Discuss] D ...
- Hadoop设置环境变量注意事项
路径是/etc/profile. 这个东西不能再普通下设置,打开是彩色的,即便是“:wq!”也不能保存,必须去root下,黑白的. 然后root下source /etc/profile,然后exit, ...