暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

如何保证数据库和缓存的一致性

不高兴就喝水 2021-06-16
1220

缓存的用法

在项目中我们经常用缓存来缓解数据库的压力,像这样:


那我们怎么保证缓存与数据库中数据的一致性呢?接下来让我们来探讨一下。

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


可以看到本来请求B是最后更新缓存的,但是请求A明显处理的更慢,所以请求A更新了最后的缓存。这就导致数据库和缓存中的数据不一致情况发生了。

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

当然,这样也会有问题。如图:



但是数据库查询的执行速度肯定是远快于写入操作,所以存在脏数据的可能性几乎为0。当然您肯定会问,要是真的发生了怎么办呀?

easy,双删就行了,即第一次删除缓存之后,等待一段时间重新再删一次。

哈哈哈,还有一种情况,删除缓存这一步失败了怎么办?

那么可以搭配消息队列食用,删除缓存失败的数据放入消息队列进行重复删除。

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


这次A请求先删除缓存,数据库还没有更新成功,此时如果B请求查询缓存,发现缓存不存在,便去数据库中查询,这时候查询到的却是旧值,然后将旧值更新到缓存,缓存不一致情况又发生了。

延时双删

其实上面的问题可以用延时双删的方案来解决,解决思路是:A请求更新完数据库之后,装睡一段时间,然后再次删除缓存。

不过装睡的时间要以业务读写缓存的时间为参照,也就是装睡时间要大于读写缓存的时间。

具体流程如下:


1.A请求删除缓存,然后更新数据库

    2.此时B请求来查询缓存,发现缓存已经被删除,所以直接从数据库中读取,这时候由于A请求还没有更新数据库,所以B请求拿到的是旧值,直接把旧值写入缓存        3.A请求根据业务估算的读写时间sleep一段时间,由于sleep的时间大于B请求读数据和写缓存的时间,所以缓存被再次删除       4.如果这时候有其他请求来读取缓存的话,就会去从数据库中读取到最新值了

其他的解决方案

设置缓存过期时间

每次放入缓存的时候设置一个过期时间,比如5分钟,以后的操作只修改数据库,不操作缓存,等待缓存超时后从数据库重新读取。

如果对于缓存和数据库数据一致性要求不是很高的情况,可以采用这种最终一致性方案。

总结

通过上面的几个例子,我们发现缓存应该做删除,而不应该去更新它。

为什么呢?我们用先更新数据库,再更新缓存举例:

如果数据库1小时内更新了1000次,那么缓存也要更新1000次,但是这个缓存可能在1小时内只被读取了1次,那么这1000次的更新有必要吗?

反过来如果是删除的话,就算数据库更新了1000次,那么也只是做了1次缓存删除,只有当缓存真正被读取的时候才去数据库读取。

其实针对缓存一致性要求不是很高的场景,通过设置缓存超时时间就可以,直接躺平。


文章转载自不高兴就喝水,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论