作者 l 会点代码的大叔(CodeDaShu)

在往期文章中,我们介绍了缓存穿透和缓存雪崩,其中缓存雪崩,是对于一些设置了过期时间的 key,在某个时间点集体失效后,有大量的请求落到数据库上导致被击垮;而我们今天要介绍的【缓存击穿】,和缓存雪崩的区别在于:雪崩针对很多 key,而击穿只针对于某一个热点 key。

还记得缓存雪崩有哪些解决方案么?

设置缓存永不过期,这个方法虽然很暴力,但是确实能解决大部分的问题,当然,大部分场景也不太适用;

设置随机过期时间,这个方案对于缓存击穿来说就不太适用了,因为击穿只针对一个热点 key,只要它一失效,大量的访问就会击垮数据库;

其余的方案比如使用互斥锁、双缓存机制,也都可以解决缓存击穿的问题,让我们看看这些方案的具体实现。

01

主动刷新缓存

缓存设置成永不过期,在更新或删除 DB 中的数据时,也主动地把缓存中的数据更新或删除掉。

这个方案很容易理解,但是实现起来却很复杂,但凡需要使用缓存的数据,都需要增加双写数据库和缓存的代码,并且双写过程中,还需要保持数据一致性。

02

检查更新

缓存依然保持设置过期时间,每次 get 缓存的时候,都和数据的过期时间和当前时间进行一下对比,当间隔时间小于一个阈值的时候,主动更新缓存。

比如(缓存过期时间 - 当前系统时间)小于 5 分钟,那么就刷新一次缓存,并且重置缓存过期时间;

不过这个方法也有个致命的问题:如果一个数据,恰好在缓存失效前五分钟,一次访问都没有,那么就不会触发检查更新,当缓存失效后有大量请求访问,那么也会造成缓存击穿。

03

使用锁

在缓存失效后,通过互斥锁或者队列,控制读数据库和写缓存的线程数量。

第一种方法:整个方法是 synchronized 的,这样做虽然可以防止大量请求落到 DB 上,但是就算是缓存没有失效,需要从 DB 中查询数据也需要排队,无疑是降低了系统的吞吐量。

public synchronized String getCacheData() {String cacheData = "";//读 RediscacheData = getDataFromRedis();if (cacheData.isEmpty()) {//读数据库cacheData = getDataFromDB();//写 RedissetDataToCache(cacheData);}return cacheData;
}

第二种方法:当缓存失效时,只对查询数据库的操作进行加锁,这样对于缓存没有失效的情况也非常友好,但是查询操作这里加锁,也只是会阻塞掉住其他调用,第一其他线程要等待,对调用方不友好,第二这些请求被阻塞的请求最终还是会落到 DB 上的。

static Object lock = new Object();public String getCacheData() {String cacheData = "";// 读 RediscacheData = getDataFromRedis();if (cacheData.isEmpty()) {synchronized (lock) {//读数据库cacheData = getDataFromDB();//写 RedissetDataToCache(cacheData);}}return cacheData;}

第三种方法:使用互斥锁,抢到锁的话读数据库并写入缓存,抢不到锁的话也不阻塞,而是直接去读缓存,如果缓存中依然读不到数据(抢到锁的可能还没有将缓存写入成功),就等一会再试试读缓存。

public String getCacheData(){String result = "";//读 Redisresult = getDataFromRedis();if (result.isEmpty()) {if (reenLock.tryLock()) {try {//读数据库result = getDataFromDB();//写 RedissetDataToCache(result);}catch(Exception e){//...}finally {reenLock.unlock();//释放锁}} else {//注意:这里可以结合下文中的双缓存机制://抢不到锁的去查询二级缓存//读 Redisresult = getDataFromRedis();if (result.isEmpty()) {try {Thread.sleep(100);} catch (InterruptedException e) {//...}return getCacheData();}}}return result;
}

04

双缓存

设置一级缓存和二级缓存,一级缓存过期时间短,二级缓存过期时间长或者不过期,一级缓存失效后访问二级缓存,同时刷新一级缓存和二级缓存。

双缓存的方式,说白了就是不能将一级缓存和二级缓存中数据同时变成失效,当一级缓存失效后,有多个请求访问,彼此之间依然是竞争锁,抢到锁的线程查询数据库并刷新缓存,而其他没有抢到锁的线程,直接访问二级缓存(代码可以参考上文中的互斥锁),如图:

特别推荐一个分享架构+算法的优质内容,还没关注的小伙伴,可以长按关注一下:长按订阅更多精彩▼如有收获,点个在看,诚挚感谢

明白了缓存穿透和缓存雪崩,再了解一下缓存击穿!相关推荐

  1. 缓存击穿和缓存穿透的区别_后端RoadMap011:缓存穿透、缓存击穿、缓存雪崩区别和解决方案...

    一.缓存处理流程 前台请求,后台先从缓存中取数据,取到直接返回结果,取不到时从数据库中取,数据库取到更新缓存,并返回结果,数据库也没取到,那直接返回空结果. 二.缓存穿透 描述: 缓存穿透是指缓存和数 ...

  2. Redis的缓存穿透问题和雪崩问题?

    缓存穿透:就是访问redis中一个不存在的key的时候,会直接穿过缓存,去数据库中进行查询. 如果是黑客,进行恶意攻击的时候,每次都请求超过2000个/秒的时候,这个时候mysql基本上就挂了. 解决 ...

  3. Redis缓存预热、缓存穿透、缓存击穿、缓存雪崩,Redis布隆过滤器怎么实现?

    目录 一.缓存预热 1.缓存预热常见步骤 2.代码实现 二.缓存雪崩 1.什么情况会发生缓存雪崩? 2.Redis缓存集群实现高可用 3.如何避免Redis缓存雪崩? 三.缓存穿透 1.什么情况会发生 ...

  4. Redis缓存穿透击穿雪崩

    目录 1.缓存穿透 2.缓存击穿 3.缓存雪崩 1.缓存穿透 概述: 缓存穿透的概念很简单,用户想要査询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库査询.发现也数据库 ...

  5. 烂大街的缓存穿透、缓存击穿和缓存雪崩,你真的懂了?

    前言 对于从事后端开发的同学来说,缓存已经变成的项目中必不可少的技术之一. 没错,缓存能给我们系统显著的提升性能.但如果你使用不好,或者缺乏相关经验,它也会带来很多意想不到的问题. 今天我们一起聊聊如 ...

  6. mysql的雪崩穿透_缓存穿透、缓存击穿和缓存雪崩实践

    我们使用缓存的主要目是提升查询速度和保护数据库等稀缺资源不被占满.而缓存最常见的问题是缓存穿透.击穿和雪崩,在高并发下这三种情况都会有大量请求落到数据库,导致数据库资源占满,引起数据库故障.今天我主要 ...

  7. Redis 的缓存异常处理 —— 缓存雪崩、缓存击穿、缓存穿透

    Redis 的缓存异常处理 -- 缓存雪崩.缓存击穿.缓存穿透 在实际应用 Redis 过程中,如果将 Redis 作为数据库的缓存,经常会遇到这几个问题:缓存雪崩.缓存击穿.缓存穿透等. 缓存雪崩 ...

  8. 缓存穿透、缓存击穿和缓存雪崩

    我们使用缓存的主要目是提升查询速度和保护数据库等稀缺资源不被占满. 而缓存最常见的问题是缓存穿透.击穿和雪崩,在高并发下这三种情况都会有大量请求落到数据库,导致数据库资源占满,引起数据库故障.今天我主 ...

  9. 保姆级教学:缓存穿透、缓存击穿和缓存雪崩!

    前言 对于从事后端开发的同学来说,缓存已经变成的项目中必不可少的技术之一. 没错,缓存能给我们系统显著的提升性能.但如果你使用不好,或者缺乏相关经验,它也会带来很多意想不到的问题. 今天我们一起聊聊如 ...

  10. 缓存穿透、缓存击穿和缓存雪崩实践附源码

    xiaolyuh@oschina 读完需要 10 分钟 速读仅需 5 分钟 我们使用缓存的主要目是提升查询速度和保护数据库等稀缺资源不被占满. 而缓存最常见的问题是缓存穿透.击穿和雪崩,在高并发下这三 ...

最新文章

  1. Android Binder IPC机制
  2. 5月14日 游戏闯关,
  3. Java基础点——面向对象(中)
  4. [Java基础]File基础
  5. Java 10:将流收集到不可修改的集合中
  6. macOS彻底卸载/删除Microsoft相关的程序
  7. Android 热补丁动态修复框架小结
  8. 导出表结构_十分钟教你轻松掌握移动PE导出表,快来学习!
  9. pycharm操作指北
  10. 客户端常见的几种数据传输方法
  11. 【发布】Bangumi动画搜索一键跳转AniDBMyAnimeListANNTMDB和动漫花园等BT站在线播放站
  12. 软件工程第二次作业——git的使用
  13. python 了解量化交易
  14. oracle wallet无密码认证,Oracle Wallet 无密码登录
  15. 计算机辅助医疗未来展望,数字骨科应用与展望:更精确、个性、直观的未来前景...
  16. 清华大学课题组联合美团研发无人机声波定位技术获ACM SenSys顶会大奖
  17. 【问题记录】js 更改数组中某字段名
  18. python数据类型的性能
  19. 创业计划书PPT模板
  20. 百度何中军:机器翻译——从设想到大规模应用

热门文章

  1. PTA基础编程题目集-6-7 统计某类完全平方数
  2. potplayer 多个进程_操作系统进程与线程基本概念理解
  3. 索引 mysql_MySQL 索引
  4. ajax按钮禁止重复提交,Ajax禁止重复提交
  5. C++ 函数模板和排序的函数模板——学习笔记
  6. Python网络爬虫 - 一个简单的爬虫例子
  7. WindowsAPI每日一练(2) 使用应用程序句柄
  8. Python 3 文件和字符编码
  9. 《python 与数据挖掘 》一 1.2 工具简介
  10. Maven学习-项目对象模型