说明:
(1)本篇博客内容:介绍了数据库和缓存双写数据不一致的问题;然后,介绍了一种缓存双删的解决方案;这是一种,保证MySQL和Redis数据最终一致性的方案;
(2)本篇博客的第五部分,梳理了本篇博客逻辑,十分重要;
目录
一:本篇博客合理性说明;
二:双写数据不一致,简介;
由于分布性系统,不能保证每个节点都可用,所有可能引起redis在极限情况下数据没有写入成功。那么此时缓存中的数据和数据库数据不一致。
(1)我们有数据库和Redis,一开始时,数据库和Redis中是一致的,里面都有一个{name:imooc}这个数据;
(2)此时,用户发起了一个新的请求,这个请求是要修改name这个数据,将其更改为{name:muke};
(3)那么,在修改的时候,用户首先是把数据更新到数据库;然后,要把新的数据更新到Redis中;
(4)但是,Redis有可能(虽然这个可能性很低)发生一些网络故障,导致{name:muke}这个新数据,没有写入到Redis中;那么,在用户这次请求结束后,数据库中的数据是{name:muke},但是Redis中的数据还是旧的{name:imooc};
(5)于是,当下一次请求过来,想要查询name数据的时候,由于Redis中已经有name这个数据了,所以其会从Redis中拿;然后,其拿的就是旧的{name:imooc}了;这就是数据库、Redis双写数据不一致的情况;
……………………………………………………
(6)针对上面的这种情况,我们是可以解决的;
三:缓存数据双写一致,简介;
(1)双写一致是什么;
什么是双写一致,我们来看如下图:
用户请求到后端,执行数据保存到数据库,没毛病,接下来需要把数据在其他的数据服务中同时进行保存,常见的保存到Redis,es或者mongodb。
那么正由于分布式系统,每个节点相互独立,就有可能造成在数据库写完之后,后续的写操作无法执行,或者发生异常中断,或者网络延时问题,这么一来,读取的数据在数据库里是新的,而redis/es/mongo中是老的或者没有,这样显然数据就造成了不一致。(一般以Redis为例,结合数据库使用的场景是最多的)
(2)DB + Redis 使用场景
一般来说,数据库和redis结合以后的常见使用方式如下:
1.新增数据到数据库,此时redis中还没有数据
2.读取数据,如果缓存没有,则从db中读取,然后同时存入redis,如果redis有数据,直接返回
3.更新数据,先从缓存中删除,随后更新数据库,后续读取重复步骤2
……………………………………………………
那么问题来了,为啥要先从redis中把数据删除,然后再更新数据库,最后再写入redis呢?为何不直接更新redis?我们先来看如下图: