Skip to content

如何选择缓存的读写策略?

上一篇讲的是:

为什么需要缓存,以及缓存能解决什么问题。

这一篇开始进入缓存设计的核心:

缓存到底应该如何和数据库配合?

因为缓存最大的难题从来不是性能,而是:

数据一致性。

数据库中的数据会不断变化,而缓存中的数据是数据库的一份副本。

所以必须解决:

text
数据库更新了
缓存怎么办?

本文聚焦在:

缓存与数据库之间的几种读写模式,以及它们各自适用于什么场景。

一、缓存设计的核心矛盾

缓存系统永远面临一个矛盾:

text
性能与一致性

如果:

每次都访问数据库

text
一致性最高
性能最低

如果:

全部访问缓存

text
性能最高
一致性最差

因此:

所有缓存策略本质上都在权衡:

「性能」和「一致性」。

二、Cache Aside(旁路缓存模式)

这是互联网最主流的方案。

也是文章重点介绍的方案。

读流程

text
请求

查缓存

命中

返回

未命中

查数据库

写缓存

返回

即:

text
Cache Miss

DB

Cache

写流程

text
更新数据库

删除缓存

注意:

不是更新缓存。

而是:

删除缓存。

为什么删除而不是更新

例如:

数据库:

text
Tom

更新为:

text
Jack

如果:

text
更新数据库

更新缓存

那么:

缓存更新失败时:

text
DB = Jack
Cache = Tom

数据不一致。

而:

text
更新数据库

删除缓存

后续请求:

text
缓存失效

查数据库

重建缓存

最终一定会恢复正确。

因此:

互联网系统普遍采用:

更新数据库 + 删除缓存。

三、Read Through

另一种模式:

应用只访问缓存。

流程:

text
应用

缓存

数据库

如果缓存没有:

缓存组件自动读取数据库。

特点:

text
业务代码简单

因为:

业务层不用关心缓存失效。

但:

缓存系统需要:

  • 数据加载
  • 数据同步

实现复杂。

因此:

国内互联网公司很少采用。

四、Write Through

Write Through:

写缓存时同步写数据库。


流程:

text
应用

缓存

数据库

写操作:

text
Cache

DB

同时完成。

优点:

数据一致性较好。

缺点:

写延迟高。

因为:

每次写都必须落数据库。

所以:

性能一般。


五、Write Back(Write Behind)

这是性能最高的写策略。

流程:

text
写缓存

立即返回

异步写数据库

例如:

text
更新库存

Redis

返回成功

稍后:

text
Redis

MySQL

异步同步。

优点:

性能极高。

因为:

请求根本不用等待数据库。

六、Write Back 的风险

最大问题:

数据丢失。

例如:

text
写入Redis

还没来得及同步数据库。

Redis 崩了。

结果:

text
数据永久丢失

因此:

Write Back 通常用于:

允许少量数据丢失

例如:

  • 浏览量
  • 点赞数
  • 统计数据

不适用于:

text
订单
支付
账户余额

七、几种策略的对比

模式读性能写性能一致性复杂度
Cache Aside较好
Read Through较好
Write Through
Write Back最高最差

八、为什么互联网系统几乎都用 Cache Aside

文章重点强调:

虽然缓存策略很多。

但实际工程中:

Cache Aside 几乎是事实标准。

原因:

1. 实现简单

业务自己控制缓存逻辑。

2. 不依赖缓存产品

Redis、Memcached 都能用。

3. 数据一致性容易保证

采用:

text
更新数据库

删除缓存

即可。

4. 故障影响小

缓存挂了:

最多:

text
回源数据库

系统还能工作。

九、Cache Aside 的经典并发问题

文章专门提到:

即使采用:

text
更新数据库

删除缓存

仍然可能出现脏数据。

例如:

线程A:

text
查数据库

准备写缓存

同时:

线程B:

text
更新数据库

删除缓存

结果:

线程A又把旧数据写回缓存:

于是:

text
DB = 新值
Cache = 旧值

这就是:

缓存一致性问题。

后续章节会专门讲解决方案。

十、本章最核心的工程思想

很多人学习缓存时会陷入误区:

有没有一种策略能同时做到:

  • 极高性能
  • 强一致性
  • 零复杂度

答案是:

没有。

缓存设计本质上就是取舍。

你必须在:

text
性能
一致性
复杂度

之间平衡。

十一、本章核心脉络

text
数据库压力大

引入缓存

缓存与数据库如何同步


Cache Aside
Read Through
Write Through
Write Back



比较性能和一致性



互联网最终选择
Cache Aside

一句话总结

缓存设计的核心问题是如何在性能和一致性之间取得平衡。常见的缓存读写策略包括 Cache Aside、Read Through、Write Through 和 Write Back,其中 Cache Aside 通过“读时加载、写时更新数据库并删除缓存”的方式,在实现复杂度、性能和一致性之间取得了最佳平衡,因此成为互联网系统中最主流的缓存模式。

Released under the MIT License.