Redis缓存一致性问题

缓存模型、问题、做法

Redis最常用的用法:用作缓存,因为Redis是内存型的,速度比关系型数据库快,所以在设计一些热点、频率较高的接口的时候,会考虑缓存,会在MySQL前面搭一层Redis,查询MySQL前会先查Redis。

这样引发的问题是:并发环境下,如果MySQL数据发生变更,Redis缓存如何处理?

做法:先更新数据库,再删缓存(Cache-Aside pattern)

1、失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。

2、命中:应用程序从cache中取数据,取到后返回。

3、更新:先把数据存到数据库中,成功后,再让缓存失效。

几个讨论点

1、保持缓存一致性,有很多做法。我的理解是:缓存是数据库的外层,要保障一致性,对缓存的操作在前就行了,类似于栈。所以更新数据时,先锁数据库,删除缓存,再更新数据库,释放锁。

2、为什么是删除,而不是更新缓存?

我们以先更新数据库,再删除缓存来举例。

举个例子:如果数据库1小时内更新了100次,那么缓存也要更新100次,但这个缓存可能在1小时内只被读取了1次,那么这100次的更新是没有必要的。

反过来,如果是删除的话,数据库更新了100次,缓存删除也就只有1次。Redis DEL 命令用于删除已存在的键。不存在的 key 会被忽略。

3、我在网上的技术文章里面,看到了太多复制粘贴的文章,关于缓存一致性问题就有很多奇思妙想,比如延迟双删(主动sleep),这种就很奇怪,在接口里面主动sleep也是少见,而且在没有任何业务前提下设计方案也显得太粗暴和不专业了。

还有引入了MQ或者MySQL的 binlog同步来通知,就一带而过说用这个方案,也是离谱,引入了额外的实体,会带来额外的问题,谨记【如无必要,勿增实体】