Cache Aside Pattern
Cache Aside Pattern 即旁路缓存是缓存方案的经验实践,这个实践又分读实践,写实践
对于读请求
先读cache,再读db
如果,cache hit,则直接返回数据
如果,cache miss,则访问db,并将数据set回缓存

如上图:
(1)先从cache中尝试get数据,结果miss了
(2)再从db中读取数据,从库,读写分离
(3)最后把数据set回cache,方便下次读命中
对于写请求
淘汰缓存,而不是更新缓存
先操作数据库,再淘汰缓存
如上图:
(1)第一步要操作数据库,第二步操作缓存
(2)缓存,采用delete淘汰,而不是set更新
Cache Aside Pattern为什么建议淘汰缓存,而不是更新缓存?如果更新缓存,在并发写时,可能出现数据不一致。

如上图所示,如果采用set缓存。
在1和2两个并发写发生时,由于无法保证时序,此时不管先操作缓存还是先操作数据库,都可能出现:
(1)请求1先操作数据库,请求2后操作数据库
(2)请求2先set了缓存,请求1后set了缓存
导致,数据库与缓存之间的数据不一致。
所以,Cache Aside Pattern建议,delete缓存,而不是set缓存。
Cache Aside Pattern为什么建议先操作数据库,再操作缓存?
如果先操作缓存,在读写并发时,可能出现数据不一致。

如上图所示,如果先操作缓存。
在1和2并发读写发生时,由于无法保证时序,可能出现:
(1)1.1 写请求淘汰了缓存
(2)1.2 写请求操作了数据库(主从同步没有完成)
(3)2.1 读请求读了缓存(cache miss)
(4)2.2 读请求读了从库(读了一个旧数据)
(5)2.3 读请求set回缓存(set了一个旧数据)
(6)1.3 数据库主从同步完成
导致,数据库与缓存的数据不一致。
所以,Cache Aside Pattern建议,先操作数据库,再操作缓存。
先操作数据库再操作缓存, 在读写并发时,也可能出现数据不一致。
如上图所示,如果先操作数据库。
(1)1.1 读请求读了缓存(cache miss)
(2)1.2 读请求读了从库(读了一个旧数据)
(3)2.1 写请求操作了数据库
(4)2.2 写请求淘汰缓存(cache miss 淘汰跟没淘汰一样)
(5)1.3 读请求set回缓存(set了一个旧数据)
(6)2.3 数据库主从同步完成
导致,数据库与缓存的数据不一致
但是:先淘汰缓存再更新数据库方案中,写请求 淘汰缓存后 被 读请求 set回一个旧数据,这种并发出现的几率很大。 而: 先更新数据库再淘汰缓存方案中,读请求 在写请求之前读了数据且data miss,又要在写请求之后set缓存, 这种几率很小。 所以:Cache Aside Pattern建议,先操作数据库,再操作缓存。
Cache Aside Pattern方案存在什么问题?
答:如果先操作数据库,再淘汰缓存,在原子性被破坏时:
(1)修改数据库成功了
(2)淘汰缓存失败了
导致,数据库与缓存的数据不一致。
参考:58沈剑 架构师之路
Cache Aside Pattern的更多相关文章
- 缓存实践Cache Aside Pattern
Cache Aside Pattern旁路缓存,是对缓存应用的一个总结,包括读数据方案和写数据方案. 读数据方案 先读cache,如果命中则返回 如果miss则读db 将db的数据存入缓存 写数据方案 ...
- 别再犯低级错误,带你了解更新缓存的四种Desigh Pattern
在我们使用分布式缓存Redis或者Memcached编写更新缓存数据代码时,我们总是会犯一个逻辑错误.先删除缓存,然后再更新数据库,而后续的操作会把数据再装载的缓存中.试想,两个并发操作,一个是更新操 ...
- cache and database
This article referenced from http://coolshell.cn/articles/17416.html We all know that high concurren ...
- [Java复习] 缓存Cache part2
7. Redis持久化有哪几种方式?不同的持久化机制都有什么优缺点?持久化机制具体底层是如何实现的? 为什么要持久化? 如果只是存在内存里,如果redis宕机再重启,内存数据就丢失了,所以要用持久化机 ...
- 缓存模式(Cache Aside、Read Through、Write Through、Write Behind)
目录 概览 Cache-Aside 读操作 更新操作 缓存失效 缓存更新 Read-Through Write-Through Write-Behind 总结 参考 概览 缓存是一个有着更快的查询速度 ...
- Tomcat源码分析——SERVER.XML文件的加载与解析
前言 作为Java程序员,对于Tomcat的server.xml想必都不陌生.本文基于Tomcat7.0的Java源码,对server.xml文件是如何加载和解析的进行分析. 加载 server.xm ...
- Memcache(1)
一.缓存套路 原文地址:http://coolshell.cn/articles/17416.html Scaling Memcached at Facebook 好些人在写更新缓存数据代码时,先删除 ...
- 面试前必须要知道的Redis面试题
前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 回顾前面: 从零单排学Redis[青铜] 从零单排学 ...
- redis缓存雪崩、缓存穿透、数据库和redis数据一致性
一.缓存雪崩 回顾一下我们为什么要用缓存(Redis):减轻数据库压力或尽可能少的访问数据库. 在前面学习我们都知道Redis不可能把所有的数据都缓存起来(内存昂贵且有限),所以Redis需要对数据设 ...
随机推荐
- 遍历文件路径python版,java版
python: # 获取所有txt路径列表 file_list = [] def gci(filepath): files=os.listdir(filepath) for fi in files: ...
- UOJ#55. 【WC2014】紫荆花之恋 点分树 替罪羊树 平衡树 splay Treap
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ55.html 题解 做法还是挺容易想到的. 但是写的话…… 首先这种题如果只要求一棵树中的满足条件的点数( ...
- JWT( JSON Web Token)
参考 https://laravelacademy.org/post/9469.html 三部分组成,头部.载荷与签名 头部 把下面的基本信息base64 加密生成头部信息 { "typ& ...
- 删除jar包
public class TestDelete { private static List<File> files = new ArrayList(); public static voi ...
- C#堆和栈
一.在讲堆栈之前,我们先看看值类型和引用类型: 1,我们看看值类型与引用类型的存储方式: 引用类型:引用类型存储在堆中.类型实例化的时候,会在堆中开辟一部分空间存储类的实例.类对象的引用还是存储在栈中 ...
- webpack打包后该如何访问项目?
一.问题描述 开发环境,页面浏览都OK,产出文件后,直接打开产出目录的index.html,页面空白. 二.预期结果 能正常看到页面. 三.问题分析 你可能会在编译的最后看到如下一句话: Tip: b ...
- bat入门--第一个bat文件
所谓的批处理就是从记事本开始进行的. 1.新建一个记事本文件, 2, 打开的记事本上敲入一行字:@echo off 意思:隐藏以下输入的代码(off改成on是打开代码显示). 3.再输入:echo h ...
- 阿里云 Windows 2012 如果安装IIS
用可视化安装如果出错, 那就用 windows powershell 安装 https://help.aliyun.com/knowledge_detail/40959.html?spm=5176.1 ...
- Mybatis_1(认识)一个简单的HelloWorld
1. 介绍: MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架. MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索. MyBatis可以使用简单的XM ...
- [LeetCode] Minimum Swaps To Make Sequences Increasing 使得序列递增的最小交换
We have two integer sequences A and B of the same non-zero length. We are allowed to swap elements A ...