关键词:
文章目录
如何保证缓存与数据库的双写一致性?
先记住结论:先更新数据库、再删除缓存是影响更小的方案
四种同步策略:
想要保证缓存与数据库的双写一致,一共有4种方式,即4种同步策略:
-
先更新缓存,再更新数据库;
-
先更新数据库,再更新缓存;
-
先删除缓存,再更新数据库;
-
先更新数据库,再删除缓存。
从这4种同步策略中,我们需要作出比较的是:
- 更新缓存与删除缓存哪种方式更合适?
先记住结论:删除缓存更适合
- 应该先操作数据库还是先操作缓存?
先记住结论:先操作数据库后操作缓存
下面我们来详细的探究一下:
同步策略探究
更新缓存还是删除缓存:
下面,我们来分析一下,应该采用更新缓存还是删除缓存的方式。
更新缓存
-
优点:每次数据变化都及时更新缓存,所以查询时不容易出现未命中的情况。
-
缺点:更新缓存的消耗比较大。如果数据需要经过复杂的计算再写入缓存,那么频繁的更新缓存,就会影响服务器的性能。如果是写入数据频繁的业务场景,那么可能频繁的更新缓存时,却没有业务读取该数据。
删除缓存
-
优点:操作简单,无论更新操作是否复杂,都是将缓存中的数据直接删除。
-
缺点:删除缓存后,下一次查询缓存会出现未命中,这时需要重新读取一次数据库。
从上面的比较来看,一般情况下,删除缓存是更优的方案。
先操作数据库还是缓存:
下面,我们再来分析一下,应该先操作数据库还是先操作缓存。
首先,我们将先删除缓存与先更新数据库,在出现失败时进行一个对比:
如上图,是先删除缓存再更新数据库,在出现失败时可能出现的问题:
-
进程A删除缓存成功;
-
进程A更新数据库失败;
-
进程B从缓存中读取数据;
-
由于缓存被删,进程B无法从缓存中得到数据,进而从数据库读取数据;
-
进程B从数据库成功获取数据,然后将数据更新到了缓存。
最终,缓存和数据库的数据是一致的,但B拿到的仍然是旧的数据。而我们的期望是二者数据一致,并且要都是新的数据。
如上图,是先更新数据库再删除缓存,在出现失败时可能出现的问题:
-
进程A更新数据库成功;
-
进程A删除缓存失败;
-
进程B读取缓存成功,由于缓存删除失败,所以进程B读取到的是旧的数据。
最终,缓存和数据库的数据是不一致的。
经过上面的比较,我们发现在出现失败的时候,是无法明确分辨出先删缓存和先更新数据库哪个方式更好,以为它们都存在问题。
后面我们会进一步对这两种方式进行比较,但是在这里我们先探讨一下,上述场景出现的问题,应该如何解决呢?
实际上,无论上面我们采用哪种方式去同步缓存与数据库,在第二步出现失败的时候,都建议采用重试机制解决,因为最终我们是要解决掉这个错误的。而为了避免重试机制影响主要业务的执行,一般建议重试机制采用异步的方式执行,如下图:
这里我们按照先更新数据库,再删除缓存的方式,来说明重试机制的主要步骤:
-
更新数据库成功;
-
删除缓存失败;
-
将此数据加入消息队列;
-
业务代码消费这条消息;
-
业务代码根据这条消息的内容,发起重试机制,即从缓存中删除这条记录。
好了,下面我们再将先删缓存与先更新数据库,在没有出现失败时进行对比:
如上图,是先删除缓存再更新数据库,在没有出现失败时可能出现的问题:
-
进程A删除缓存成功;
-
进程B读取缓存失败;
-
进程B读取数据库成功,得到旧的数据;
-
进程B将旧的数据成功地更新到了缓存;
-
进程A将新的数据成功地更新到数据库。
可见,进程A的两步操作均成功,但由于存在并发,在这两步之间,进程B访问了缓存。最终结果是,缓存中存储了旧的数据,而数据库中存储了新的数据,二者数据不一致。
如上图,是先更新数据库再删除缓存,再没有出现失败时可能出现的问题:
-
进程A更新数据库成功;
-
进程B读取缓存成功;
-
进程A更新缓存成功。
可见,最终缓存与数据库的数据是一致的,并且都是最新的数据。但进程B在这个过程里读到了旧的数据,可能还有其他进程也像进程B一样,在这两步之间读到了缓存中旧的数据,但因为这两步的执行速度会比较快,所以影响不大。对于这两步之后,其他进程再读取缓存数据的时候,就不会出现类似于进程B的问题了。
最终结论:
经过对比你会发现,先更新数据库、再删除缓存是影响更小的方案。如果第二步出现失败的情况,则可以采用重试机制解决问题。
补充:延时双删策略
上面我们提到,如果是先删缓存、再更新数据库,在没有出现失败时可能会导致数据的不一致。如果在实际的应用中,出于某些考虑我们需要选择这种方式,那有办法解决这个问题吗?
答案是有的,那就是采用延时双删的策略,延时双删的基本思路如下:
-
删除缓存;
-
更新数据库;
-
sleep N毫秒;
-
再次删除缓存。
阻塞一段时间之后,再次删除缓存,就可以把这个过程中缓存中不一致的数据删除掉。而具体的时间,要评估你这项业务的大致时间,按照这个时间来设定即可。
采用读写分离的架构怎么办?
如果数据库采用的是读写分离的架构,那么又会出现新的问题,如下图:
进程A先删除缓存,再更新主数据库,然后主库将数据同步到从库。而在主从数据库同步之前,可能会有进程B访问了缓存,发现数据不存在,进而它去访问从库获取到旧的数据,然后同步到缓存。这样,最终也会导致缓存与数据库的数据不一致。这个问题的解决方案,依然是采用延时双删的策略,但是在评估延长时间的时候,要考虑到主从数据库同步的时间。
第二次删除失败了怎么办?
如果第二次删除依然失败,则可以增加重试的次数,但是这个次数要有限制,当超出一定的次数时,要采取报错、记日志、发邮件提醒等措施。
java进阶面试必问:如何保证缓存与数据库的双写一致性?
面试题如何保证缓存与数据库的双写一致性?面试官心理分析你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题?面试题剖析一般来说,如果允... 查看详情
经典好文--如何保证缓存和数据库的双写一致性
面试题如何保证缓存与数据库的双写一致性?面试官心理分析你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题?面试题剖析一般来说,如果允... 查看详情
java面试常被问到这道题:如何保证缓存与数据库的双写一致性?
面试原题如何保证缓存与数据库的双写一致性?面试官心理分析你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题?面试题剖析一般来说,如果... 查看详情
一个经典面试题:如何保证缓存与数据库的双写一致性?
只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题?面试题剖析一般来说,如果允许缓存可以稍微的跟数据库偶尔有不一致的情况,也就是说如果... 查看详情
如何保证缓存与数据库的双写一致性?
一般来说,如果允许缓存可以稍微的跟数据库偶尔有不一致的情况,也就是说如果你的系统不是严格要求 “缓存+数据库”必须保持一致性的话,最好不要做这个方案,即:读请求和写请求串行化,串到一个内存队列里... 查看详情
java面试常被问到这道题:如何保证缓存与数据库的双写一致性?(代码片段)
面试原题:如何保证缓存与数据库的双写一致性?面试官心理分析你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题?面试题剖析一般来说,如... 查看详情
java面试常被问到这道题:如何保证缓存与数据库的双写一致性?(代码片段)
面试原题:如何保证缓存与数据库的双写一致性?面试官心理分析你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题?面试题剖析一般来说,如... 查看详情
一个高频面试题:怎么保证缓存与数据库的双写一致性?
...的组件,但是用到了分布式缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题?CacheAsidePattern最经典的缓存+数据库读写的模式,就是CacheAsidePattern。读的... 查看详情
浅析数据库与缓存的双写一致性问题
浅析数据库与缓存的双写一致性问题缓存由于其高并发和高性能的特性,在项目中被广泛使用。读缓存流程如下图:读取缓存流程双写一致性有以下三个要求:缓存不能读到脏数据缓存可能会读到过期数据,但要在可容忍时间内... 查看详情
美团二面:redis与mysql双写一致性如何保证?
...s与MySQL双写一致性如何保证?这道题其实就是在问缓存和数据库在双写场景下,一致性是如何保证的?本文将跟大家一起来探讨如何回答这个问题。公众号:捡田螺的小男孩谈谈一致性一致性就是数据保持一致,在分布式系统中... 查看详情
保证缓存与数据库双写时的数据一致性
缓存与数据库双写时的数据一致性问题:只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题? 一般来说,就是如果你的系统不是严格要求缓存... 查看详情
分布式缓存的面试题9
1、面试题 如何保证缓存与数据库的双写一致性? 2、面试官心里分析 你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题? 3... 查看详情
如何保证数据库和缓存双写一致性?(代码片段)
大家好,我是苏三,又跟大家见面了。前言数据库和缓存(比如:redis)双写数据一致性问题,是一个跟开发语言无关的公共问题。尤其在高并发的场景下,这个问题变得更加严重。我很负责的告诉大家,该问题无论在面试,还... 查看详情
美团二面:redis与mysql双写一致性如何保证?(代码片段)
...ySQL双写一致性如何保证?这道题其实就是在问缓存和数据库在双写场景下,一致性是如何保证的?本文将跟大家一起来探讨如何回答这个问题。公众号:捡田螺的小男孩谈谈一致性一致性就是数据保持一致,... 查看详情
如何保证redis缓存与数据库的一致性?(代码片段)
...更新缓存还是删除缓存2.1更新缓存2.2删除缓存3、先操作数据库还是缓存3.1先删除缓存再更新数据库3.2先更新数据库再删除缓存4、延时双删4.1采用读写分离的架构怎么办?5、利用消息队列进行删除的补偿1、四种同步策略... 查看详情
高并发下如何保证数据库和缓存双写一致性?(代码片段)
前言数据库和缓存(比如:redis)双写数据一致性问题,是一个跟开发语言无关的公共问题。尤其在高并发的场景下,这个问题变得更加严重。我很负责的告诉你,该问题无论在面试,还是工作中遇到... 查看详情
redis11_缓存和数据库一致性如何保证解决方案提供canel解决数据一致性问题
文章目录①.缓存和数据库双写一致保证②.缓存数据一致性-解决方案③.缓存数据一致性-解决-Canal①.缓存和数据库双写一致保证①.只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问... 查看详情
大厂面试必备:合肥java工资
面试题如何保证缓存与数据库的双写一致性?面试官心理分析你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题?面试题... 查看详情