Java 性能调优实战
刘超
前金山软件技术经理
59174 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 49 讲
开篇词 (1讲)
模块一 · 概述 (2讲)
结束语 (1讲)
Java 性能调优实战
15
15
1.0x
00:00/00:00
登录|注册

43 | 如何使用缓存优化系统性能?

分布式集群
分散过期时间
排斥锁
布隆过滤算法
空值缓存
Ehcache
Guava Cache
JVM实现的缓存
强缓存
协商缓存
解决方案
解决方案
解决方案
线程安全队列
缓存删除操作
分布式缓存 (Redis)
进程缓存
网关缓存 (CDN)
本地缓存
建议删除缓存中的数据
缓存雪崩
缓存击穿
缓存穿透
解决方案
数据不一致问题
服务层缓存技术
前端缓存技术
思考题
缓存穿透、缓存击穿、缓存雪崩
数据库与缓存数据一致性问题
缓存技术
如何使用缓存优化系统性能?

该思维导图由 AI 生成,仅供参考

你好,我是刘超。
缓存是我们提高系统性能的一项必不可少的技术,无论是前端、还是后端,都应用到了缓存技术。前端使用缓存,可以降低多次请求服务的压力;后端使用缓存,可以降低数据库操作的压力,提升读取数据的性能。
今天我们将从前端到服务端,系统了解下各个层级的缓存实现,并分别了解下各类缓存的优缺点以及应用场景。

前端缓存技术

如果你是一位 Java 开发工程师,你可能会想,我们有必要去了解前端的技术吗?
不想当将军的士兵不是好士兵,作为一个技术人员,不想做架构师的开发不是好开发。作为架构工程师的话,我们就很有必要去了解前端的知识点了,这样有助于我们设计和优化系统。前端做缓存,可以缓解服务端的压力,减少带宽的占用,同时也可以提升前端的查询性能。

1. 本地缓存

平时使用拦截器(例如 Fiddler)或浏览器 Debug 时,我们经常会发现一些接口返回 304 状态码 + Not Modified 字符串,如下图中的极客时间 Web 首页。
如果我们对前端缓存技术不了解,就很容易对此感到困惑。浏览器常用的一种缓存就是这种基于 304 响应状态实现的本地缓存了,通常这种缓存被称为协商缓存。
协商缓存,顾名思义就是与服务端协商之后,通过协商结果来判断是否使用本地缓存。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入介绍了如何使用缓存优化系统性能,从前端到服务端,系统了解了各个层级的缓存实现,并分别了解了各类缓存的优缺点以及应用场景。在前端缓存技术方面,介绍了本地缓存和网关缓存的实现原理和流程。在服务层缓存技术方面,分别介绍了进程缓存和分布式缓存的实现方式和适用场景。文章通过具体的实现代码和示例,帮助读者快速了解了缓存优化系统性能的重要性和实现方法。 此外,文章还深入探讨了数据库与缓存数据一致性问题,以及缓存穿透、缓存击穿、缓存雪崩等问题。针对这些问题,提出了解决方案,如使用线程安全队列缓存更新或删除的数据,以及使用布隆过滤算法来解决缓存穿透问题。同时,对于缓存击穿和缓存雪崩问题,也提出了相应的解决方案。 总的来说,本文全面介绍了缓存优化系统性能的重要性,以及在实际应用中可能遇到的问题和解决方案。读者可以从中了解到如何在前端和服务端合理应用缓存技术,以提高系统性能和降低后端压力。文章内容丰富,涵盖了技术实现细节和解决方案,对于想要深入了解缓存优化系统性能的读者来说,是一篇非常有价值的文章。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Java 性能调优实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(31)

  • 最新
  • 精选
  • QQ怪
    学到了很多,挺收益的,思考题:更新效率太低,代价很大,且不一定被访问的频率高,不高则没必要缓存,还不如直接删掉,而且还容易出现数据不一致问题

    作者回复: 👍🏻 对的,两个并发写去更新还存在一致性的问题。不过,在删除缓存后,记得读取数据需要加锁或延时等待,防止读取脏数据。

    2019-08-29
    23
  • Loubobooo
    课后题:原因很简单 1. 很多时候,在复杂点的缓存场景,缓存不单单是数据库中直接取出来的值。比如可能更新了某个表的一个字段,然后其对应的缓存,是需要查询另外两个表的数据并进行运算,才能计算出缓存最新的值的。 另外更新缓存的代价有时候是很高的。每次修改数据库的时候,都一定要将其对应的缓存更新一份,这样做的代价较高。如果遇到复杂的缓存数据计算的场景,缓存频繁更新,但这个缓存到底会不会被频繁访问到?如果没有,这个缓存的效率就很低了

    作者回复: 👍🏻 回答很全面

    2019-08-29
    2
    11
  • giserway
    还有就是更新缓存代价大。如果缓存里的数据不是把数据库里的数据直接存下来,而是需要经过某种复杂的运算,那么这种不必要的更新会带来更大的浪费。

    作者回复: 对的,这也是一种情况

    2019-08-29
    8
  • yungoo
    基于redis集中缓存更新数据采用删除而不是直接更新缓存的原因之一:避免二类更新丢失问题。 分布式系统中当存在并发数据更新时,因无法保证更新操作顺序的时间一致性,从而导致旧值覆盖新值。 如: t1时间点,A进程发起更新key1为1的P1操作。 t1+x时间点,B进程发起更新key1为2的P2操作。 其中P1 -> P2,数据库中值为2。 而redis收到的指令,可能因网络抖动或者STW,实际为P2 -> P1,缓存的值为1,造成数据不一致。

    作者回复: 👍🏻 存在并发更新时数据不一致问题

    2019-08-29
    2
    6
  • Maxwell
    老师您说的:通常我们会在查询数据库时,使用排斥锁来实现有序地请求数据库,减少数据库的并发压力。这个通常哪些方案?

    作者回复: 最常用的就是使用同步锁或Lock锁实现。

    2019-08-29
    3
    3
  • 许童童
    直接更新缓存中的数据,因为请求到达的顺序无法保证,有可能后请求的数据覆盖前请求的数据。直接将数据删除,就是一种幂等的操作,删除后,再去数据库拉数据,就不会有覆写的问题。

    作者回复: 对的,如果两个并发写去更新还存在一致性的问题,还不如直接删除,等下次读取的时候再次写入缓存中。不过,在删除缓存后,记得读取数据需要加锁或延时等待,防止读取脏数据。

    2019-08-29
    2
  • ty_young
    老师您好,请问协商缓存和强制缓存没有关联么,不会先走强制缓存,然后在强制缓存的基础上走协商缓存

    作者回复: 强制缓存只有两种情况,要么访问服务端,要么用本地缓存,所以加上协商缓存意义不大

    2019-10-31
    1
  • Better me
    布隆过滤器为什么要经过n个hash函数散列,有什么特别的考虑吗

    作者回复: 这是为了计算不同的位置,通过不同位置置1,得出一个数值。

    2019-08-29
    3
    1
  • -W.LI-
    老师真棒,全能。 CDN的缓存策略是copy服务端的,协商缓存和强缓存?如果有些静态资源,服务端开发没做缓存策略,CDN还会缓存么?实际开发中用过一次CDN。是在资源路径前,拼接一段CDN路径。具体不知 课后习题,如果并发操作时,虽然redis是单线程的但是没法保证网络延时下,先更新数据库。也先更新缓存。个人感觉失效一个key比写一个key开销小。网络传输上看,update还得传一个value的值,redis更新还得写缓存感觉也是失效慢。并发情况写两次(除开正确性)有一次的写完全浪费。

    作者回复: 通常我们是会指定一些静态资源文件上传到CDN上去,并且通过版本号来更新。例如,我们的js资源文件是 xxx001.js,如果我们更新了该资源文件,则将xxx002.js推送到CDN上,同时前端的访问路径也更新访问资源路径。

    2019-08-29
    1
  • 💢 星星💢
    老师,我有个问题,分布式更新或者删除缓存的时候,为啥不对这个操作加锁呢,例如a线程更新或者删除缓存,并更新数据库,然后解锁。此时b线程在争夺锁。并且持有锁。是不是性能问题,所以不这样,还是我理解错了?

    作者回复: 没有理解错,锁和我文中提到的队列都是解决redis缓存数据一致性问题的方案,这种解决方案会带来一定的性能损耗

    2019-09-29
    3
收起评论
显示
设置
留言
31
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部