新入职的同事问我,为什么会出现数据库和缓存不一致的问题?

Hollis

共 1933字,需浏览 4分钟

 · 2022-05-10

△Hollis, 一个对Coding有着独特追求的人△
这是Hollis的第 392 篇原创分享
作者 l Hollis
来源 l Hollis(ID:hollischuang)
Hollis的新书限时折扣中,一本深入讲解Java基础的干货笔记!
关于缓存,相信很多人都不陌生,我们通常会在数据库之上搭建一个缓存服务器,将一些高频的数据存储到缓存中,可以提升查询效率,从而提高响应速度以及并发度。


但是,与此同时也带来了一个问题,那就是如何保证缓存和数据库之间的数据一致性?


在讨论怎么做之前,我们先来看看为什么会出现缓存一致性的问题呢?这些问题是如何发生的呢?



非并发的情况

首先,我们在非并发的场景中,出现不一致的问题大家都能比较容易的理解,因为缓存的操作和数据库的操作是存在一定的时间差的


而且这两个操作是没办法保证原子性的,也就是说,是有可能一个操作成功,一个操作失败的。


所以,这就必然会存在不一致的情况。


但同时,因为我们的业务系统是开放给用户使用的,所以经常会出现各种各样的并发的场景,因为并发的存在,会使得数据一致性的问题更加的多。



并发的情况


对于数据的操作,无外乎就是读和写两种,那么就会同时存在"读读并发"、"读写并发"和"写写并发"。


对于两个读线程,即使发生并发,因为只是读的动作,所以不会有数据的变更,发生了并发的话也不会有数据不一致的情况。


接下来我们先来分析比较容易理解的"写写并发"的情况。


   写写并发

因为在数据库和缓存的操作过程中,可能存在"先写数据库,后删缓存"、"先写数据库,后更新缓存"、"先删缓存库,后写数据库"以及"先更新缓存库,后写数据库"这四种。


其中"删缓存"的这两种是把缓存清空,所以"写写并发"不会存在缓存和数据库不一致的情况。我们就看"更新缓存"的这两种:


先写数据库,后更新缓存:

  

                

先更新缓存,后写数据库:



以上两种情况,都是两个写线程并发之后,因为乱序的问题,导致最终缓存中的值是20,而数据库中的值是10,最终导致缓存和数据库中的值不一致的情况。


除了写写并发之外,还有一种比较容易被忽视的情况,那就是读写之间的并发也会导致数据库和缓存的不一致。


 读写并发

我们知道,当我们使用了缓存之后,一个读的线程在查询数据的过程是这样的:


1、查询缓存,如果缓存中有值,则直接返回 

2、查询数据库 

3、把数据库的查询结果更新到缓存中


所以,对于一个读线程来说,虽然不会写数据库,但是是会更新缓存的,所以,在一些特殊的并发场景中,就会导致数据不一致的情况。


读写并发的时序如下:



也就是说,假如一个读线程,在读缓存的时候没查到值,他就会去数据库中查询,但是如果自查询到结果之后,更新缓存之前,数据库被更新了,但是这个读线程是完全不知道的,那么就导致最终缓存会被重新用一个"旧值"覆盖掉。


这也就导致了缓存和数据库的不一致的现象


但是这种现象其实发生的概率比较低,因为一般一个读操作是很快的,数据库+缓存的读操作基本在十几毫秒左右就可以完成了。


而在这期间,更好另一个线程执行了一个比较耗时的写操作的概率确实比较低。


当然,根据墨菲定律,只要有可能发生的事情,就一定会发生。所以我们也要引起重视。



总结


我们在本文中介绍了数据库和缓存因为双写存在的不一致的情况,无论是单线程还是多线程,都是有可能会出现数据不一致的。


本文中还提到了在数据库和缓存的操作过程中,可能存在"先写数据库,后删缓存"、"先写数据库,后更新缓存"、"先删缓存库,后写数据库"以及"先更新缓存库,后写数据库"这四种。


那么,到底是应该删除缓存好呢,还是更新缓存好呢?到底应该先操作数据库呢还是先操作缓存呢?哪种方案更好呢?又该如何选择呢?


我们在后面的文章中再展开介绍。后面几篇文章会基于本文作为前提展开,所以大家要先能理解不一致问题出现在什么时候,才能知道要怎么做才能解决。


 

技术交流群

最近有很多人问,有没有读者交流群,想知道怎么加入。
最近我创建了一些群,大家可以加入。交流群都是免费的,只需要大家加入之后不要随便发广告,多多交流技术就好了。
目前创建了多个交流群,全国交流群、北上广杭深等各地区交流群、面试交流群、资源共享群等。
有兴趣入群的同学,可长按扫描下方二维码,一定要备注:全国 Or 城市 Or 面试 Or 资源,根据格式备注,可更快被通过且邀请进群。
▲长按扫描


往期推荐


我出书了!


各大框架都在使用的Unsafe类,到底有多神奇?


类型转换神器Mapstruct新出的Spring插件真好用




如果你喜欢本文,
请长按二维码,关注 Hollis.
转发至朋友圈,是对我最大的支持。

点个 在看 
喜欢是一种感觉
在看是一种支持
↘↘↘
浏览 13
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报