高并发下的各种缓存

前言

Cache在大家最开始接触开发的时候应该就听过许多了,比如浏览器缓存、OS中的缓存、什么缓存一致性等等,各式各样的Cache,看起来各种高大上的样子,看着群里或者某乎的大佬们在不断的讨论或者推缓存相关的blog。
近期对于缓存相关研究了不少,自己也在试着写一个Cache中间件来研究下。过程中整理了一下,准备做成一个系列文章发一下,也希望大家给我多多指正。
在正式开始开始写缓存之前,当然是先研究领域内现有的一些Cache 相关的内容,作为一个引言。
后续分别从OS 中的缓存、JVM中的缓存、Web 应用中常见缓存、现有常作为独立缓存的Redis/MemCache、InnoDB中的存储引擎、浏览器中的缓存、分布式缓存的实现案例 进行对应的浅析及相应Cache设计主题的引入。下面先大体的介绍一下各个场景及实现方式,后续会独立推送对应的浅析文章。

Cache 于操作系统

Cache 最早的出现是在操作系统中,致力于解决速度的大幅度差异而效率低下 引出的一种概念。
在早期操作系统中,最核心的速度差异在于 CPU与主存 & 主存与磁盘 CPU与磁盘 之间的速度差异。往往硬件方面的限制因素会更多一些,比如说昂贵的寄存器、相对昂贵的主存介质,CPU速度与主存读取速度、主存速度与磁盘IO的发展速度不均衡,这些几乎是一些无可奈何的客观因素,尽管技术圈的大家一直在为此努力。因为这些因素的限制,我们不得不想出一些策略来均衡一些短板的出现,其中诞生了一些复用技术、中断、虚拟内存、缓存等均衡及提升计算机整体瓶颈与资源利用率的技术。
这里我们要说的是缓存,从我们计算机的心脏CPU开始说起,CPU一直是速度领先于计算机其他组件的一个存在,算是第一数量级,大家学过 计算机组成或者计算机系统的话应该非常清楚,这里先不展开描述,主存整体来说是第二数量级的存在,现阶段磁盘大多为仍为机械结构更是慢的惊人,即使是SSD虽然对于普通机械磁盘来说速度上快一点但是仍然不足,之间的差异算是鸿沟。
为实现速度的均衡也就是让主存能够不太拖CPU的后腿,磁盘不拖CPU及主存的后腿诞生了由 寄存器 -> 高速缓存 -> 主存 -> 磁盘 这样的一种结构,正在使用的数据通常是存在于寄存器中的,最近高频使用的数据是存在于高速缓存中,最近可能会使用的高频数据是存放在主存中的,这种描述虽然不太准确,但是更容易让大家感受缓存的设计思路。根据数据的使用频次及对应材质的速度差异进行分析 做到物尽其用,发挥各自的优势,比如速度快或者低廉的价格,使计算机能够以更低的价格发挥出更高的性能。
其中提到的如何分析材质及数据的使用频次就引出了对应Cache的设计思想及对应解决的问题。
比如说

设备:

磁盘对应的是最廉价的设备,可以以非常低的价格来存储更多数据。主存相对来说要贵一些,但是速度上已经有了质的提升,CPU中的寄存器几乎与CPU速度一致但是价格非常昂贵。

数据:

数据的使用频次差异性非常强,比如说我们操作系统所需的程序代码,这几乎是高频使用的,而我们的计算机上的用户应用 使用频次算是中等,用户应用所需要的数据频次就会更低一些,我们存储在磁盘上的文本图像等使用频率更低。
现在我们就可以让速度最快最昂贵容量最小的寄存器来储存最近需要执行的指令,让高速缓存存储正在执行的所需的指令集,让主存来存储我们最近可能需要运行的程序及数据,让能迅速寻址的那部分磁盘来存储稍低频次所使用的数据,让磁盘其他部分来存储那些需要保存但是几乎不常使用的数据。这样CPU与内存、CPU与磁盘、主存与磁盘之间的速度差异在运行过程中就不再那么的明显,我们要做的只是在恰当的时机完成不同介质之间的数据交换,让快的设备去访问速度稍次的设备。
这算是Cache大体的实现思想或者说思路,其中所谓的频次、材质只是举例,在现实问题中可能是CPU与磁盘,也可能是也可能是不同的服务器站点,也可能是发消息方与接受方处理速度的差异,我们需要针对具体的问题进行对应的抽象,本质来说就是速度上的差异。
例子中提到了不同介质之间数据的交换来保证能够相邻访问(缓存命中率问题),这就引出了Cache所要解决的几个核心问题及Cache对应的实现。
1、如何判断速度的频次?(是否为热点数据)
2、何时把热点数据放入缓存中?
3、热点数据应该放在哪一部分?
4、应该把哪个数据移走?(数据的淘汰策略)
5、移走的数据应该存放于何处?(数据的降级问题)
在我们的操作系统中已经完成了对应的策略,具体的实现会在《浅析 操作系统中的缓存》中阐述~
这里仅仅是大体描述一下及对应的背景及应用介绍。

Cache 于JVM

这里要说的是JVM中缓存抽象思想的使用,缓存最主要的解决速度差异的问题以提升整体效率,在JVM中也是这样的。
Java 是一种解释型语言,其实这个话不能说的如此绝对,自动JIT出现之后,Java 中的绝大部分热点代码是编译为机器码放在缓存区中的。这其实就是一种缓存思想的使用。
最初Class 文件是存放于磁盘或者从网络中获取的,频次较低。
当我们需要使用一部分代码从磁盘或者网络中加载并且解析链入内存,以供我们快速的使用,频次偏高。而一个文件完全不使用后又会被清楚内存,详见class的清理。
当工程中某一部分代码已经被鉴定为高频使用时,这一块代码将会直接被编译为机器码为下次直接使用而不是再次解释做准备,频次最高。
而这三种方式的速度也是依次提升的。使用频次的最高的以最快的方式使用。
而对应的什么样的代码应该被缓存,这就取决于JIT的热点代码判断策略。并且这里存在一个很经典的现实问题,叫做jvm的代码缓存耗尽导致性能下降。
以上问题的解释后续会详细的给出。
篇幅太长········
Cache 于Web 应用、Cache 于Redis/MemCache、Cache 与InnoDB 存储引擎、Cache 于浏览器、Cache 于分布式系统
这几个就先不详细介绍了,不小心写的有点长。后续单独推送~

你可能感兴趣的:(高并发下的各种缓存)