入行这么久? 真正理解了缓存吗

强制缓存与协商缓存的理解与使用 强制缓存,顾名思义,就是当浏览器第一次请求某个资源时,服务器会告诉浏览器,这个资源可以缓存下来,在下次请求时直接使用缓存,而不需要再次去服务器请求。浏览器会根据缓存的有效期判断是否可以继续使用缓存的内容。浏览器每次请求资源时,会检查本地缓存。如果缓存没有过期,就直接使用缓存的数据,而不向服务器发送请求。:这是控制缓存的最重要的字段。通过设置缓存的过期时间或缓存策略来控制资源是否能被缓存。Expires:指定资源的过期时间(如某个时间点之前有效),当设置了时,它的优先级高于Expires。 阅读详情

今天跟大家分享的缓存是指软件层面的缓存。大家都知道的一点是,缓存可以让原本打开很慢的页面,变得能“秒开”。你平时访问的 APP 与网站几乎都有涉及到缓存的运用。
那么,缓存除了能加速数据的访问之外,还有什么作用呢?
另外,任何事物都有两面性,我们如何才能将缓存的优点发挥得淋淋尽致,同时避免掉到它的弊端中呢?

缓存能做什么?

正如前面所说,大家最普遍的理解就是当我们遇到某个页面打开很慢的时候,会想到引入缓存,这样页面打开就快了。

其实快和慢都是相对的,从技术角度来说,缓存之所以快是因为缓存是基于内存去建立的,而内存的读写速度比硬盘快 X 倍,所以用内存来代替硬盘作为读写的介质自然能大大提高访问数据的速度。

这个过程大致是这样的,通过在内存中存储被访问过的数据供后续访问时使用,以此来达到提速的效果。

其实除此之外,缓存还有另外 2 个重要的运用方式:预读取和延迟写。

预读取

预读取就是预先读取将要载入的数据,也可以称作“缓存预热”,它是在系统中先将硬盘中的一部分数据加载到内存中,然后再对外提供服务。

为什么要这样做呢?因为有些系统一旦启动就要面临上千上万的请求进来(在一些 toC 的项目尤其如此),如果直接让这些请求打到数据库上,非常大的可能是数据库压力暴增,直接被干趴,无法正常响应。

为了缓解这个问题,就需要通过“预读取”来解决。

可能你会问,哪怕用了缓存还是扛不住呢?那就是做横向扩展+负载均衡的时候到了,这不是本文讨论的内容,有机会再专门分享吧。

如果说“预读取”是在“数据出口”加了一道前置的缓冲区的话,那么下面要说的“延迟写”就是在“数据入口”后面加了一道后置的缓冲区。

延迟写

你可能知道,数据库的写入速度是慢于读取速度的,因为写入的时候有一系列的保证数据准确性的机制。

所以,如果想提升写入速度的话,要么做分库分表,要么就是通过缓存来进行一道缓冲,再一次性批量写到磁盘,以此来提速。

那么,通过缓存机制来加速“写”的过程就可以称作“延迟写”,它是预先将需要写入到磁盘或者数据库的数据,暂时写入到内存,然后就返回成功,再定时将内存中的数据批量写入到磁盘。
在这里插入图片描述
可能你会想,写到内存就认为成功,万一中途出现意外、断电、停机等导致程序异常终止的情况,数据不就丢了吗?

是的。所以“延迟写”一般仅用于对数据完整性要求不是那么苛刻的场景,比如点赞数啊、参与用户数啊等等,可以大大缓解对数据库频繁修改所带来的压力。

其实在我们熟知的分布式缓存 Redis 中,其默认运用的持久化机制——RDB,也是这样的思路。

在一个成熟的系统中,能够运用到缓存的地方其实并不是一处。下面就来梳理一下我们在哪些地方可以“加缓存”。

哪里可以加缓存?

在说哪里可以加缓存之前我们先搞清楚一个事情,我们要缓存什么?也就是符合什么特点的数据才需要加缓存?毕竟加缓存是一个额外的成本投入,得物有所值。

一般来说你可以用这两个标准来判断:

热点数据:被高频访问,如几十次/秒以上
静态数据:很少变化,读远大于写,如几天变更一次

接下去就可以替它们找到合适的地方加缓存了。

缓存的本质是一个“防御性”的机制,而系统之间的数据流转是一个有序的过程,所以,选择在哪里加缓存就相当于选择在一条马路的哪个位置设路障。在这个路障之后的道路都能受到保护,不被车流碾压。

那么在以终端用户为起点,系统所用的数据库为终点的这条道路上可以作为缓存设立点的位置大致有以下这些:
在这里插入图片描述
每个设立点可以挡掉一些流量,最终形成一个漏斗状的拦截效果,以此保护最后面的系统以及最终的数据库。
在这里插入图片描述
下面简要描述一下每个运用场景以及需要注意的点。

浏览器缓存

这是离用户最近的可以作为缓存的地方,而且借助的是用户的“资源”(缓存的数据在用户的终端设备上),性价比可谓最好,让用户帮你分担压力。
在这里插入图片描述
当你打开浏览器的开发者工具,看到 from cache 或者 from memory cache、from disk cache 的时候,就意味着这些数据已经被缓存在了用户的终端设备上了,没网的时候也能访问到一部分内容就是这个原因。

这个过程是浏览器替我们完成的,一般用于缓存图片、js 与 css 这些资源,我们可以通过 Http 消息头中的 Cache-Control 来控制它,具体细节这里就不展开了。此外,js 里的全局变量、cookie 等运用也属于该范畴。

浏览器缓存是在于用户侧的缓存点,所以我们对它的掌控力会比较差,在没有发起新请求的情况下,你无法主动去更新数据。

CDN 缓存
提供 CDN 服务的服务商,在全国甚至是全球部署着大量的服务器节点(可以叫做“边缘服务器”)。

那么将数据分发到这些遍布各地服务器上作为缓存,让用户访问就近的服务器上的缓存数据,就可以起到压力分摊和加速效果。这在 toC 类型的系统上运用,效果格外显著。

但是需要注意的是,由于节点众多,更新缓存数据比较缓慢,一般至少是分钟级别,所以一般仅适用于不经常变动的静态数据。

网关(代理)缓存

到这里做缓存就是在你自己的地盘了。很多时候我们会在源站前面架一层网关(或者说反向代理、正向代理),为的是做一些安全机制或者作为统一分流策略的入口。
在这里插入图片描述
同时这里也是做缓存的一个好场所,毕竟网关是“业务无关性”的,它能够拦下来请求,对背后的源站也有很大的受益,减少了大量的 CPU 运算。
常用的网关(代理)缓存有 Varnish、Squid 与 Ngnix。一般情况下,简单的缓存运用场景,用 Nginx 即可,因为大部分时候我们会用它来做负载均衡,能少引入一个技术就少一份复杂度。如果是大量的小文件可以使用 Varnish,而 Squid 则相对大而全,运用成本也更高一些。

进程内缓存

可能我们大多数程序员第一次刻意使用缓存的场景就是这个时候。

一个请求能走到这里说明它是“业务相关”的,需要经过业务逻辑的运算。

也正因为如此,从这里开始对缓存的引入成本比前面 3 种大大增加,因为对缓存与数据库之间的“数据一致性”要求更高了。

进程外缓存

这个大家也熟悉,就是 Redis 与 Memcached 之类,甚至也可以自己单独写一个程序来专门存放缓存数据,供其它程序远程调用。

这里先多说几句关于 Redis 和 Memcached 该怎么选择的思路。

对资源(cpu、内存等)利用率格外重视的话可以使用 Memcached,但程序在使用的时候需要容忍可能发生的数据丢失,因为是纯内存的机制。如果无法容忍这点,并且对资源利用率也比较豪放的话可以使用 Redis。而且 Redis 的数据库结构更多,Memcached 只有 key-value,更像是一个 NoSQL 存储。

数据库缓存

数据库本身是自带缓存模块的,否则也不会叫它内存杀手,基本上你给多少内存就能吃多少。数据库缓存是数据库的内部机制,一般都会给出设置缓存空间大小的配置来让你进行干预。

最后,其实磁盘本身也有缓存。所以你会发现,为了让数据能够平稳地写到物理磁盘中真的是一波三折,不知道什么时候可以有“快”到不需要程序来考虑缓存的磁盘出现来拯救我们程序员呢。

缓存是银弹吗?

可能你会想缓存那么好,那么应该多多益善,只要慢就上缓存来解决?

一个事物看上去再好,也有它负面的一面,缓存也有一系列的副作用需要考虑。除了前面提到的“缓存更新”和“缓存与数据的一致性”问题,还有诸如下边的这些问题:

缓存雪崩:在大量的请求并发进入时,由于某些原因未起到预期的缓冲效果,哪怕只是很短的一段时间,导致请求全部流转到数据库,造成数据库压力过重。解决它可以通过“加锁排队”或者“缓存时间增加随机值”。
缓存穿透:和“缓存雪崩”比较类似,区别是这会持续更长的时间,因为每次“cache miss”后依然无法从数据源加载数据到缓存,导致持续产生“cache miss”。解决它可以通过“布隆过滤器”或者“缓存空对象”。
缓存并发:一个缓存 Key 下的数据被同时 set,怎么保证业务的准确性?再加上数据库的话呢?进程内缓存、进程外缓存与数据库三者皆用的情况下呢?用一句话来概括建议的方案是:使用“先 DB 再缓存”的方式,并且缓存操作用 delete 而不是 set。
缓存无底洞:虽然分布式缓存是可以无限横向扩展的,但是,集群下的节点真的是越多越好吗?当然不是,缓存也是符合“边际效应递减”规律的。
缓存淘汰:内存总是有限的,如果数据量很大,那么根据具体的场景定制合理的淘汰策略是必不可少的,如 LRU、LFU 与 FIFO 等等。

所以缓存不是银弹,对缓存的使用也需要先考虑各种问题。总结一下,本文先向你介绍了运用缓存的三种思路,然后梳理了在一个完整的系统中可以设立缓存的几个位置,并且分享了关于浏览器、CDN 与网关(代理)等缓存的一些使用经验,没有具体展开来讲细节,只是希望你对缓存有一个更加体系化的认识,希望能让你看得更加全面。

喜欢的可以给博主点点赞!

双缓冲技术原理以及优缺点 立即下载

相关推荐

告别JTAG!用Artix-7和SPI Flash实现FPGA远程升级的保姆级教程

本文详细介绍了如何利用Artix-7 FPGA和SPI Flash实现FPGA远程升级(OTA)的完整方案。通过硬件连接、Vivado工程配置和STM32模拟更新等步骤,帮助开发者告别传统的JTAG烧录方式,实现高效、安全的远程固件更新,特别适用于嵌入式系统开发中的现场维护场景。

weixin_33964987的博客 364

关于缓存的理解

是否要为系统引入缓存和引入缓存的利弊

eck_燃的博客 506

宝塔面板全栈部署指南:Node后端+React前端与数据库配置实战

本文提供了一份详尽的宝塔面板全栈部署实战指南,涵盖Node.js后端、React前端与数据库的完整配置流程。文章深入解析了环境准备、数据库创建与导入、Node服务部署、PM2进程守护、React应用构建与托管,以及线上环境变量管理与安全配置等核心步骤,帮助开发者高效、稳定地将项目部署至生产环境。

weixin_29232121的博客 90

一文带你了解单片机的缓存——Cache

本文将分享我对单片机的缓存——Cache的理解,希望我的分享对你有所帮助!

m0_73931287的博客 3180

PaddleOCR转ONNX模型实战:5分钟搞定中文OCR推理部署(附完整代码)

本文详细介绍了将PaddleOCR模型转换为ONNX格式并进行高效推理部署的完整实战方案。通过Paddle2ONNX工具实现模型转换,利用ONNX Runtime构建跨平台推理引擎,涵盖环境配置、模型优化、批量处理及多平台部署等关键步骤,显著提升中文OCR在边缘设备上的推理性能。

weixin_29051811的博客 617

Cursor Agent模式下如何优雅切换conda环境运行Python脚本?3种实用方法实测

本文针对Cursor Agent模式下运行Python脚本时环境错配的痛点,实测了三种优雅切换conda环境的实用方法。通过Shell全局配置、项目级.cursorrc文件定制以及对话中直接指令,开发者可以确保AI助手在正确的虚拟环境中执行代码,从而提升开发效率和协作流畅度。

redis7keeper的博客 598

缓存原理及优缺点

原理:先查询缓存中有没有要的数据,如果有,就直接返回缓存中的数据。 如果缓存中没有要的数据,才去查询数据库,将得到数据先存放到缓存中,然后再返回给php。 优点: 1、 减少了对数据库的读操作,数据库的压力降低  2、 加快了响应速度   缺点: 1、 因为内存断电就清空数据,存放到内存中的数据可能丢失        2、 缓存中的数据可能与数据库中数据不一致    

Noneyes的博客 4313

UG\NX二次开发 分割曲线

分割曲线没有ufun函数?那就换一种思路实现。

王牌飞行员_里海的博客 1147

简历_熟悉缓存高并发场景处理方法(使用 Redis 对高频访问的信息进行缓存,降低数据库査询压力),如缓存穿透、缓存击穿、缓存雪崩

*服务实现类*

buyaotutou的博客 1786

SA8295P QNX主机上电启动流程分析

嵌入式系统的启动过程对于确保系统正常运行至关重要。本文将详细分析SA8295P芯片在QNX主机上的上电启动流程,并提供相应的源代码示例。嵌入式系统的启动过程对于确保系统正常运行至关重要。本文将详细分析SA8295P芯片在QNX主机上的上电启动流程,并提供相应的源代码示例。以下是一个SA8295P QNX主机上电启动流程分析。

CodeMaven的博客 1231

肖特基二极管选型参数,结构原理,工艺与注意问题总结

肖特基二极管(Schottky Diode)是一种特殊的二极管,也被称为肖特基势垒二极管。它是利用金属与半导体接触形成的金属-半导体结原理制成的。与传统的PN结二极管相比,肖特基二极管具有更低的正向压降、更高的开关速度、更高的反向恢复时间以及更好的温度稳定性等特点。本文对肖特基二极管的工作原理,结构特点,工艺流程,选型参数及设计注意事项进行总结。

fydar的博客 813

Redis 学习笔记(五):避雷!这些 Redis 错误,别再踩了

本文总结了Redis使用中常见的三大问题——缓存穿透、击穿和雪崩。穿透指查询不存在数据导致数据库被攻击;击穿是热点key过期引发瞬时高并发;雪崩则是大量key同时失效造成系统崩溃。文章通过对比表、流程图和代码示例,详细分析了三者的区别与解决方案:穿透需缓存空值并设短TTL,击穿应采用逻辑过期+异步重建,雪崩需随机TTL+高可用架构。最后还列举了其他常见Redis使用误区,强调缓存不是银弹,必须考虑失效场景并进行防御性编程。

2401_87778289的博客 728

12027.linux flash驱动之IS25LP01G/IS25WWP01G

一页:512字节 --> 扇区 4096字节 --> 块 32k,64k, 层层递进关系。

写给自己的笔记 2289

缓存穿透、缓存击穿、缓存雪崩的理解和解决方案

目录 一、缓存穿透 二、缓存击穿 三:缓存雪崩 在生产环境中,会因为很多的原因造成访问请求绕过了缓存,都需要访问数据库持久层,虽然对Redsi缓存服务器不会造成影响,但是数据库的负载就会增大,使缓存的作用降低 一、缓存穿透 1、缓存穿透理解 缓存穿透是指查询一个根本不存在的数据,缓存层和持久层都不会命中。在日常工作中出于容错的考虑,如果从持久层查不到数据则不写入缓存层,缓存穿透将导致不存在的数据每次请求都要到持久层去查询,失去了缓存保护后端持久的意义。 缓存穿透示意图: 缓存穿透问...

a898712940的博客 3万+

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Glide三级缓存理解详细

Glide三级缓存理解详细一、普通的三级缓存二、Glide三级缓存分类:活动缓存、内存缓存、磁盘(本地)缓存三、三级缓存范围:四、三级缓存的作用:五、活动缓存的说明:六、内存缓存的说明:七、磁盘缓存的说明:八、Glide三级缓存的使用九、Glide的缓存使用九、总结共勉:向前行进。 本文对Glide的三级缓存进行主要的文字描述,希望能帮助大家加深对Glide的缓存理解。 Glide官网: https://github.com/bumptech/glide 一、普通的三级缓存 内存缓存,优先加载,速度最快

wenzhi的博客 6484

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

对缓存的一些简单理解

缓存的存在意义,使用缓存的问题:一致性、命中率、内存管理等

a15089415104的博客 1352

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级的理解

缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级的理解

weixin_40587144的博客 1339

Picasso的缓存理解

Picasso的缓存理解及简单的封装想必大家对Picasso的使用已经比较熟悉了,在此处我就不多说了,不熟悉的小伙伴可以看看Picasso官网。然后简单说说项目的依赖。Picasso的缓存理解及简单的封装 依赖权限 缓存LruCache DiskLruCache Picasso中的缓存操作 缓存清除 封装接口部分 接口实现 转换车间 函数调用 Demo下载 依赖一般情况下都是通过 GRADLE 进行

PM-LEE的博客 5870

深入理解浏览器的缓存机制之协商缓存与强缓存

浏览器缓存指的就是浏览器对之前请求过的文件进行缓存,以便在下一次访问时重复使用,从而节省带宽、提升访问速度、降低服务器压力。本文所说的HTTP缓存机制就是利用HTTP响应头将所请求的资源在浏览器中进行缓存,缓存方式主要分为两种:强缓存、协商缓存。

青春木鱼的博客 8568

谈谈我对前端缓存的理解

本文主要讲解了前端缓存中的强缓存和协商缓存,与缓存相关的首部字段,缓存的不同位置及其之间的区别等。 为什么要使用缓存 使用缓存有如下优点: 减少冗余的数据传输 节省网络费用,缓解网络瓶颈问题 降低对原始服务器的要求,服务器可以更快响应,避免出现过载 降低距离时延 浏览器请求资源的过程 浏览器第一次请求资源: 本地无缓存数据 向服务器发送请求 从服务器获取资源,并协商缓存(是否缓存,获取资源的...

忙着开花儿 2464

Mybatis的缓存机制理解

概述 针对查询操作,mybatis支持通过缓存的方式来减少SQL的调用,提高查询性能。在缓存级别方面分为一级缓存和二级缓存, 一级缓存的粒度较小,是与某个SqlSession绑定的,只对该SqlSession的相关查询操作进行缓存,不同SqlSession实例之间相互不影响,缓存为使用本地内存实现; 二级缓存是一种全局缓存,是由所有SqlSession实例所共享的,即不同SqlSession实例...

源码之下,了无秘密 5012

一级缓存和二级缓存的理解

首先补充下CPU的知识: CPU也就是中央处理器,相当于计算机的大脑; CPU是一块超大规模的集成电路,是一台计算机的运算核心(Core)和控制核心(Control Unit); CPU功能主要是解释计算机指令以及处理计算机软件中的数据; 中央处理器主要包括运算器(算术逻辑运算单元,ALU,Arithmetic Logic Unit)和高速缓冲存储器(Cache)及实现它们之间联系的数据(Data)、控制及状态的总线(Bus); CPU与内部存储器(Memor.

sinat_22510827的博客 2895

缓存的理解

缓存,为什么要引入缓存,缓存雪崩、缓存穿透、缓存一致性

weixin_35794878的博客 2351

深入理解前端缓存

前端缓存是所有前端程序员在成长历程中必须要面临的问题,它会让我们的项目得到非常大的优化提升,同样也会带来一些其它方面的困扰。等,但是我相信大部分的前端程序员不了解它们的缓存机制。接下来我将带你们深入理解缓存的机制以及缓存时间的判断公式,如何合理的使用缓存机制来更好的提升优化。我将会把前端缓存分成HTTP缓存和浏览器缓存两个部分来和大家一起聊聊。

量子前端的博客 1805

【JuiceFS】理解juicefs缓存

对于一个由对象存储和数据库组合驱动的文件系统,缓存是本地客户端与远端服务之间高效交互的重要纽带。读写的数据可以提前或者异步载入缓存,再由客户端在后台与远端服务交互执行异步上传或预取数据。相比直接与远端服务交互,采用缓存技术可以大大降低存储操作的延时并提高数据吞吐量。JuiceFS 提供包括元数据缓存、数据读写缓存等多种缓存机制。【学会思考】上面我们知道了缓存的优势,为什么要引入缓存。还要考虑我们的应用场景 ,真的需要缓存吗?缓存提升性能的前提是什么?

metaopen的博客 2320

理解:什么是缓存,什么是文件缓存?

前言 什么是缓存?所谓的缓存就是,将程序频繁调用的对象,存在服务器系统内存中。以便下次调用时可以直接取系统内存中对象做到快速响应。省去了第一次访问时,对象实例创建和查询数据库等操作。从而,降低服务器资源消耗,提高服务器性能。 举例: 场景一:电商平台高并发下,10W个人每次访问某个活动商品信息都要去查询数据库,然后封装对象返回; 场景二...

shenshao_8的博客 4249
上一篇: 谈谈JVM-深堆、浅堆
下一篇: Redis之实现持久化与恢复
Formor_
博客等级 码龄7年 7粉丝 31原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值