有如下四个假设方案

  1. 先更新数据库,再更新缓存
  2. 先删除缓存,再更新数据库
  3. 先更新数据库,再删除缓存
  4. 先更新缓存,再更新数据库

方案一

先更新数据库,再更新缓存

问题: 多线程场景可能会出现缓存是旧的情况

方案二

先删除缓存,再更新数据库

可能会出现不一致的情况,如下图这种情况在第三步和第四步之间就会出现不一致的情况

解决方案: 延时双删策略

1
2
3
4
5
6
7
public void write(String key,Object data){
        redis.delKey(key);
        db.updateData(data);
        // 这个时间可以根据自己的业务调整
        Thread.sleep(1000);
        redis.delKey(key);
    }

方案三

先更新数据库,再删除缓存

有专门的名称: Cache-Aside pattern

失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中命中:应用程序从cache中取数据,取到后返回更新:先把数据存到数据库中,成功后,再让缓存失效。

方案四

先更新缓存,再更新数据库

和方案1类似的问题

总结

出现双写问题的本质原因是多线程写入顺序不可控

参考资料

Redis与Mysql双写一致性方案解析 - 知乎