面试必问的缓存使用:如何保证数据一致性、缓存设计模式

简介: 缓存使用在现在的项目中非常常见,缓存在为我们带来便利的同时,也会带来一些常见的问题,如果不谨慎使用,可能会带来意想不到的结果。

前言


缓存使用在现在的项目中非常常见,缓存在为我们带来便利的同时,也会带来一些常见的问题,如果不谨慎使用,可能会带来意想不到的结果。


面试中,缓存使用带来的各种问题也是面试官喜欢考察的点,今天我将跟大家一起探讨以下几个常见的问题:


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

·       先操作数据库 or 先操作缓存?

·       失效缓存 or 更新缓存?

·       缓存的常见设计模式有哪些?

 

正文


缓存查询通用流程

image.png

这个缓存查询流程相信大家都不陌生,这应该是目前应用最广的缓存查询流程。

但是大部分人可能不知道,这个流程其实有一个名字:Cache Aside Pattern,这是缓存设计模式的一种。

上图是 Cache Aside Pattern 的查询流程,而更新流程如下。

 

image.png

这个更新流程会引出两个问题:

1)为什么是先操作数据库,可以先操作缓存吗?

2)为什么是失效缓存,可以更新缓存吗?

接下来我们一一分析。

 

先操作数据库 or 先操作缓存

先操作数据库

案例如下,有两个并发的请求,一个写请求,一个读请求,流程如下:

 

image.png

 

脏数据时间范围:更新数据库后,失效缓存前。这个时间范围很小,通常不会超过几毫秒。

 

 

先操作缓存

案例如下,有两个并发的请求,一个写请求,一个读请求,流程如下:

 

image.png

 

脏数据时间范围:更新数据库后,下一次对该数据的更新前。这个时间范围不确定性很大,情况如下:

 

1)如果下一次对该数据的更新马上就到来,那么会失效缓存,脏数据的时间就很短。

 

2)如果下一次对该数据的更新要很久才到来,那这期间缓存保存的一直是脏数据,时间范围很长。

 

结论:通过上述案例可以看出,先操作数据库和先操作缓存都会存在脏数据的情况。但是相比之下,先操作数据库,再操作缓存是更优的方式,即使在并发极端情况下,也只会出现很小量的脏数据。

 

 

失效缓存 or 更新缓存

 

更新缓存

案例如下,有两个并发的写请求,流程如下:

 image.png

 

分析:数据库中的数据是请求B的,缓存中的数据是请求A的,数据库和缓存存在数据不一致。

 

 

失效缓存

案例如下,有两个并发的写请求,流程如下:

 

image.png

 

分析:由于是删除缓存,所以不存在数据不一致的情况。

 

结论:通过上述案例,可以很明显的看出,失效缓存是更优的方式。

 

 

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

 

在上文的案例中,无论是先操作数据库,还是先操作缓存,都会存在脏数据的情况,有办法避免吗?

 

答案是有的,由于数据库和缓存是两个不同的数据源,要保证其数据一致性,其实就是典型的分布式事务场景,可以引入分布式事务来解决,常见的有:2PCTCCMQ事务消息等。

 

但是引入分布式事务必然会带来性能上的影响,这与我们当初引入缓存来提升性能的目的是相违背的。

 

所以在实际使用中,通常不会去保证缓存和数据库的强一致性,而是做出一定的牺牲,保证两者数据的最终一致性。

 

如果是实在无法接受脏数据的场景,则比较合理的方式是放弃使用缓存,直接走数据库。

 

保证数据库和缓存数据最终一致性的常用方案如下:

 

1)更新数据库,数据库产生 binlog

 

2)监听和消费 binlog,执行失效缓存操作。

 

3)如果步骤2失效缓存失败,则引入重试机制,将失败的数据通过MQ方式进行重试,同时考虑是否需要引入幂等机制。

 image.png

 

兜底:当出现未知的问题时,及时告警通知,人为介入处理。

 

人为介入是终极大法,那些外表看着光鲜艳丽的应用,其背后大多有一群苦逼的程序员,在不断的修复各种脏数据和bug

 

image.png

 

 

上文我们聊到了缓存设计模式中的 Cache Aside,并对常见的问题进行了延伸。

 

接着,我们来聊下缓存设计模式的其他几种:Read ThroughWrite ThroughWrite Behind Caching

 

 

Read/Write Through

 

Cache Aside 中,应用层需要和两个数据源打交道:缓存、数据库,这增加了应用层的复杂度,能否只和一个数据源打交道?

 

Read/Write Through 就是用来解决这个问题的,该模式下应用层只和缓存打交道,由缓存去操作和维护数据库。

 

该模式会让应用层变得更加简单,同时代码也会更简洁。

 

 

Read Through

 

应用层查询数据时,当缓存未命中时,由缓存去查询数据库,并且将结果写入缓存中,最后返回结果给应用层。

image.png 

 

 

Write Through

 

应用层更新数据时,由缓存去更新数据库。同时,当缓存命中时,写缓存和写数据库需要同步控制,保证同时成功。 

 

image.png

 

 

Write Behind Caching

 

Write Behind 又称为 Write Back,从应用层的视角来看和 Write Through 类似,在该模式下,应用层也是只需要和缓存一个数据源打交道,不同点在于:

 

Write Through 会立刻把数据同步写入数据库中,这样做的优点是操作简单,缺点是数据修改需要同时写入数据库,数据写入速度会比较慢。

 

Write Behind 会在一段时间之后异步的把数据批量写入数据库,这样的做的优点是:1)应用层操作只写缓存,应用层会觉得操作飞快无比;2)缓存在异步的写入数据库时,会将多个 I/O 操作合并成一个,减少 I/O 次数。

 

缺点是:1)复杂度高;2)更新后的数据还未写入数据库时,如果此时出现系统断电的情况,数据将无法找回。

 

Write Behind 的核心流程图如下:

 image.png

 

Write Back 缓存模式由于其复杂性比较高,所以在业务应用中使用的比较少,但是由于其带来的性能提升,还是有不少优秀的软件采用了该设计模式,例如:linux 中的页缓存、MySQL 中的InnoDB 存储引擎。

 

linux 中的 page cache(页缓存)采用的就是 write back 机制:用户 write 时只是将数据写到 page cache,并标记为 dirty,并没有真正写到硬盘上。内核在某个时刻会将 page cache 里的 dirty 数据wirteback 到硬盘上。

 

wikipedia 上有一张 Write Back 的流程图,如下,图中的 lower memory 可以简单的理解为数据库(硬盘):

 

image.png

image.png

 

最后


 

最近我将自己的原创文章整理分类了一下,汇总到了该文章下:原创汇总,后续的原创文章也会往该目录补充,喜欢我文章的同学可以收藏方便后续查阅。

 

当你的才华还撑不起你的野心的时候,你就应该静下心来学习,愿你在我这里能有所收获。

 

原创不易,如果你觉得本文写的还不错,对你有帮助,请通过【点赞】让我知道,支持我写出更好的文章。

 

推荐阅读


两年Java开发工作经验面试总结

4 Java 经验,阿里网易拼多多面试总结、心得体会

5 Java 经验,字节、美团、快手核心部门面试总结(真题解析)

921天,咸鱼到阿里的修仙之路

复习2个月拿下美团offer,我都做了些啥

如何写一份让 HR 眼前一亮的简历(附模板)

面试阿里,HashMap 这一篇就够了

面试必问的 MySQL,你懂了吗?

面试必问的线程池,你懂了吗?

跳槽,如何选择一家公司

如何准备好一场大厂面试

MySQL 8.0 MVCC 核心原理解析(核心源码)

相关文章
|
5天前
|
缓存 NoSQL 关系型数据库
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
本文详解缓存雪崩、缓存穿透、缓存并发及缓存预热等问题,提供高可用解决方案,帮助你在大厂面试和实际工作中应对这些常见并发场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
|
17天前
|
SQL 缓存 关系型数据库
美团面试:Mysql 有几级缓存? 每一级缓存,具体是什么?
在40岁老架构师尼恩的读者交流群中,近期有小伙伴因未能系统梳理MySQL缓存机制而在美团面试中失利。为此,尼恩对MySQL的缓存机制进行了系统化梳理,包括一级缓存(InnoDB缓存)和二级缓存(查询缓存)。同时,他还将这些知识点整理进《尼恩Java面试宝典PDF》V175版本,帮助大家提升技术水平,顺利通过面试。更多技术资料请关注公号【技术自由圈】。
美团面试:Mysql 有几级缓存? 每一级缓存,具体是什么?
|
23天前
|
缓存 监控 算法
小米面试题:多级缓存一致性问题怎么解决
【10月更文挑战第23天】在现代分布式系统中,多级缓存架构因其能够显著提高系统性能和响应速度而被广泛应用。
35 3
|
2月前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
404 37
|
1月前
|
存储 缓存 NoSQL
阿里面试题:缓存的一些常见的坑,你遇到过哪些,怎么解决的?
阿里面试题:缓存的一些常见的坑,你遇到过哪些,怎么解决的?
|
1月前
|
设计模式 缓存 Java
面试题:谈谈Spring用到了哪些设计模式?
面试题:谈谈Spring用到了哪些设计模式?
|
1月前
|
存储 缓存 NoSQL
大数据-38 Redis 高并发下的分布式缓存 Redis简介 缓存场景 读写模式 旁路模式 穿透模式 缓存模式 基本概念等
大数据-38 Redis 高并发下的分布式缓存 Redis简介 缓存场景 读写模式 旁路模式 穿透模式 缓存模式 基本概念等
57 4
|
2月前
|
设计模式 安全 算法
【Java面试题汇总】设计模式篇(2023版)
谈谈你对设计模式的理解、七大原则、单例模式、工厂模式、代理模式、模板模式、观察者模式、JDK中用到的设计模式、Spring中用到的设计模式
【Java面试题汇总】设计模式篇(2023版)
|
2月前
|
存储 缓存 Android开发
Android RecyclerView 缓存机制深度解析与面试题
本文首发于公众号“AntDream”,详细解析了 `RecyclerView` 的缓存机制,包括多级缓存的原理与流程,并提供了常见面试题及答案。通过本文,你将深入了解 `RecyclerView` 的高性能秘诀,提升列表和网格的开发技能。
66 8
|
1月前
|
存储 缓存 NoSQL
有关缓存的一些面试知识
有关缓存的一些面试知识