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双写一致性的主要内容,如果未能解决你的问题,请参考以下文章

Redis与MySQL双写一致性如何保证?

美团二面:Redis与MySQL双写一致性如何保证?

美团二面:Redis与MySQL双写一致性如何保证?

美团二面:Redis与MySQL双写一致性如何保证?

美团二面:Redis与MySQL双写一致性如何保证?

美团二面:Redis与MySQL双写一致性如何保证?