周末一刻

这周过的比较快,事情也比较多,依然无法阻挡我每周一浪的节奏。

先去了“杰论”的奶茶店,好不好喝不做评价,主要是捧个场,就感觉你们每次在文章下面点个赞一样。

这周还去了所谓网红桥,被网友们称为成都桥梁界的"新晋扛把子"。看看长撒子样子

这个大桥听说参考了"无限之环"—莫比乌斯杯的概念,将可能在四维空间中才存在的抽象涉及到三维空间,就仿佛数学符号"∞",以此表达高新区无限可能性和开放发展的广阔胸怀,当然也给与了不少的工作机会

吃完串串,这个串串感觉真的巴适。吃完约几个朋友漫步于桥上,听着河水流动的呲呲声,呼吸着湿润的空气是不是很xui服,


没想到吃完了去抽个奖,啊哈,中了100的代金卷,没想我旁边的菇凉比我还激动,当然我确实没想到我会抽个100的代金卷,毕竟一直都是:“感谢抽奖”。下次请你吃?


生活着不就这样嘛,吃吃喝喝,逛逛,别天天想着买房买车,给自己压力,有个大大的梦想,咦,分治思想嘛,化成一个个小目标慢慢实现勒

好了,还是学点东西,让我有点东西。

使用好缓存就仿佛拥有了无比锋利的宝剑,对于性能的提升是立竿见影的。但是如果使用的不好就会严重的影响系统的运行,那么今天我们看看缓存到底是什么以及缓存的应用模式

1 缓存的本质

网上有各种对缓存的定义和解释,我认为缓存是为了节约对原始资源重复获取的开销

什么是资源?

首先如果这个资源是经常变化的,你觉得缓存了有什么意义。显然不可行,所以,我们对资源的操作需要时是幂等切安全的。举个例子,比如银行转账,改变了目标状态,自然就不能缓存。

其次,缓存的数据是"重复"获取的。意味着将经常使用的数据缓存下来,当下一次访问的时候直接返回即可,这样节约了通过原始流程访问数据的时间。比如数据库中的连接池,线程池,就是为了避免频繁的创建链接,销毁链接而出。

如何衡量这个缓存的效果?

在数据获取的过程中,通过缓存获得数据的次数,除以总的次数所得到的结果为缓冲命中率

加了一层缓存就一定更快?

非也。首先这个快是相对而言的,因为在不同的系统中对于同一对象可能扮演的角色不同。比如CPU的多级高速缓存,即内存的缓存。而内存对于CPU存储而言又比较慢,但是对于磁盘却快了很多,所以它可以用作磁盘的缓存介质

能够举一个常见的例子来阐述缓存的应用?

如果看了我之前写的面试文章,应该对这个面试题非常的熟悉了。“当敲入URL会经历什么?”,在那篇文章中,写了一万多字来阐述这个问题,意味着如果面试官问你这个问题,你可以讲什么且可以从一个点出发将的比较深。回到这里,如果我让你以缓存的角度来阐述这个问题,你将如何去回答?

首先在地址栏输入域名,会查询浏览器内部"域名-IP"缓存,如果之前通过这个浏览器访问过这个域名,那么就有一张映射表。

如果没有,则会查询操作系统是否存在这个缓存,如果是mac电脑则/etc/hosts就可以定义域名到IP的关系。

如果还是没有则会查询域名服务器DNS得到对应的IP和可缓存的时间。如果需要使用命令来测试,这里可以同dig命令查看这个详细过程。

当请求到达了服务端,通常会有反向代理,在反向代理中会存在缓存配置,对于一个MVC架构的应用而言,MVC的各个层都有可以应用缓存模式

Controller层有拦截过滤器,可以通过配置缓存来过滤我们需要的请求,这样过滤器直接返回缓存结果而不执行后面的逻辑

对于Model层,在DAO上的Service暴露API应用缓存也是非常常见的操作

对于View层,页面标签居多,不会每次都去渲染,而是通过缓存标签的方式节省渲染操作

这一切操作完事后就会返回给浏览器,浏览器会加载页面中大量的资源,这都是通过读取浏览器的缓存来避免HTTP请求的开销。

看吧,我们在不断冲浪的同时,下面有着这么精彩的故事,也说明了缓存的重要性了吧

3 缓存应用模式

通过不同的特性和优缺点,将缓存分了几种模式,我们看看这几种模式的区别以及优缺点

Cache-Aside

数据库的异常情形

  • 如果数据库读取异常直接返回失败,不会存在数据不一致的情况
  • 如果数据读取成功了,但是缓存的写入失败,那么下次访问统一数据的时候继续尝试写入,也没有数据不一致的情况

所以这两种情况是比较安全的

数据更新的策略,到底是先更新数据库还是先让缓存失效

假设我们让缓存显示小,意味着在数据库更新成功之前,如果另外的请求访问缓存,此时缓存已经失效,那么就会按照原来的访问策略,从数据库中使用这个已经旧的数据去更新缓存的数据,这样就导致过期的数据会长期存放于缓存中,最终导致数据不一致。

为了加深大家对这个概念的理解,画了下面这幅图

第二需要注意的是:数据库更新以后,需要让缓存失效而不是更新缓存为最新的值

为什么呢?如果两个几乎同时发出的请求分别更新数据库中的值A和B,如果结果是B的更新晚于A,那么数据中的最终值为B。但是,如果数据库更新后去更新缓存,而不是让缓存失效,那么缓存中的数据就有可能是A,而不是B。因为数据库虽然是"更新为A"在"更新为B"之前发生,但如果不做特殊的跨存储系统的事务控制,缓存的更新顺序就未必遵从"A先于B"这个规则,就会导致缓存中的数据是一个长期错误的值A。

同样画个图,让大家理解更深刻

4 缓存常出现的问题

上面大多数时候都在谈论缓存带来的好处,现在该说说其弊端了

  • 缓存穿透

当在同一时间有大量的数据访问,经过了缓存屏障但是并没有起到应有的保护作用。举个例子,需要在数据库对一个key进行查询,如果数据库中没有这个数据,那么缓存也没有这个数据,每次请求都会去数据库查,缓存再次根本没有作用

怎么解决这个问题勒?

我们可以在缓存中对这个key存放一个空结果,毕竟没有结果也是结果嘛

还有一种比较严重的缓存穿透后果。在一般的缓存策略下,通常需要先发生一次缓存命中失败,然后从数据库得到结果,再填到内存缓存中。但是,如果这个数据库的查询太慢,此时大量的数据接踵而至,全部穿透缓存落在数据库上, 此时对于最初的请求所引发的缓存可能还没来得及混村,数据库就直接挂掉了,这种问题有那么解决方案呢

还有其他的解决方案?

使用布隆过滤器。主要用来判断一个元素是否在一个集合中,这个算法由一个二进制数据和一个hash算法组成,其基本的思路是这样的:

我们把集合中的每一个值按照提供的 Hash 算法算出对应的 Hash 值,然后将 Hash 值对数组长度取模后得到需要计入数组的索引值,并且将数组这个位置的值从 0 改成 1。在判断一个元素是否存在于这个集合中时,你只需要将这个元素按照相同的算法计算出索引值,如果这个位置的值为 1 就认为这个元素在集合中,否则则认为不在集合中。 画个图看看就更清楚了

ABC组成一个集合,元素D计算出来对应的数值为1,所以D也存在于集合。但是F在数组值为0,所以不在集合中了。

如何通过布隆过滤器解决缓存穿透?

我们以存储用户为例子,初始化一个大数组,长度为10亿的数据,选择一个Hash算法,计算用户的ID的Hash值并映射到这个大数组中,映射的位置为1,其他设置为0

一旦存在新注册的用户,当我们需要查询一个用户的信息的时候,首先查询的ID在布隆过滤器中是否存在,不存在则直接返回空,不继续查询数据库和缓存,这样不就大大的减少异常查询带来的缓存穿透

过滤器具有非常高的性能,无论是写入还是读取时间复杂度都是O(1)。空间上也是有着不错的又是,假设20亿 的数据需要2000000000/8/1024/1024 = 238M 控制,而如果使用数组来村粗,每个用户ID占4个字节,存储20亿 需要2000000000 * 4 / 1024 / 1024 =7600M 的空间,是布隆过滤器的 32 倍

布隆过滤器有哪些缺陷?

  • 判断元素是否在集合中有一定的错误几率

这个问题是hash算法的问题,Hash算法难免有一定的碰撞几率,所谓碰撞,即不同的输入值得到相同的Hash结果

  • 不支持删除元素

举个例子,假设两个元素A和B都是集合中的元素,具有相同的Hash值,会映射到数组相同的位置。此时如果删除A,数组中对应的位置从1变为-,那么在判断B的时候发现B不在集合中了,得到了错误的结论

如何解决这个问题

让数组中不在只有0和1两个数值,直接存储一个计数。假设AB同时命中数组的索引,此时这个值为2,如果A删除,将这个值改为1。当然这样就会增加空间的消耗,所以使用过滤器根据业务需求而定。

流量控制

限制对于同一数据的访问,必须等到前一个完成以后才能进行下一个,即如果缓存失效而引发的数据库查询正在进行,那么请他的请求只好乖乖的等着,这种方法通用性还可以,但是这个等待机制会比较影响用户的体验

缓存预热

在大量请求到来之前先预热一波,简单高效,局限性在于需要提前知道那些数据可能引发缓存穿透的问题

  • 缓存雪崩

在一定时间段出现大量的请求访问失效,直接造成后方的系统压力过大,引起系统过载,宕机,这就是缓存雪崩。

通常采取限流和预热两种方式进行避免。限流可以保障请求大量落到数据库的时候,系统只接纳能够承载的数量。对于预热则主动先王内存中加载一定的热点数据,请求到来的时候缓存不是空的,这样具有一定的保护能力。

缓存数据存在过期时间,如果缓存加载时间比较集中,那么此时大量的缓存同时国企,对这些数据的请求将全部落在后面的数据库从而导致系统崩溃,如何避免?

这里主要避免缓存集中写入时间,如果无法避免则使用一个范围的随机数均匀分散过期时间,从而打散系统造成的压力

  • LRU致命缺陷

LRU即Least Recently Used,最少最近使用算法,原理是维护一个限定最大容量的队列,队列头部总是放置最近访问的元素,超过容量限制的时候从队尾淘汰元素。

通过一个图看看LRU工作原理

这看起来是 个不错的方案,需要从缓存淘汰数据的时候总是从尾部淘汰一个不常用的,但是如果有用户有意无意的访问一些错误信息,此时就会破坏整个LRU队列中最近访问数据的真实性。

如果一不小心咱们缓存中存放不少冷门数据,热门活动开始后,大量的请求到来,全部穿透缓存导致数据库压力倍增,网站响应时间瞬间到告警线上。

怎么解决这个问题?

这里基于LRU的改进方案很多,简单说下LRU-K,即主缓存队列排的是"第K次访问的元素",也就是如果访问的次数小于k,则将其放在另一个"低级"的队列中维护,这样保证在一定的访问下限才能被送到LRU主队列中

5 小结

其中总结了我觉得比较高频的关于缓存的题,希望对大家有所帮助,下一周大大要过来,意味着9点下班可能成为日常,是高兴呢还是高兴?求个,么么哒

「面试」缓存知识点大总结相关推荐

  1. 史上最「奇葩」的十大编程语言,最后一个有毒……

    关注「实验楼」,每天分享一个项目教程 当你看到这些编程语言时,你的反应应该是「这人一定很闲」.「同是九年义务教育,他为什么这么优秀」.「这人有毒吧」-- 正文共:2220 字 预计阅读时间:7 分钟 ...

  2. 「面试」美团肝了我30+问题

    叮.....美团来电.这次不是外卖而是电话面试.所报岗位为后端/服务端开发,但是从我的复盘来看,这和 Java 后端开发的内容差不多,除了部分的语言特性外,还是四大件基础知识为重,下面我们来看看都问了 ...

  3. 「面试」到阿里第五轮后我才知道所谓的URL是什么

    计算机网络的重要程度不言而言,也是非常的复杂.今天我将从输入URL这个简单例子开始,一起探索数据包的心路历程.先点个赞再文章的大纲,么么哒. 1 源头------网址 网址即平时所说的URL.就是经常 ...

  4. 好消息:「ShowMeBug」获两大顶级基金联合领投A轮融资,将快速拓展产品及市场

    36氪获悉,「ShowMeBug」近期完成近亿元A轮融资,由红杉中国种子基金及高瓴创投联合领投.光璞资本担任长期独家财务顾问.本轮融资主要用于产品及运营推广方面. 「ShowMeBug」成立于2019 ...

  5. 告别「热」情的大武汉,TiDB TechDay 2019 收官站杭州见!

    上周六,TiDB TechDay 2019 全国巡讲来到了「火炉」武汉,这是我们第一次在武汉举办线下交流活动,就有近百位同学到场,非常感谢武汉社区伙伴们的热情支持(天儿这么热,能出门的都是真爱 ). ...

  6. 「完结」总结12大CNN主流模型架构设计思想

    http://blog.sina.com.cn/s/blog_cfa68e330102zocn.html 专栏<CNN模型解读>正式完结了,在这一个专栏中,我们给大家回顾了深度学习中的各类 ...

  7. 「面试」给金融科技安排明白了

    群友分享的一篇银行秋招经验贴,共勉.关于银行等国企的面试相关方法可以参考这篇----,相关的复习资料文末取 1 个人简介 先介绍一下自己的背景, 北邮 se本 男 只拿过校内比赛奖项 项目倒是杂七杂八 ...

  8. 「面试」拿到B站的意向书

    此次B站服务端开发面试之旅可谓惊险,不过通过对大部分面试题套路的掌握,不出意外还是拿下了,下面我们来看看这些骚题是不是常见的不能再常见的了.这些面试题看了就能面上?当然不是,只是通过这些题让自己知道所 ...

  9. 「面试」国企银行都喜欢问啥?

    差不多十月份了,这个时候可能国企,银行,事业单位的笔试面试比较多,今天给大家分享下面试这些企业的注意事项以及当初的复习资料都用了啥,直接拉到文末即可,希望对大家有所帮助 本篇文章主要给大家分享关于面试 ...

最新文章

  1. Java并发编程实战 第13章 显式锁
  2. 查看linux显示文件大小,Linux下查看占用最大的文件和文件夹大小
  3. python种颜色循环_Python 实现一个颜色色值转换的小工具
  4. java获取本周的开始时间和结束时间_创业板注册制开始时间/股票开户流程结束后,怎么炒股?...
  5. 我的docker随笔:开篇
  6. 基于贪心算法的几类区间覆盖问题 nyoj 12喷水装置(二) nyoj 14会场安排问题...
  7. Java基础知识(一) 自增、自减运算符
  8. 2019年宁波高职技能考计算机,2019年宁波职业技术学院高职提前招生考试综合素质测试大纲...
  9. 玩转Reactjs第三篇-组件(模式stateprops)
  10. Java使用IP代理突破IP限制进行投票
  11. 1号线彭埠站故障已经查明 是积水导致转辙机信号不良
  12. 如何在微信自定义链接分享内容,图文链接xml卡片生成代码,制作微信卡片实现自定义标题,描述,缩列图以供转发
  13. 《九日集训》第四天打卡
  14. 深入浅出Flask PIN
  15. Speedoffice(excel)如何快捷隐藏表格内所有空行
  16. 校招 | 华为终端云服务招聘NLP、CV、推荐和大数据等岗位
  17. Etcd Unable to attach or mount volumes
  18. STM32驱动MPU6050基于IIC协议
  19. java/php/net/python车辆保养管理系统设计
  20. Vue实现订单列表【用户端】

热门文章

  1. 解决PHP项目显示“该网页无法正常运作”,但没有显示报错内容
  2. jenkins自动打包报错:cannot find symbol
  3. 微信支付分 - 取消支付分API
  4. R语言——循环判断语句
  5. 学计算机要不要懂绘画,学绘画 学修图 你需要一台怎样的电脑
  6. 《构建高性能Web站点》
  7. 初等证明:费马商的加法分配律证明
  8. Zabbix6.2这些新特性太棒了,手把书教你在Linux部署Zabbix6.2,速度收藏!
  9. 《计算机网络(第七版)谢希仁 编著》第一章内容总结及部分解题
  10. kon-boot启动盘测试