Redis与Mysql双写一致性
Posted 冬日寻雾记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis与Mysql双写一致性相关的知识,希望对你有一定的参考价值。
双写一致性时为了保证Redis缓存与MySQL数据库中的数据一样
我们对Redis中没有的数据,MySQL怎么回写呢?
我们用 双检加锁策略
这样只要第一个请求发过来,后面的请求就不会发送到MySQL,直接从Redis中获取缓存数据就可以了。
为了保证这种一致性,有三种方案
- 1. 先更新数据库,再更新缓存
- 2. 先删除缓存,再更新数据库
- 3. 先更新数据库,再删除缓存
(1)先更新数据库,再更新缓存
原因一(线程安全角度) 同时有请求A和请求B进行更新操作,那么会出现
- (1)线程A更新了数据库
- (2)线程B更新了数据库
- (3)线程B更新了缓存
- (4)线程A更新了缓存
2)先删缓存,再更新数据库
该方案会导致不一致的原因是。同时有一个请求A进行更新操作,另一个请求B进行查询操作。那么会出现如下情形:
- (1)请求A进行写操作,删除缓存
- (2)请求B查询发现缓存不存在
- (3)请求B去数据库查询得到旧值
- (4)请求B将旧值写入缓存
- (5)请求A将新值写入数据库 上述情况就会导致不一致的情形出现。而且,如果不采用给缓存设置过期时间策略,该数据永远都是脏数据。
那么,如何解决呢?采用延时双删策略 伪代码如下
public void write(String key,Object data) redis.delKey(key); db.updateData(data); Thread.sleep(1000); redis.delKey(key);
这种方法会有什么问题呢?
第二次删除失败,就会出现如下情形。还是有两个请求,一个请求A进行更新操作,另一个请求B进行查询操作,为了方便,假设是单库:
- (1)请求A进行写操作,删除缓存
- (2)请求B查询发现缓存不存在
- (3)请求B去数据库查询得到旧值
- (4)请求B将旧值写入缓存
- (5)请求A将新值写入数据库
- (6)请求A试图去删除请求B写入对缓存值,结果失败了。
(3)先更新数据库,再删缓存
那么怎么知道mysql有更新呢?
我们可以用canal
以上是关于Redis与Mysql双写一致性的主要内容,如果未能解决你的问题,请参考以下文章