今天跟大家分享的缓存是指软件层面的缓存。大家都知道的一点是,缓存可以让原本打开很慢的页面,变得能“秒开”。你平时访问的 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 与网关(代理)等缓存的一些使用经验,没有具体展开来讲细节,只是希望你对缓存有一个更加体系化的认识,希望能让你看得更加全面。

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

入行这么久? 真正理解了缓存吗相关推荐

  1. Java后端入行看这 做软件园最靓的仔

    16k长文以失败学角度分享普通本科二线Java后端入行经历 前言 入行趣事 ■ 实习前 ■ 趣事分享1 -- 找实习 ■ 开启一周面试狂潮 1.皮包单休公司 2.养老级银行政务 3.培训机构 4.狼性 ...

  2. 刚入行的小菜鸡,怎样做好功能测试?

    常见的功能测试的流程是:需求分析,用例编写,用例评审,提测验证,Bug 回归验证,上线与线上回归. 但是做起来就是:写不完的用例,跑不完的case,天天都要加班. 我以功能测试的工作流程,结合实际的工 ...

  3. 写给新入行程序员的10条建议

    1. 想清楚,再动手写代码 刚入行的新手,为了展示自己的能力,拿到需求迫不及待地就开始上手写代码,大忌! 2. 不交流,就会头破血流 不爱说话和沟通,需求都理解错误了,最后做出来才发现,只能加班返工. ...

  4. 游戏建模师真实状况,入行4K?网上吐槽的是真的吗?

    网络上有太多的声音说建模这个行业不行,入行薪资低.是的,这些人没有骗你,大学刚毕业出来,建模师的薪酬确实只有4-5K左右.(当然也看地区,北上广深杭等一般6k起步)由于你是新人,效率比较慢,加班也是常 ...

  5. 一个入行很长的老鸟给新手的一些建议——转

    今天有空,随便写点东西给大家.很久没有混在技术论坛中,记忆里最近一次大概是在5.6年以前. 大学读的是土木,曾经也在建筑工地和设计院实习,我相信我可以把那些事情做好,但完全不是我想要的东西.96年有幸 ...

  6. U3D游戏开发工程师正确入行姿势指南

    2021年,游戏圈上演了一场精彩绝伦的抢人大战.在上海游戏圈,年薪百万的人越来越多了. 据多名HR估算,在上海,过去一年TA.引擎.美术等稀缺岗位拟的薪资涨幅大概在20%-30%左右.某位圈内知名资深 ...

  7. Fedora和Red Hat Enterprise Linux实用指南(第6版)(上、下册)( 入行必读的Linux圣经)

    Fedora和Red Hat Enterprise Linux实用指南(第6版)(上.下册)( 入行必读的Linux圣经) (美)苏贝尔(SobellL,M.G.)著 李洋等译 ISBN 978-7- ...

  8. 入行测试已经4年了 ,进华为后迷茫了3个月,做完这个项目我决定离职....

    转行测试 我是大专非计科,我转行之前从事的工作是商场管理,努力了4年左右的时间才做到楼层经理,但是工资太低并且事情太多,薪资才6K. 更多的是坚定了自己的想法,我要改变自己 恰好有几个大学同学在互联网 ...

  9. 数据科学行业已被挤爆?4点建议献给准备入行的小白

    数据科学家被称为"21世纪最性感的职业",也被认为是最容易找工作的职业,但如今,真实情况如何呢? 数据科学刚刚度过了它的黄金五年. 自2012年以来,这个行业发展迅速.它几乎完整经 ...

  10. python数据分析师工作内容_小白入行数据分析师3年-工作内容复盘分享含代码(一)-Python篇介绍...

    前言 个人作为互联网行业数据分析师工作已有3年之久,日常工作中碰到过问题,也在解决的问题过程中学到了很多.作为组内技术较为资深的组员,也经常在周会中安排环节给组内人员进行知识分享,以及日常帮助同事解决 ...

最新文章

  1. 使用条件卷积进行实例和全景分割
  2. lua 实现策划需要保留的小数位数
  3. [转]GetProcAddress函数
  4. 国外版莆田系医院要凉了:谷歌禁止未验证、没有科学根据的医疗广告
  5. 类加载子系统的详解——未完待续
  6. 电脑手机wifi互传文件_手机之间怎么互传文件?几则小技巧了解下
  7. 注册表文件(*.reg)的编写及应用
  8. zoj 1006 Do the Untwist 簡單字符串
  9. 哈哈哈,第一次做codeforce
  10. mysql数据表备份_MySQL数据库备份之逻辑备份和物理备份概述
  11. 五大最佳自动化软件测试工具
  12. html中页面整体排版,html在不同尺寸浏览器窗口中页面排版混乱
  13. html 文字竖着排引号,竖排文字 引号如何使用?
  14. 计算机 开机硬盘灯一直亮,电脑一开机硬盘灯就一直亮
  15. 2020年中国羊肉行业供需现状、进出口情况及产业链分析,新西兰为羊肉主要进口国「图」
  16. MySQL INSERT插入条件判断:如果不存在则插入
  17. 技嘉显卡性能测试软件,你好六啊!GTX 1660 Ti深度测试:升吧
  18. 超级App成为Gartner预测的战略技术,软件降本增效是否能进一步提速?
  19. 国内从事红外热成像的公司
  20. PyCharm专业版安装教程

热门文章

  1. 《私募股权基金投资基础知识》---第四章
  2. 江阴:智慧融入城市血液,打造创新发展新名片
  3. 波士顿学院的计算机科学,波士顿学院介绍_专业_费用_排名_申请-托普仕美国院校库...
  4. 安装vue脚手架vue-cli
  5. 上千个游戏模型推荐 好用又实用,流行又火爆的都在这里
  6. 名词用作动词举例_古语名词使动用法解析
  7. 怎样开启无线热点服务器,Win7开启无线WIFI热点
  8. 史玉柱自述:我是如何做游戏策划
  9. 记录一次China GT比赛历程
  10. 韩顺平python教程视频_尚硅谷_韩顺平_Linux_2018Linux基础入门教程全集