写点什么

Java 开发面试基础,牛客网客户端,【面试总结】

用户头像
极客开源
关注
发布于: 刚刚

Cache aside

Cache aside也就是旁路缓存,是比较常用的缓存策略。


(1)读请求常见流程



应用首先会判断缓存是否有该数据,缓存命中直接返回数据,缓存未命中即缓存穿透到数据库,从数据库查询数据然后回写到缓存中,最后返回数据给客户端。


(2)写请求常见流程



首先更新数据库,然后从缓存中删除该数据。


看了写请求的图之后,有些同学可能要问了:为什么要删除缓存,直接更新不就行了?这里涉及到几个坑,我们一步一步踩下去。

Cache aside 踩坑

Cache aside 策略如果用错就会遇到深坑,下面我们来逐个踩。


踩坑一:先更新数据库,再更新缓存


如果同时有两个写请求需要更新数据,每个写请求都先更新数据库再更新缓存,在并发场景可能会出现数据不一致的情况。



如上图的执行过程:


(1)写请求1更新数据库,将 age 字段更新为 18;


(2)写请求2更新数据库,将 age 字段更新为 20;


(3)写请求2更新缓存,缓存 age 设置为 20;


(4)写请求1更新缓存,缓存 age 设置为 18;


执行完预期结果是数据库 age 为 20,缓存 age 为 20,结果缓存 age 为 18,这就造成了缓存数据不是最新的,出现了脏数据。


踩坑二:先删缓存,再更新数据库


如果写请求的处理流程是先删缓存再更新数据库,在一个读请求和一个写请求并发场景下可能会出现数据不一致情况。



如上图的执行过程:


(1)写请求删除缓存数据;


(2)读请求查询缓存未击中(Hit Miss),紧接着查询数据库,将返回的数据回写到缓存中;


(3)写请求更新数据库。


整个流程下来发现数据库中 age 为 20,缓存中 age 为 18,缓存和数据库数据不一致,缓存出现了脏数据。


踩坑三:先更新数据库,再删除缓存


在实际的系统中针对写请求还是推荐先更新数据库再删除缓存,但是在理论上还是存在问题,以下面这个例子说明。



如上图的执行过程:


(1)读请求先查询缓存,缓存未击中,查询数据库返回数据;


(2)写请求更新数据库,删除缓存;


(3)读请求回写缓存;


整个流程操作下来发现数据库age为20缓存age为18,即数据库与缓存不一致,导致应用程序从缓存中读到的数据都为旧数据。


但我们仔细想一下,上述问题发生的概率其实非常低,因为通常数据库更新操作比内存操作耗时多出几个数量级,上图中最后一步回写缓存(set age 18)速度非常快,通常会在更新数据库之前完成。


如果这种极端场景出现了怎么办?我们得想一个兜底的办法:缓存数据设置过期时间。通常在系统中是可以允许少量的数据短时间不一致的场景出现。

Read through

在 Cache Aside 更新模式中,应用代码需要维护两个数据源头:一个是缓存,一个是数据库。而在?Read-Through?策略下,应用程序无需管理缓存和数据库,只需要将数据库的同步委托给缓存提供程序?Cache Provider?即可。所有数据交互都是通过抽象缓存层完成的。



如上图,应用程序只需要与Cache Provider交互,不用关心是从缓存取还是数据库。


在进行大量读取时,Read-Through?可以减少数据源上的负载,也对缓存服务的故障具备一定的弹性。如果缓存服务挂了,则缓存提供程序仍然可以通过直接转到数据源来进行操作。


Read-Through 适用于多次请求相同数据的场景,这与 Cache-Aside 策略非常相似,但是二者还是存在一些差别,这里再次强调一下:


  • 在 Cache-Aside 中,应用程序负责从数据源中获取数据并更新到缓存。

  • 在 Read-Through 中,此逻辑通常是由独立的缓存提供程序(Cache Provider)支持。

Write through

Write-Through?策略下,当发生数据更新(Write)时,缓存提供程序?Cache Provider?负责更新底层数据源和缓存。


缓存与数据源保持一致,并且写入时始终通过抽象缓存层到达数据源。


Cache Provider类似一个代理的作用。


Write behind

Write behind在一些地方也被成为Write back, 简单理解就是:应用程序更新数据时只更新缓存,?Cache Provider每隔一段时间将数据刷新到数据库中。说白了就是延迟写入



如上图,应用程序更新两个数据,Cache Provider 会立即写入缓存中,但是隔一段时间才会批量写入数据库中。


这种方式有优点也有缺点:


  • 优点是数据写入速度非常快,适用于频繁写的场景。

  • 缺点是缓存和数据库不是强一致性,对一致性要求高的系统慎用。

一线互联网大厂 Java 核心面试题库


正逢面试跳槽季,给大家整理了大厂问到的一些面试真题,由于文章长度限制,只给大家展示了部分题目,更多 Java 基础、异常、集合、并发编程、JVM、Spring 全家桶、MyBatis、Redis、数据库、中间件 MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty 等等已整理上传,感兴趣的朋友可以看看支持一波!


本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

用户头像

极客开源

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
Java开发面试基础,牛客网客户端,【面试总结】