缓存简介
众所皆知,缓存在计算机技术中利用地非常宽泛。如 CPU->L1/L2/L3-> 内存 -> 磁盘就是个典型例子。那些频繁拜访的数据、热点数据、IO 耗时长的数据都能够放在缓存中,应用程序先从缓存中读取,如果没有名字,再从实在数据源读取,并搁置在缓存中。缓存对于撑持高并发零碎,起到了十分要害的作用。
缓存命中率
缓存命中率 = 从缓存中胜利读取的次数 / 总读取次数(从缓存读次数 + 从实在数据源读次数)。这是一个十分重要的监控指标,它能够帮忙咱们查看缓存是否工作正当且良好,如果缓存命中率很低,那么咱们应该从新扫视,是否哪里出了问题?这类数据是否应该放在缓存中?
缓存回收策略
1. 基于空间
基于空间指的是缓存设置了存储空间大小,如 20MB,当缓存数据达到设置的空间下限时,则依照策略淘汰数据。
2. 基于容量
基于容量指的是缓存设置了数量条目限度。当缓存的条目超过数量下限时,则依照策略淘汰数据。
3. 基于工夫
基于工夫分为两类:
TTL(Time To Live):缓存的存活工夫,当缓存数据被放入存活到肯定时间段时,会主动到期移除。
TTI(Time To Idle):缓存的闲暇期,即缓存通过肯定工夫没有被拜访,就会主动被移除。
4. 基于 Java 援用
这里次要指的是软援用和弱援用。
软援用 :当 JVM 在垃圾回收时,如果内存不足,则会回收软援用指向的对象内存空间。
弱援用:当 JVM 在垃圾回收时,发现了弱援用,则会回收弱援用指向的对象内存空间。相比软援用,它不会判断内存是否够用,都会回收空间。
5. 基于算法
常见的缓存淘汰算法有如下:
FIFO: 先进先出算法。即最先放入的数据最先被淘汰。
LRU: 最近起码被应用算法。上次应用工夫间隔当初最久的那个数据被淘汰。
LFU: 最不罕用算法。即肯定时间段内应用次数(频率)起码的那个被淘汰。
Java 缓存类型
堆内缓存 :次要指软援用和弱援用缓存的对象,开源的 Guava Cache 有相干实现。
堆外缓存 :顾名思议,不依赖 Java 堆空间,只受限本机内存大小。EhCache 有相干实现。
磁盘缓存 :缓存数据寄存在磁盘上,相比放在内存中,磁盘缓存即便断电数据也可复原。
分布式缓存:下面的缓存个别指的是过程内缓存,但分布式系统中,往往须要共享缓存数据,如应用高性能的 Redis 分布式缓存。
缓存应用模式
Cache-Aside
业务代码围绕着 Cache 写,由业务代码来保护缓存数据。
Cache-as-SoR
SoR(system-of-record):即真正存储数据的数据源,如 mysql 数据库等。
Cache-as-SoR 是把 Cache 当做 SoR, 所有操作都是针对 Cache 进行,如果缓存未命中,则交给 Cache 组件去回源,而不是业务代码做回源的操作。有三种相干的实现:Read-Through、Write-Through、Write-Behind。
Read-Through
即业务代码调用 Cache,如果命中则返回,未命中则由 Cache 组件去从数据源加载数据,通常配置一个 CacheLoader 去做这个回源的操作。
Write-Through
也称为穿透写 / 直写模式,业务代码首先调用 Cache 写操作的 API,而后由 Cache 负责写数据库和写缓存,而不是业务代码。通常须要配置一个 CacheLoaderWriter 来做这个操作。
Write-Behind
也称为 Write-Back,即回写模式。与 Write-Through 不同的是,这里的写 SoR 和写 Cache 是异步的,而不是同步。此外,Write-Behind 还反对批量写。
Copy Pattern
有两种模式:Copy-On-Read 和 Write-On-Read。与 CopyOnWriteArrayList 思维相似,写操作时先复制一份源数据,而后在复制的数据上做写操作,防止多线程环境下的并发批改问题。
参考资料:
《亿级流量网站架构核心技术》