什么都缓存只会害了你
现在对于缓存的误解:
- 不管是什么性能问题,通用解决方案都是缓存 + 多线程
- redis并不是唯一的缓存方案
- 缓存并不是提高性能的唯一方案,甚至不是最优方案
你没有尝试其他方案、或者对业务不是特别了解,不要动辄上缓存。
缓存的本质
在机械硬盘时代,系统一般装在C盘。
C盘的读写速度通常比其他盘快,这是因为硬盘分区的创建顺序和物理特性决定的。在早期的机械硬盘时代,硬盘分区的创建是从外圈向内圈进行的,由于角速度固定,外圈的线速度比内圈大,因此外圈的分区(如C盘)读写速度相对较快。此外,由于C盘作为系统盘,通常位于硬盘的最外圈,这使得C盘的读写速度在所有分区中是最快的。因此,将软件安装到C盘可以加快软件的运行速度,因为软件读取速度更快,响应也更迅速。
总结:
- 内圈的读写速度可能比外圈慢2-3倍
- 我们分区的目的之一,就是将最快的外圈分配给系统使用。提高整个系统的表现
- 大量的软件会把配置文件放到C盘中
这个情况就描述了:
- 系统有多种资源ABC,都能解决一个问题
- 而我们应该尽量使用性能最高的资源A,当A无法解决的时候才会使用次一级的B
了解了这个逻辑再聊第二个场景:
电脑上有三级缓存。
缓存是指可以进行高速数据交换的存储器,它先于内存与CPU交换数据,因此速率很快。L1 Cache(一级缓存)是CPU第一层高速缓存。内置的L1高速缓存的容量和结构对CPU的性能影响较大,不过高速缓冲存储器均由静态RAM组成,结构较复杂,在CPU管芯面积不能太大的情况下,L1级高速缓存的容量不可能做得太大。一般L1缓存的容量通常在32—256KB。L2 Cache(二级缓存)是CPU的第二层高速缓存,分内部和外部两种芯片。内部的芯片二级缓存运行速率与主频相同,而外部的二级缓存则只有主频的一半。L2高速缓存容量也会影响CPU的性能,原则是越大越好,普通台式机CPU的L2缓存一般为128KB到2MB或者更高,笔记本、服务器和工作站上用CPU的L2高速缓存最高可达1MB-3MB。由于高速缓存的速度越高价格也越贵,故有的计算机系统中设置了两级或多级高速缓存。紧靠CPU的一级高速缓存的速度最高,而容量最小,二级高速缓存的容量稍大,速度也稍低 [1]。
总结:
- 一级缓存速度最快,但是由于架构的原因做不大
- 二级缓存比一级缓存大,但是慢一半,但是仍然很快
- 三级缓存比二级缓存大,但是更慢,但是仍然很快
- 当查询的时候,先查询一级缓存,然后再查询二级缓存,再查询三级缓存
对于缓存,有一个基本的逻辑:
- 为什么要用缓存,因为有性能的瓶颈,需要更快的响应速度
- 有多个不同的介质:有高速但是容量有限的高速介质,有便宜并且大量的低速介质
- 缓存就是在多种不同速度的介质存储多个副本。
- 当查询的时候优先查询高速介质,查询不到再去查询低速介质,从而提高整个系统的表现
对于网络下载,硬盘可以做网络下载的缓存。
对手硬盘来说,内存可以做硬盘的缓存。
redis使用的是内存,而传统数据库使用的介质是硬盘。
内存的性能高于硬盘
那么,可以用redis做传统数据库的缓存。
缓存跳过计算过程
缓存可以直接跳过计算过程,直接查询到结果。
比如:
- 我需要统计学生的数量,但是全表扫描太慢,我可以直接缓存一个结果
- 我需要进行一个复杂计算,我可以直接查询之前是否进行过计算,然后从缓存里面拿到结果
这个就不需要解释了。
缓存的问题
妥协
缓存是一个妥协:
- 数据库性能差
- 用了缓存承担了80%的业务
一旦业务穿透了缓存(缓存雪崩 缓存穿透 缓存击穿),那么直接打挂数据库。
这种方式很优雅嘛?
如果有其他的解决方案,我个人不是很建议直接缓存。
- 大厂有运维人员,而小厂你不能24小时盯着系统
- 缓存的复杂性会导致各种各样的问题,比如数据一致性
- 隐患是存在的,“一旦穿透缓存,数据库就挂”
复杂度
和其他方案相比,缓存并不是一层,而是多层。
- 布隆过滤器
- 缓存
- 数据库
缓存的解决方案,基本上都是三层。而且要写入多个数据源。
作为一个解决方案,缓存是“很重”的一个解决方案。
- 有几层,就需要写几次
- 当数据变更的时候,缓存变更和替换难度相对来说比较大
- 缓存一致和缓存失效是老大难问题
为什么不可行
直接高速介质?
了解了缓存的本质以后:
- 我确认这个数据是高频的
- 这个数据数据量还很小
- 为什么不全量存到高速介质?而不是缓存?
公司穷
举个例子来描述缓存的局限性:
- 我有个老旧的系统,他内存使用率已经达到了85%,内存天天爆红
- 然后我使用了redis对系统进行了优化
这怎么优化?优化不了一点。
- 缓存的本质就是“热点数据存在高速介质,提高整个系统的表现”
- 你公司没有提供有效的高速介质,高速介质已经满了
总结一句话:老板,加钱买内存。内存是高速介质,然后我可以将“热点数据”存到内存中,提高整个系统的表现。加ssd也可以啊——但是我不用改代码。
无热点查询
缓存生效的是热点数据。
- 有10%的数据属于高频数据
- 有90%的数据低频
就系统而言,缓存的提升的几个核心要素就是:“缓存的命中率”和“缓存的大小、“高速介质和低速介质的速度差异”。比较核心的是“缓存的命中率”
而命中率不取决于“技术”,而取决于“业务”。
- 哪些业务是用户的高频查询词汇
- 哪些内容是高性能消耗的内容,值得去缓存
不确认业务场景,强行进行缓存,意义不大。
缓存不等于内存 + redis
缓存可以直接跳过计算过程,直接查询到结果。
那么:比如数据库进行count(*)比较慢,所以我直接缓存结果。
能不能直接存到数据库里呢?
- 缓存并不是非要缓存在redis
- 他存到数据库也是完全没问题的
是否有其他的方案?
数据库查询慢,是否可以买高速SSD?
是否可以不用select *,减少内存的消耗
是否可以变成分布式存储?
是否可以替换为其他解决方案呢?
是否有那么高的时效性?
是否可以进行最终一致?
用户量是否有那么高?
缓存的命中率是否高?
作为解决方案而言:
- 缓存的实现难度是比较大的
- 缓存有缓存一致性、缓存雪崩、缓存穿透等
- 会引入一些复杂的中间件
你没有尝试其他方案、或者对业务不是特别了解,不要动辄上缓存。
