这两个玩意,想保证实时性的情况下,是无法保证强一致性的,只能保证最终一致性
有几个方案,对比下,首先说一些不怎么好的方案,可以看看为什么不好,再改进
先写mysql再写redis
上图什么意思,简单来说就是两个请求都是先写mysql,再写redis,然后请求a先更新了mysql为10,然后请求b这时候更新了mysql为11。现在问题不大,但是在写redis的时候,请求a可能卡了下(网络原因或者什么的都可能),更新的时候变慢了,请求b先更新redis为11,然后请求a再更新redis为10。
那我们现在去读数据,redis中的是10,但是mysql的值已经被更新为11了。那就出现数据不一致的现象。
先写redis再写mysql
这个意思其实和上一个很像,也是一样最后redis的值和mysql的不一致。
先删除redis再写mysql
图上表示了,首先请求a删除缓存,请求b拿不到缓存,就去请求数据库,这时候数据还没被请求a更新为11,所以会先查到10,然后再回写10到缓存中去。
然后有几个比较好的
先删除redis,再写mysql,再删除redis
这个方案基于上一个进行修改,可以用缓存双删来实现,不过也有个问题,你怎么保证双删的时候一定在回写之前呢,如果在之后的话不就很尴尬。或许我们可以让第二次删除延迟一会再执行,但是也无法完全保证,所以还是不太行哈哈
先写mysql再删除redis
上图中,请求a先更新mysql为11,请求b第一次查询是查不到11这个值的,因为我们还没更新最新的值到mysql。这个方案能保证最终一致性,而且比较简单,但是也有个问题就是第一次查询查到的值是不对的,如果对于正常的系统来说是没关系的,因为只要回写之后就可以,毕竟db的数据是正确的,但是对于一些秒杀服务还是不行。
先写mysql,再通过binlog,异步更新redis
这个方案其实和上一个差不多,也是在如果写到redis这段时间有请求来查的话,会查到不一样的数据。所以也只是保证了最终一致性。
综上,个人感觉先写mysql再删除redis的方案最合适也是比较常用的。而先写mysql再写redis的话,如果并发不高,也是可以用的。