缓存,笔者的理解是让数据更接近于使用者,目的是让访问速度更快。工作机制是先从缓存中读取数据,如果没有,再从慢速设备上读取实际数据并同步到缓存。那些经常读取的数据,频繁访问的数据、热点数据、IO瓶颈数据、计算昂贵的数据、符合5分钟法则和局部性原理的数据都可以进行缓存。如CPU-L1/L2/L3-内存-磁盘就是一个典型的例证,CPU需要数据时先从L1读取,如果没有找到,则查找L2/L3读取,如果没有,则到内存中查找,如果还没有,回到磁盘中查找。用过Maven的应该知道,加载依赖的时候,先从本机仓库找,再从本地服务器仓库找,最后到远程仓库服务器找。

雷小天博客

说到缓存,一个名词必须要提,那就是缓存命中率。什么是缓存命中率?缓存命中率是从缓存中读取数据的次数与总读取次数的比例,命中率越高越好。缓存命中率=从缓存中读取次数/总读取次数(从缓存中读取次数+从慢速设备上读取次数)。这是一个非常重要的监控指标,如果做缓存,则应该通过监控这个指标来判断缓存是否工作良好。

雷小天博客

下面再来说下缓存回收策略。根据不同的指标、场景来判断是否缓存回收,下面几种策略可以了解下。


基于空间:基于空间指缓存设置了存储空间,如设置为10MB,当达到存储空间上限时,安装一定的策略移除数据。


基于容量:基于容量指缓存设置了最大大小,当缓存的条目超过最大大小时,按照一定的策略移除数据。


基于时间:


TTL(Time To Live):存活期,即缓存数据从创建开始直到到期的一个时间段(不管在这个时间段内有没有被访问,缓存数据都将过期)


TTI(Time To Idle):空闲期,即缓存数据多久没被访问后移除缓存的时间。


基于Java对象引用:


软引用:如果一个对象是软引用,那么当JVM堆内存不足时,垃圾回收器可以回收这些对象。软引用合适用来做缓存,从而当JVM堆内存不足时,可以回收这些对象腾出一些空间供强引用对象使用,从而避免OOM。


弱引用:当垃圾回收器回收内存时,如果发现弱引用,则将它立即回收。相对于软引用,弱引用有更短的生命周期。


回收算法


使用基于空间和基于容量的缓存会使用一定的策略移除旧数据,常见的如下。


FIFO(First In First Out):先进先出算法,即先放入缓存的先被移除。


LRU(Least Recently Used):最近最少算法,使用时间距离现在最久的那个被移除。


LFU(Least Frequently Used):最不常用算法,一定时间段内使用次数最少的那个被移除。


实际应用中基于LRU的缓存居多,如Guava Cache、Ehcache支持LRU。