(转载)Java应用缓存示例

参考文章:http://zhuanlan.51cto.com/art/201705/538546.htm

参考代码:https://github.com/lebron374/cacheDemo

一、缓存简介

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

本文以Java应用缓存为示例进行讲解。

二、缓存命中率

缓存命中率是从缓存中读取数据的次数与总读取次数的比率,命中率越高越好。缓存命中率 = 从缓存中读取次数/〔总读取次数(从缓存中读取次数 + 从慢速设备上读取的次数)〕。这是一个非常重要的监控指标,如果做缓存,则应通过监控这个指标来看缓存是否工作良好。

三、缓存回收策略

1. 基于空间

即设置缓存的存储空间,如设置为10MB,当达到存储空间时,按照一定的策略移除数据。

2. 基于容量

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

3. 基于时间

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

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

4. 基于Java对象引用

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

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

注意:弱引用/软引用对象只有当没有其他强引用对象引用它时,垃圾回收时才回收该引用。即如果有一个对象(不是弱引用/软引用)引用了弱引用/软引用对象,那么垃圾回收时不会回收该引用对象。

5. 回收算法

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

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

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

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

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


两种模式如下。

● 单机时:存储最热的数据到堆缓存,相对热的数据到堆外缓存,不热的数据存到磁盘缓存。

● 集群时:存储最热的数据到堆缓存,相对热的数据到堆外缓存,全量数据存到分布式缓存。

接下来,我们看看如何在Java中使用堆缓存、堆外缓存、磁盘缓存、分布式缓存,是不是感觉像L1、L2、L3级缓存架构。

Guava Cache只提供堆缓存,小巧灵活,性能最好,如果只使用堆缓存,那么使用它就够了。

EhCache3.x提供了堆缓存、堆外缓存、磁盘缓存、分布式缓存。但是,其代码注释比较少,API还不完善(比如,2.x支持LRU、LFU、FIFO,而3.x目前还没有API设置),功能还不完善(比如,集群情况个人测试其暂时不可以生产环境使用),如果需要较稳定的API和功能,则请考虑使用EhCache2.x(不支持堆外缓存)。

MapDB是一款嵌入式Java数据库引擎和集合框架。提供了Maps、Sets、Lists、Queues、Bitmaps的支持,还支持ACID事务,增量备份。支持堆缓存、堆外缓存、磁盘缓存。

推荐阅读更多精彩内容

  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 33,933评论 11 326
  • 理论总结 它要解决什么样的问题? 数据的访问、存取、计算太慢、太不稳定、太消耗资源,同时,这样的操作存在重复性。因...
    jiangmo阅读 778评论 0 10
  • 1.JVM 堆内存和非堆内存 堆和非堆内存按照官方的说法:“Java 虚拟机具有一个堆(Heap),堆是运行时数据...
    yanzhu728阅读 232评论 0 0
  • 所有知识点已整理成app app下载地址 J2EE 部分: 1.Switch能否用string做参数? 在 Jav...
    侯蛋蛋_阅读 1,183评论 1 3
  • 저~그럼 잠깐 언니라고 불러도 돼요? 제가 의논할 언니가 없어가지고요. 언니라고 부르면 장르는 딱 하나...
    韩溏韩语阅读 39评论 0 0