缓存一致性问题
分享汇总 : 文章汇总
本文应该是关于缓存一致性的系列文章,每篇会讨论一个策略,持续更新中
前情提要
最近我提前去公司入职实习了,发现公司项目中大量用到了 MySQL + Redis 这一堆存储组合。因为实际上 MySQL 作为主要的存储, Redis 作为缓存,如果有一个请求过来,请求会首先在 Redis 中搜索结果,如果 Redis 中找到了,那实际上就不会去 MySQL 中再查询了,这样就帮 MySQL 抵挡住了一定的请求。但是这样就会带来缓存不一致的问题,缓存不一致指的是 Redis 中存储的数据和 MySQL 中存储的数据不一致(CPU 也有 Cache 缓存,可以参考那个缓存不一致的概念)
其实处理缓存一致性问题,业界是有几种方案的,本文会先介绍 Read/Write Through 方案
Read/Write Through
-
Read Through
Read Through 是应对读操作的策略,如果有一个读操作
- 如果请求命中缓存,则直接返回结果
-
如果未命中,则从 MySQL 中查询数据,然后将数据写入 Redis 并返回数据
-
Write Through
Write Through 是应对写删除更新等操作的策略,如果有一个此类型请求
- 如果缓存命中,则更新 Redis,然后更新 MySQL
- 如果没命中,则直接更新 MySQL
图示
缺点
本方案还是有一些问题的主要是在并发的情况下,会出现读脏数据的问题
情况一
假如有 A,B 两个请求, A 是读请求,B 是写请求
如果此时,时间线是这样的
- A 缓存未命中,从 MySQL 中读出数据
- B 缓存未命中,直接更改 MySQL,注意此时 MySQL 中的是新数据,和 A 持有的数据发生了不一致
- A 将持有的旧数据写入 Redis,并返回, 此时 Redis 中 缓存的是旧数据,而 MySQL 中存储的是新数据
情况二
假如有 A B C两个请求, A,B 是读请求,C 是写请求。
如果此时,时间线是这样的
- A, B 首先查询缓存,都没命中
- A,B 都从 MySQL 中读取数据
- A 首先将 MySQL 中读出来的数据写入了 Redis
- C 先后更新了缓存和数据
- 然后 A 现在持有的是 MySQL 中旧的数据,此时 A 会将旧数据写入 MySQL
- A, B 请求返回数据