缓存穿透与雪崩及支付宝2018年面试题剖析

一、什么是缓存?

  ☞ 缓存就是数据交换的缓冲区(称作:Cache),当某一硬件要读取数据时,会首先从缓存汇总查询数据,有则直接执行,不存在时从内存中获取。由于缓存的数据比内存快的多,所以缓存的作用就是帮助硬件更快的运行。
  ☞ 缓存往往使用的是RAM(断电既掉的非永久存储),所以在用完后还是会把文件送到硬盘等存储器中永久存储。电脑中最大缓存就是内存条,硬盘上也有16M或者32M的缓存。
  ☞ 高速缓存是用来协调CPU与主存之间存取速度的差异而设置的。一般CPU工作速度高,但内存的工作速度相对较低,为了解决这个问题,通常使用高速缓存,高速缓存的存取速度介于CPU与主存之间。系统将一些CPU在最近几个时间段经常访问的内容存在高速缓存,这样就在一定程度上缓解了由于主存速度低造成的CPU“停工待料”的情况。
  ☞ 缓存就是把一些外存上的数据保存在内存上而已,为什么保存在内存上,我们运行的所有程序里面的变量都是存放在内存中的,所以如果想将值放入内存上,可以通过变量的方式存储。在JAVA中一些缓存一般都是通过Map集合来实现的。

▁▂▃▅▆ :缓存在不同的场景下,作用是不一样的具体举例说明:
✔ 操作系统磁盘缓存 ——> 减少磁盘机械操作。
✔ 数据库缓存——>减少文件系统IO。
✔ 应用程序缓存——>减少对数据库的查询。
✔ Web服务器缓存——>减少应用服务器请求。
✔ 客户端浏览器缓存——>减少对网站的访问。

二、缓存穿透

什么是缓存穿透?发生的原因?

1、缓存穿透: 缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候, 在缓存中找不到对应key的value,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次
无用的查询)。这样请求就绕过缓存直接查数据库
诱发原因:恶意攻击

2、有什么解决方案来防止缓存穿透?

  1. 缓存空值如果一个查询返回的数据为空(不管是数据不 存在,还是系统故障)我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。通过这个直接设置的默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库

  2. 采用布隆过滤器BloomFilter 优势占用内存空间很小,bit存储。性能特别高。 将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个bitmap 拦截掉,从而避免了对底层存储系统的查询压力

三、缓存击穿

什么是缓存击穿?发生原因?

上面提到的某个数据没有,然后好多请求查询数据库,可以归为缓存击穿的范畴:对于热点数据,当缓存失效的一瞬间,所有的请求都被下放到数据库去请求更新缓存,数据库被压垮。

解决方案:

  1. 一种思路是加全局锁,就是所有访问某个数据的请求都共享一个锁,获得锁的那个才有资格去访问数据库,其他线程必须等待。
  2. 对即将过期的数据进行主动刷新,比如新起一个线程轮询数据,或者比如把所有的数据划分为不同的缓存区间,定期分区间刷新数据。该思路也是缓存雪崩的解决方案之一

四、缓存雪崩

什么是缓存雪崩?发生原因?

缓存雪崩是指当我们给所有的缓存设置了同样的过期时间,当某一时刻,整个缓存的数据全部过期了,然后瞬间所有的请求都被抛向了数据库,数据库就崩掉了。——实际上就是连锁式缓存穿透 导致性能急速下降

解决方案:

  1. 加锁排队 key: whiltList value:1000w个uid 指定setNx whiltList valuenullValuemutex互斥锁解决,Redis的SETNX去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法
  2. 数据预热 在系统上线后将相关数据加载到缓存系统,避免用户访问之间访问数据库而不是缓存
  3. 双层缓存策略 其实就是为你的缓存"买一个保险" 做个备份 当A缓存失效后 直接访问B缓存 注:A缓存失效的时间短 B(备份缓存)失效时间长
  4. 定时更新缓存

关于加锁 setnx 与setex 操作 :一般来说,setnx&setex 可以应对分布式锁的大部分需求场景 但是这样却会产生一个问题!!——那就是无法实现可重入锁 也就是说只能锁无法解锁

加锁流程
在这里插入图片描述
会产生问题
在这里插入图片描述

1、当qps 流量请求过多 导致项目服务宕机 导致Redis锁无法释放 其他机器无法获取锁
2、当缓存雪崩导致Redis宕机 获取不到锁
3、当setnx 和setex之间发生服务宕机 导致Redis锁永远不会过期

解决方案:

  1. 手动删除key
  2. 使用lua脚本 把setnx 和setex两个指令放到一起

五、缓存刷新

什么是缓存刷新?

既清空缓存 ,一般在insert、update、delete操作后就需要刷新缓存,如果不执行就会出现脏数据。但当缓存请求的系统蹦掉后,返回给缓存的值为null。

发布了47 篇原创文章 · 获赞 30 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_42083036/article/details/103405727
今日推荐