SpringCache整合Ehcache
SpringCache 整合Ehcache
一 、介绍
EhCache 是一个纯Java
的进程内缓存框架
,具有快速、精干等特点,是Hibernate中默认CacheProvider。Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容器。它具有内存
和磁盘
存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器,支持REST和SOAP api等特点。
特性
- 快速、简单
- 多种
缓存策略
- 缓存数据有两级:
内存和磁盘
,因此无需担心容量问题
- 缓存数据会在虚拟机
重启
的过程中写入磁盘
- 可以通过
RMI
、可插入API等方式进行分布式缓存
- 具有缓存和缓存管理器的侦听接口
- 支持
多
缓存管理器实例
,以及一个实例的多个缓存区域
- 提供
Hibernate
的缓存实现
集成
可以单独使用,一般在第三方库中被用到的比较多(如mybatis、shiro等)ehcache 对分布式支持不够好
,多个节点不能同步
,通常和redis一块使用
灵活性
ehcache具备对象api接口
和可序列化api接口
不能序列化的对象
可以使用出磁盘存储外ehcache
的所有功能 支持基于Cache和基于Element的过期策略,每个Cache的存活时间都是可以设置和控制的。 提供了LRU、LFU和FIFO缓存淘汰算法,Ehcache 1.2引入了最少使用和先进先出缓存淘汰算法,构成了完整的缓存淘汰算法。 提供内存和磁盘存储,Ehcache和大多数缓存解决方案一样,提供高性能的内存和磁盘存储。 动态、运行时缓存配置,存活时间、空闲时间、内存和磁盘存放缓存的最大数目都是可以在运行时修改的。
应用持久化
在vm重启
后,持久化到磁盘的存储可以复原数据
Ehache是第一个引入缓存数据持久化存储的开源java缓存框架,缓存的数据可以在机器重启后从磁盘上重新获得 根据需要将缓存刷到磁盘。将缓存条目刷到磁盘
的操作可以通过cache.fiush
方法执行,这大大方便了ehcache的使用
二、ehcache 和 redis 比较
ehcache直接在jvm虚拟机中缓存,速度快
,效率高;但是缓存共享麻烦
,集群分布式应用不方便。
redis是通过socket访问到缓存服务,效率比ecache低,比数据库要快很多, 处理集群和分布式缓存方便,有成熟的方案。如果是单个应用
或者对缓存访问要求很高
的应用,用ehcache。如果是大型系统,存在缓存共享、分布式部署、缓存内容很大
的,建议用redis。
三、基本配置
所有的存储操作还是SpringCache的那一套,只是存储采取的载体不同
1、pom.xml
ehcache
spring-boot-starter-cache
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!--ehcache依赖-->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2、yaml配置
若缓存配置文件名为ehcache.xml
则无需配置此项
配置ehcache文件的存放位置
==>
spring:
cache:
ehcache:
config: classpath:ehcache/ehcache1.xml
3、ehcache配置文件
配置文件说明
==>
diskStore
- path :指定磁盘存储的位置
defaultCache
默认的缓存
cache
自定的缓存,当自定的配置不满足实际情况时可以通过自定义(可以包含多个cache节点
)
name
: 缓存的名称,可以通过指定名称
获取指定的某个Cache对象
maxElementsInMemory
:内存中允许存储的最大的元素个数
,0代表无限
个clearOnFlush
:内存数量最大时是否清除
。eternal
:设置缓存中对象是否为永久
的,如果是,超时设置将被忽略
,对象从不过期。根据存储数据的不同,例如一些静态不变的数据如省市区等可以设置为永不过时timeToIdleSeconds
: 设置对象在失效前
的允许闲置
时间(单位:秒)。仅当eternal=false
对象不是
永久有效时使用
,可选属性,默认值是0,也就是可闲置时间无穷大
。timeToLiveSeconds
:缓存数据的生存时间
(TTL),也就是一个元素从构建到消亡的最大时间间隔值,这只能在元素不是永久驻留时有效,如果该值是0就意味着元素可以停顿无穷长的时间。(和上面的两者取最小值
)overflowToDisk
:内存不足时,是否启用磁盘
缓存。maxEntriesLocalDisk
:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。maxElementsOnDisk
:硬盘最大缓存个数。diskSpoolBufferSizeMB
:这个参数设置DiskStore(磁盘缓存
)的缓存区大小
。默认是30MB。每个Cache都应该有自己的一个缓冲区。diskPersistent
:是否在VM重启时存储硬盘的缓存数据
。默认值是false。
diskExpiryThreadIntervalSeconds
:磁盘失效线程
运行时间间隔,默认是120秒。memoryStoreEvictionPolicy
:当达到maxElementsInMemory
限制时,Ehcache将会根据指定的策略
去清理内存。默认策略是LRU(最近最少使用)
。你可以设置为FIFO(先进先出
)或是LFU(较少使用)
。这里比较遗憾,Ehcache并没有提供一个用户定制策略的接口,仅仅支持三种指定策略,感觉做的不够理想。
<ehcache>
<!-- 磁盘缓存位置 -->
<!--
diskStore:为缓存路径,ehcache分为内存和磁盘 2级,此属性定义磁盘的缓存位置
user.home - 用户主目录
user.dir - 用户当前工作目录
java.io.tmpdir - 默认临时文件路径
-->
<diskStore path="java.io.tmpdir/ehcache"/>
<!--
name:缓存名称。
maxElementsInMemory:缓存最大数目
maxElementsOnDisk:硬盘最大缓存个数。
eternal:对象是否永久有效,一但设置了,timeout将不起作用。
overflowToDisk:是否保存到磁盘,当系统宕机时
timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
clearOnFlush:内存数量最大时是否清除。
memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。
FIFO,first in first out,这个是大家最熟的,先进先出。
LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。
LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
-->
<!-- 默认缓存 -->
<defaultCache
maxEntriesLocalHeap="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
maxEntriesLocalDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap"/>
</defaultCache>
<!-- 自定义缓存 -->
<!--name 为缓存名称-->
<cache name="mycache"
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="600"
timeToLiveSeconds="600"
overflowToDisk="true"
memoryStoreEvictionPolicy="LRU"/>
</ehcache>
4、实体bean(实现serializable)
@Getter
@Setter
@ToString
public class User implements Serializable {
private Integer id;
private String username;
private String address;
}
5、开启缓存
@SpringBootApplication
//启用缓存
@EnableCaching
public class JpaRestApplication {
public static void main(String[] args) {
SpringApplication.run(JpaRestApplication.class, args);
}
}
6、service层
@Service
public class UserService {
@Cacheable(cacheNames = "mycache",key = "#id")
public User getUserById(Integer id){
User user=new User();
user.setId(id);
System.out.println("id=====>"+id);
return user;
}
}
测试==>
@SpringBootTest
class JpaRestApplicationTests {
@Autowired
private UserService userService;
@Test
void contextLoads() {
User userById = userService.getUserById(1);
User userById1 = userService.getUserById(1);
System.out.println(userById);
System.out.println(userById1);
}
}