【Java知识点详解 8】缓存

多级缓存之JVM进程缓存 传统的缓存策略一般是请求到达Tomcat后,先查询Redis,如果未命中则查询数据库,在多级缓存架构中,Nginx内部需要编写本地缓存查询、Redis查询、Tomcat查询的业务逻辑,因此这样的nginx服务不再是一个反向代理服务器,而是一个编写业务的Web服务器了。缓存在日常开发中启动至关重要的作用,由于是存储在内存中,数据的读取速度是非常快的,能大量减少对数据库的访问,减少数据库的压力。Caffeine是一个基于Java8开发的,提供了近乎最佳命中率的高性能的本地缓存库。 阅读详情

🍅 Java学习路线推荐:Java基础教程系列

🍅 SpringBoot精品推荐:Spring Boot基础教程

🍅 简介:Java领域优质创作者🏆、优快云哪吒公众号作者✌ 、Java架构师奋斗者💪

🍅 扫描主页左侧二维码,加入群聊,一起学习、一起进步  

🍅 欢迎点赞 👍 收藏 ⭐留言 📝  

一、前言

缓存可以让原本打开很慢的页面,变得能“秒开”。平时访问的APP与网站几乎都涉及缓存的运用。

那么,缓存除了能加速数据的访问之外,还有什么作用呢?

另外,任何事物都有两面性,我们如何才能将缓存的优点发挥的淋漓尽致,同时避免它的弊端呢?

本文就给大家分享一下如何理解缓存,以及它的运用思路,希望对大家有所启发。

二、缓存能做什么?

正如前面所说,大家最普遍的理解就是当我们遇到某个页面打开很慢的时候,会想到引入缓存,这样页面打开就快了。其实快和慢是相对的,从技术角度来说,缓存之所以快是因为缓存是基于内存去建立的,而内存的读写速度比硬盘快很多倍,所以用内存来代替磁盘作为读写的介质自然能大大提高访问数据的速度。

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

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

三、预读取

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

为什么要这么做呢?因为有些系统一旦启动就要面临数以万计的请求进来,如果直接让这些请求打到数据库上,非常大的可能是数据库压力暴增,直接被反扒下,无法正常响应。

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

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

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

四、延迟写

你可能知道,数据库的写入速度是慢于读取速度的,因为写入的时候有一系列的保证数据准确性的机制。所以,如果想提升写入速度的话,要么做分库分表,要么就是通过缓存来进行一道缓冲,再一次性批量写到磁盘,以此来提速。

由于分库分表对跨表操作以及多条件组合查询的副作用巨大,所以引入它的复杂度大于引入缓存,我们应当优先考虑引入缓存的方案。

那么,通过缓存机制来加速“写”的过程就可以称作“延迟写”,它是预先将需要写入磁盘或数据库的数据,暂时写入到内存,然后返回成功,再定时将内存中的数据批量写入到磁盘。

可能你会想,写到内存就认为成功,万一中途出现意外、断电、停机等导致程序异常终止的情况,数据不就丢失了吗?

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

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

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

五、哪里可以加缓存?

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

一般来说你可以用两个标准来衡量:

热点数据:被高频访问,如几十次/秒以上。

静态数据:很少变化,读大于写。

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

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

那么在以终端用户为起点,系统所用的数据库为终点的这条道路上可以作为缓存设立点的位置大致有以下这些:

每个设立点可以挡掉一些流量,最终形成一个漏斗状的拦截效果,以此保护最后面的系统以及最终的数据库。

下面简要描述一下每个运用场景以及需要注意的点。

六、缓存类别

1、浏览器缓存

这是离用户最近的可以作为缓存的地方,而且借助的是用户的“资源”(缓存的数据在用户的终端设备上),性价比可谓最好,让用户帮你分担压力。

当你打开浏览器的开发者工具,看到 from cache 或者 from memory cache、from disk cache 的时候,就意味着这些数据已经被缓存在了用户的终端设备上了,没网的时候也能访问到一部分内容就是这个原因。

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

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

2、CDN缓存

提供CDN服务的服务商,在全国甚至是全球部署着大量的服务器节点(可以叫做“边缘服务器”)。那么将数据分发到这些遍布各地服务器上作为缓存,让用户访问就近的服务器上的缓存数据,就可以起到压力分摊和加速效果。这在TOC类型的系统上运用,效果格外显著。

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

解决方式也是有的,就是在 url 后面带个自增数或者唯一标示,如 ?v=1001。因为不同的 url 会被视作“新”的数据和文件,被重新 create 出来。

3、网关(代理)缓存

很多时候我们在源站前面加一层网关,为的是做一些安全机制或者作为统一分流策略的入口。

同时这里也是做缓存的一个好场所,毕竟网关是“业务无关”的,它能够拦下来请求,对背后的源站也有很大的受益,减少了大量的CPU运算。

常用的网关缓存有Varnish、Squid与Ngnix。一般情况下,简单的缓存运用场景,用Ngnix即可,因为大部分时候我们会用它做负载均衡,能少引入一个技术就少一分复杂度。如果是大量的小文件可以使用Varnish,而 Squid 则相对大而全,运用成本也更高一些。

4、进程内缓存

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

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

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

5、进程外缓存

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

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

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

6、数据库缓存

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

最后,其实磁盘本身也有缓存。所以你会发现,为了让数据能够平稳地写到物理磁盘中真的是一波三折。

七、缓存是银弹吗?

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

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

1、缓存雪崩

大量的请求并发进入时,由于某些原因未起到预期的缓冲效果,哪怕只是很短的一段时间,导致请求全部转到数据库,造成数据库压力过重。解决它可以通过“加锁排队”或者“缓存时间增加随机值”。

2、缓存穿透

和缓存雪崩类似,区别是这会持续更长的时间,因为每次“cache miss”后依然无法从数据源加载数据到缓存,导致持续产生“cache miss”。解决它可以通过“布隆过滤器”或者“缓存空对象”。

3、缓存并发

一个缓存key下的数据被同时set,怎么保证业务的准确性?再加上数据库的话?进程内缓存、进程外缓存与数据库三者皆用的情况下呢?用一句话来概括建议的方案是:使用“先DB再缓存”的方式,并且缓存操作用delete而不是set。

4、缓存无底洞

虽然分布式缓存是可以无限横向扩展的,但是,集群下的节点真的是越多越好吗?当然不是,缓存也是符合“边际效用递减”规律的。

5、缓存淘汰

内存总是有限的,如果数据量很大,那么根据具体的场景定制合理的淘汰策略是必不可少的, 如 LRU、LFU 与 FIFO 等等。

八、总结

本文介绍了运用缓存的三种思路,然后梳理了在一个完整的系统中可以设立缓存的几个位置,并且分享了关于浏览器、CDN与网关(代理)等缓存的一些实用经验,没有具体展开来讲细节,只是希望我们对缓存有一个更加体系化的认识,希望能让我们变得更加全面。

🍅 Java学习路线推荐:Java基础教程系列

🍅 SpringBoot精品推荐:Spring Boot基础教程

🍅 简介:Java领域优质创作者🏆、优快云哪吒公众号作者✌ 、Java架构师奋斗者💪

🍅 扫描主页左侧二维码,加入群聊,一起学习、一起进步  

🍅 欢迎点赞 👍 收藏 ⭐留言 📝  

【成为架构师3-14】缓存:进程内缓存该怎么玩 进程内缓存的优缺点,一致性问题的三种解决方案,以及适用场景 阅读详情

相关推荐

详解java数值类型核心知识点

我们比较推荐结合业务,小数变为整数进行计算,代码如下所示,我们完全可以结合业务场景决定将这段代码转为整数完成计算,如下所示,笔者将所有数值都乘10,这样一来所有计算都是整数计算,从而避免。为了得到-6的2进制的表示形式,我们首先将6的2进制取反。因为近期收到很多读者的私信,所以也专门创建了一个交流群,感兴趣的读者可以通过上方的公众号获取笔者的联系方式完成好友添加,点击备注。因为近期收到很多读者的私信,所以也专门创建了一个交流群,感兴趣的读者可以通过上方的公众号获取笔者的联系方式完成好友添加,点击备注。

禅与计算机程序设计的艺术 5537

缓存技术4之进程内缓存

进程内缓存 通过了客户端,CDN,负载均衡器,我们终于来到了应用服务器。应用服务器上部署着一个个应用,这些应用以进程的方式运行着,那么在进程中的缓存是怎样的呢? 进程内缓存又叫托管堆缓存,以 Java 为例,这部分缓存放在 JVM 的托管堆上面,同时会受到托管堆回收算法的影响。 由于其运行在内存中,对数据的响应速度很快,通常我们会把热点数据放在这里。 在进程内缓存没有命中的时候,...

aocuan3388的博客 336

【Java知识点详解 1】缓存

为什么要这么做呢?因为有些系统一旦启动就要面临数以万计的请求进来,如果直接让这些请求打到数据库上,非常大的可能是数据库压力暴增,直接被反扒下,无法正常响应。 为了缓解这个问题,就需要通过“预读取”来解决。 可能你会玩,哪怕用了缓存还是扛不住吗?那就是做横向扩展和负载均衡的时候了,这不是本文讨论的内容,有机会再专门分享吧。 如果说“预读取”是在“数据出口”加了一道前置的缓冲区的话,那么下面要说的“延迟写”就是在“数据入口”后面加了一道后置的缓冲区。 四、延迟写 你可能知道,数据库的写入速度是慢于读取速度的

m0_69745415的博客 666

进程内缓存,究竟怎么玩?

转:http://www.sohu.com/a/237745373_178889 进程内缓存,究竟怎么玩?  除了常见的redis/memcache等进程外缓存服务,缓存还有一种常见的玩法,进程内缓存。 什么是进程内缓存? 答:将一些数据缓存在站点,或者服务的进程内,这就是进程内缓存。 进程内缓存的实现载体,最简单的,可以是一个带锁的Map。又或者,可以使用第三方库,例如leveldb。...

baxiadsy_csdn的博客 502

Java缓存技术详解:概念、原理与常用方案

缓存(Cache)是一种用于存储临时数据的硬件或软件组件,其核心目的是通过减少数据访问延迟来提高系统性能。在计算机科学领域,缓存充当了高速数据访问层,存储着频繁访问的数据子集,使得后续请求能够更快地得到响应,而不必每次都访问较慢的底层存储层。从本质上讲,缓存是一种典型的"空间换时间"策略,通过消耗额外的存储空间来换取数据处理速度的提升。这种技术在计算机体系结构的各个层面都有体现,从CPU内部的L1、L2、L3缓存,到操作系统层面的磁盘缓存,再到应用程序级别的数据缓存,形成了一个完整的多级缓存体系。

记录学习的过程 966

DEA各种模型原理及stata代码实现

DEA各种模型原理及stata代码实现DEA各种模型原理及stata代码实现一、CCR和BCC1.原理2.效率测算stata代码3.Malmquist指数3.1M指数3.2Global-Malmquist指数4.指数计算代码与案例二、SBM模型1.原理2.stata代码实现三、方向性距离函数(DDF)1.原理2.stata代码实现3.非径向DDF模型(NDDF)3.GML指数4.指数测算四、总结 DEA各种模型原理及stata代码实现 一、CCR和BCC 1.原理 CCR模型产出导向下的效率通过求解以下规划

wonder1322的博客 4万+

初识Caffeine

缓存在日常开发中启动至关重要的作用,由于是存储在内存中,数据的读取速度是非常快的,能大量减少对数据库的访问,减少数据库的压力。我们把缓存分为两类: 分布式缓存,例如Redis: 优点:存储容量更大、可靠性更好、可以在集群间共享 缺点:访问缓存有网络开销 场景:缓存数据量较大、可靠性要求较高、需要在集群间共享 进程本地缓存,例如HashMap、GuavaCache: 优点:读取本地内存,没有网络开销,速度更快 缺点:存储

Leon_Jinhai_Sun的博客 1432

Excel插件开发实战:从零封装一个带自定义Ribbon的.xlam工具包

本文详细介绍了如何从零开发一个带自定义Ribbon的Excel插件.xlam工具包。通过VBA和XML技术,读者将学习到插件架构设计、Ribbon界面定制、模块化开发以及企业级部署策略,帮助提升Excel自动化办公效率。

weixin_42531128的博客 516

java缓存框架Caffeine详解

本地缓存是指将数据存储在设备的硬盘、内存或闪存中,通过空间换时间的策略来减少从远程服务器获取数据的时间和网络开销。Caffeine是一个基于Java8开发的提供了近乎最佳命中率的高性能缓存库。可以说是目前最优秀的本地缓存,性能对比可以参考链接:。实际上,Caffeine和ConcurrentMap很像——支持并发,并且支持O(1)时间复杂度的数据存取。ConcurrentMap将存储所有存入的数据,直到你将其手动移除;Caffeine将通过给定的配置,自动移除“不常用”的数据,以保持内存的合理占用。

asxyxxx的博客 1万+

[ENVI]-[高光谱遥感]-波谱沙漏分析工具的使用

图1-2-1查看特殊波段的坏波段图1-2-2在中添加坏波段ENVI波谱沙漏分析工具MNF变换。

m0_57992372的博客 1470

Ubuntu20.04运行Vins-fusion

因已安装ROS noetic,eigen,opencv及ceres等库,这部分环境配置就不细讲,直接下载VINS-FUSION的代码库 下载编译 cd ~/vins-fusion/src git clone https://github.com/HKUST-Aerial-Robotics/VINS-Fusion.git cd ../ catkin_make source ~/catkin_ws/devel/setup.bash 编译时会发现一堆错误,别急,无非就是环境冲突问题,一个个解决 1)首先,ROS

xiaojinger_123的博客 1万+

java缓存详解

缓存

yushan125的博客 3328

一位海外开发者的 OpenSPG KAG 实践分享

KAG 是一个以创建和操作知识图谱为核心的框架。知识图谱是数据之间相互关联的可视化和结构化表示,对于搜索引擎、推荐系统和机器学习等应用至关重要。KAG 的目标是提供一个强大的平台,使开发者能够:轻松构建图谱;通过增强算法丰富数据;集成人工智能,以进行更精确的推理。通过理解 KAG,可以明显看出,这个框架旨在帮助从初学者到专业开发者,在项目中创造更优的解决方案。它在简便性和集成方面的优势,使其成为下一代基于数据的应用程序的前景工具。

金融机器智能社区 3405

Java8-本地缓存

这里我将会给大家演示用ConcurrentHashMap类和lambda表达式实现一个本地缓存。因为Map有一个新的方法可以在key为Null的时候自动计算一个新的value值。非常完美的实现cache。来看下代码: public static void main(String[] args) { for (int i = 0; i < 10; i++) System.o

踏雁寻花 2935

一文学会VOS2009对接网关指定走某个落地网关

介绍:  在我们日常使用VOS2009/3000的过程中,肯定会有很多落地网关与对接网关,并且某些时候还需要某些对接网关指定去走某个落地网关或者某些落地网关,从而实现比较精准的控制对接网关与落地网关的关系,下面就演示下在VOS2009/3000中如何配置某个对接网关指定走某个或者多个落地网关。 实现步骤:  VOS2009可以通过添加固定前缀的方式来指定对接网关走某个落地网关。 比如:  r1对接网关在被叫改写规则里面填写*:a*  r2对接网关在被叫改写规则里填写*:b* 1.登录VOS客户端 2.进入

非著名运维的博客 1963

Apollo 9.0 参考线生成器 -- ReferenceLineProvider

在基于参考线的规划算法中,参考线是Planning一切工作的基础和前提,所以搞清楚参考线怎么来的就变得很重要。为此,首先需要了解Planning 与 Routing的交互,通过交互得到路径片段,这些路径片段就告诉我们该怎么走,再在此基础上生成参考线,最后使用不同的平滑算法对参考线进行平滑,得到一条光滑的参考线。

WaiNgai 1665

面试必问知识点总结,【Java知识点详解 8】缓,阿里java社招面试

这个月马上就又要过去了,还在找工作的小伙伴要做好准备了,小编整理了大厂java程序员面试涉及到的绝大部分面试题及答案,希望能帮助到大家一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

2401_84004024的博客 1521

Google antigravity 不支持你所在地区?手把手教你把账号改成支持地区

Google antigravity功能火爆,但国内老账号根本用不了🤬本文分享几种有效的账号国家地区切换方法,最快几分钟就能让antigravity直接亮起🔥

XiaoqiangClub的博客 2万+

缓存详解-在java项目中使用缓存

一、概述 在java项目中经常有使用缓存的场景,这时候如何使用缓存就很重要了,本篇文章言简意赅,带你读透缓存 二、java常用的缓存 在java项目中经常使用到的缓存主要分为两个种类 1、内存类 java中的Map、List等容器实现类可以用来作为本地缓存。 一些本地缓存框架,类似ehcache,guava中实现的缓存。 2、中间件类 redis、memcache等等 三、使用缓存将会面临的一些问...

qq_32384985的博客 4804

OV9734 DATASHEET,完整规格书

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

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

使用Caffeine库的Java本地缓存详解

在Java编程语言中,Caffeine是一个开源的缓存库,用于提供高性能的本地缓存实现。它支持在应用程序中轻松管理缓存,并提供了许多灵活的配置选项。

cxkjntm123的博客 2774

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

java 缓存_Java8简单的本地缓存实现

原文链接 译文链接 翻译:踏雁寻花,校对:丁一这里我将会给大家演示用ConcurrentHashMap类和lambda表达式实现一个本地缓存。因为Map有一个新的方法,在key为Null的时候自动计算一个新的value值。非常适合实现cache。来看下代码:当然,这种方式很傻瓜。即使对于一个非常小的数,例如fibonacci(5),上面的代码也会打印出很多行,而且都是在进行重复计算,输出如下(只截...

weixin_36105296的博客 497

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

【java】缓存机制详解

本文深入解析Java缓存机制,从基础概念到实际应用全面覆盖。主要内容包括:缓存的定义与核心价值(提升访问速度、减轻数据库压力、提高并发能力);Java中三种缓存实现方式(本地缓存、分布式缓存、多级缓存)及各自优缺点;典型缓存工作流程Cache Aside Pattern;重点剖析缓存三大问题(穿透、击穿、雪崩),特别是缓存击穿的解决方案(互斥锁、热点数据永不过期、逻辑过期);最后推荐高性能缓存工具Caffeine并总结面试高频问题。全文系统性地讲解了缓存技术的原理、实现和最佳实践。

2301_81481532的博客 690

Java缓存开源库Ehcache详解

Ehcache是一个开源的Java缓存框架,遵循JSR-107标准,支持本地和分布式缓存。它具有多级缓存(内存+磁盘)、灵活的淘汰策略(LRU/LFU/FIFO)、分布式同步、事务支持和丰富的监控功能。Ehcache架构围绕CacheManager构建,支持XML和编程两种配置方式,适用于高频读低频写、快速响应和数据库减压等场景。相比Guava Cache和Caffeine,Ehcache支持持久化和分布式;相比Redis,它更轻量但功能较弱。集成Spring Boot简便,但需注意缓存一致性、内存溢出和序

魏波 2325
上一篇: springboot实现热部署 | Spring Boot 13
下一篇: Spring Boot原理篇
哪 吒
哪 吒 2022年度博客之星TOP 1 2022年度博客之星TOP 1 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 59万+粉丝 2953原创
评论 11
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值