当前位置: 首页 > news >正文

缓存夺命连环问

1. 为什么要用缓存?

用缓存,主要有两个用途:高性能高并发

高性能

  • 假设这么个场景,你有个操作,一个请求过来,吭哧吭哧你各种乱七八糟操作 MySQL,半天查出来一个结果,耗时 600ms。但是这个结果可能接下来几个小时都不会变了,或者变了也可以不用立即反馈给用户。那么此时咋办?
  • 缓存啊,折腾 600ms 查出来的结果,扔缓存里,一个 Key 对应一个 Value,下次再有人查,别走 MySQL 折腾 600ms 了,直接从缓存里,通过一个 Key 查出来一个 Value,2ms 搞定。性能提升 300 倍。
  • 就是说对于一些需要复杂操作耗时查出来的结果,且确定后面不怎么变化,但是有很多读请求,那么直接将查询出来的结果放在缓存中,后面直接读缓存就好

高并发

  • MySQL这么重的数据库,压根儿设计不是让你玩儿高并发的,虽然也可以玩儿,但是天然支持不好。MySQL 单机支撑到2000QPS(每秒查询率)也开始容易报警了
  • 所以要是你有个系统,高峰期一秒钟过来的请求有 1 万,那一个 mysql 单机绝对会死掉。你这个时候就只能上缓存,把很多数据放缓存,别放 mysql。缓存功能简单,说白了就是Key-Value式操作,单机支撑的并发量轻松一秒几万十几万,支撑高并发 so easy单机承载并发量是 MySQL单机的几十倍

缓存是走内存的,内存天然就支撑高并发。

2. 用了缓存之后会有什么不良后果?

常见的缓存问题有以下几个:

  • 缓存与数据库双写不一致
  • 缓存血崩、缓存穿透、缓存击穿
  • 缓存并发竞争 

缓存血崩、缓存穿透、缓存击穿知识铺垫: 

缓存雪崩(Cache Avalanche)

  • 对于系统 A,假设每天高峰期每秒 5000 个请求,本来缓存在高峰期可以扛住每秒 4000 个请求,但是缓存机器意外发生了全盘宕机。缓存挂了,此时 1 秒 5000 个请求全部落数据库,数据库必然扛不住,它会报一下警,然后就挂了。此时,如果没有采用什么特别的方案来处理这个故障,DBA 很着急,重启数据库,但是数据库立马又被新的流量给打死了。

这就是缓存雪崩。

缓存穿透(Cache Penetration)

  • 对于系统 A,假设一秒 5000 个请求,结果其中 4000 个请求是黑客发出的恶意攻击。
  • 黑客发出的那 4000 个攻击,缓存中查不到,每次你去数据库里查,也查不到。
  • 举个栗子。数据库 id 是从 1 开始的,结果黑客发过来的请求 id 全部都是负数。这样的话,缓存中不会有,请求每次都“视缓存于无物”,直接查询数据库。这种恶意攻击场景的缓存穿透就会直接把数据库给打死

 

缓存击穿(Hotspot Invalid)

  • 缓存击穿,就是说某个 key 非常热点,访问非常频繁,处于集中式高并发访问的情况,当这个 key 在失效的瞬间,大量的请求就击穿了缓存,直接请求数据库,就像是在一道屏障上凿开了一个洞。
  • 解决方式也很简单,可以将热点数据设置为永远不过期或者基于 redis or zookeeper 实现互斥锁,等待第一个请求构建完缓存之后,再释放锁,进而其它请求才能通过该 key 访问数据。

3. 为啥Redis单线程模型也能效率这么高?

  • 纯内存操作
  • 核心是基于非阻塞的IO多路复用机制
  • C语言实现,一般来说,C语言实现的程序"距离"操作系统更新,执行速度相对会更快
  • 单线程反而避免了多线程的频繁上下文切换的问题,预防了多线程可能产生的竞争问题。

4. redis 的并发竞争问题是什么?如何解决这个问题?了解 redis 事务的 CAS 方案吗? 

  • 某个时刻,多个系统实例都去更新某个 key
  • 可以基于 zookeeper 实现分布式锁。每个系统通过 zookeeper 获取分布式锁,确保同一时间,只能有一个系统实例在操作某个 key,别人都不允许读和写。
  • 你要写入缓存的数据,都是从 mysql 里查出来的,都得写入 mysql 中,写入 mysql 中的时候必须保存一个时间戳,从 mysql 查出来的时候,时间戳也查出来。

  • 每次要写之前,先判断一下当前这个 value 的时间戳是否比缓存里的 value 的时间戳要新。如果是的话,那么可以写,否则,就不能用旧的数据覆盖新的数据。

http://www.lryc.cn/news/162906.html

相关文章:

  • 模型生成自动化测试用例
  • 归并排序-面试例子
  • docker 生成镜像的几个问题
  • 云计算时代的采集利器
  • 【Unity编辑器扩展】| Inspector监视器面板扩展
  • Redis配置
  • CSDN每日一练 |『小艺照镜子』『Ctrl+X,Ctrl+V』『括号上色』2023-09-11
  • React 全栈体系(四)
  • 各种UI库使用总结
  • 2023Web前端开发面试手册
  • 一文了解数据科学Notebook
  • 2020年12月 C/C++(二级)真题解析#中国电子学会#全国青少年软件编程等级考试
  • 关于ChatGPT的个人的一些观点
  • Solidity 小白教程:13. 继承
  • 队列(Queue)的顶级理解
  • 选择 Guava EventBus 还是 Spring Framework ApplicationEvent
  • Linux下go环境安装、环境配置并执行第一个go程序
  • 自定义Dynamics 365实施和发布业务解决方案 - 5. 高级自定义
  • 软件测试下的AI之路(2)
  • 前端面试的话术集锦第 7 篇:高频考点(浏览器渲染原理 安全防范)
  • 打印剪刀手“耶”(V形)
  • eNSP基本命令大全
  • java并发编程 ConcurrentLinkedQueue详解
  • msvcp110.dll是什么意思与msvcp110.dll丢失的解决方法
  • 八)Stable Diffussion使用教程:MultiDiffusion
  • java通过钉钉机器人发消息
  • Git工具本地管理总结
  • 单片机C语言实例:13、看门狗
  • 时序分解 | MATLAB实现基于SSA奇异谱分析的信号分解分量可视化
  • mysql报错:Duplicate entry ‘...‘ for key ‘field‘