springboot中配置使用EhCache做持久化缓存(内存+硬盘)

作者: ʘᴗʘ发布时间:2021-11-17 16:56 浏览量:957 点赞:823 售价:0

前言

springboot中我们最常用的缓存数据库可能是redis、memcached等。但是,redis适合的场景是“小数据,高频访问”,有一些场景则不适合。比如你想把你的CMS系统、博客系统提速,做全站缓存。这时候你需要一个可以保存数据到服务器本地内存、磁盘的缓存工具。本文推荐使用EhCache来完成“大小数据、高频访问”的场景需求。

相比Redis,EhCache对数据的存取都在服务器本机,所以没有网络开销。但缺点也很明显,就是服务器的内存大小、磁盘大小决定了EhCache能够存放多少数据。还有个缺点,就是在分布式环境下,因为缓存保存在本机,所以无法与集群内的其他机器共享。(针对上面提到的CMS系统静态化页面,其实CDN是更好的解决方案)

在Springboot中引入EhCache

一、maven引入相关依赖包

  • 引入EhCache包

    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache</artifactId>
        <version>2.10.9.2</version>
    </dependency>
    
  • 引入Springboot cache包

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    

二、配置Springboot application.properties

需在在springboot的配置文件application.properties中指定使用EhCache作为缓存,并指定EhCache的配置文件所在路径。代码如下:

spring.cache.type=ehcache
spring.cache.ehcache.config=classpath:ehcache.xml

三、@EnableCaching开启Springboot的缓存

在Springboot项目的Main函数上,标记@EnableCaching注解,开启缓存。如下图所示:

springboot中配置使用EhCache做持久化缓存(内存+硬盘)

四、配置EhCache配置文件ehcache.xml

在Springboot项目的resources目录下,新建一个名为ehcache.xml的配置文件,配置ehcache。内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <!-- 磁盘缓存文件的路径 -->
    <diskStore path="./tmp/Ehcache"/>

    <!--
        默认的缓存配置:
        该配置将应用于 通过CacheManager.add(String cacheName)
        以编程方式创建的缓存
    -->
    <defaultCache eternal="true"
                  maxElementsInMemory="1"
                  maxElementsOnDisk="0"
                  overflowToDisk="true"
                  diskPersistent="true">
    </defaultCache>


    <cache name="indexArticleList"
           eternal="false"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="3600"
           maxElementsInMemory="3"
           maxElementsOnDisk="0"
           overflowToDisk="true"
           diskPersistent="true">
    </cache>

    <cache name="articleDetails"
           eternal="false"
           timeToIdleSeconds="36000"
           timeToLiveSeconds="36000"
           maxElementsInMemory="5"
           maxElementsOnDisk="0"
           overflowToDisk="true"
           diskPersistent="true">
    </cache>

    <cache name="websiteConfig"
           eternal="false"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="3600"
           maxElementsInMemory="30"
           maxElementsOnDisk="0"
           overflowToDisk="true"
           diskPersistent="true">
    </cache>

</ehcache>

代码介绍:

  • 每一个<cache></cache>标签,都是一个缓存单元。后续你在springboot中使用@Cacheable@CachePut等注解时,注解内的value、name就是这里cache标签的name。
  • diskStore是磁盘缓存文件路径

具体参数:

  • name:缓存名称
  • maxElementsInMemory:内存中最大缓存对象数
  • maxElementsOnDisk:硬盘中最大缓存对象数,若是0表示无穷大
  • eternal:true表示对象永不过期,此时会忽略timeToIdleSeconds和timeToLiveSeconds属性,默认为false
  • overflowToDisk:true表示当内存缓存的对象数目达到了maxElementsInMemory界限后,会把溢出的对象写到硬盘缓存中。注意:如果缓存的对象要写入到硬盘中的话,则该对象必须实现了Serializable接口才行。
  • diskSpoolBufferSizeMB:磁盘缓存区大小,默认为30MB。每个Cache都应该有自己的一个缓存区。
  • diskPersistent:是否在VM重启时存储硬盘的缓存数据。默认值是false。
  • diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认为120秒
  • timeToIdleSeconds: 设定允许对象处于空闲状态的最长时间,以秒为单位。当对象自从最近一次被访问后,如果处于空闲状态的时间超过了timeToIdleSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清空。只有当eternal属性为false,该属性才有效。如果该属性值为0,则表示对象可以无限期地处于空闲状态
  • timeToLiveSeconds:设定对象允许存在于缓存中的最长时间,以秒为单位。当对象自从被存放到缓存中后,如果处于缓存中的时间超过了 timeToLiveSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清除。只有当eternal属性为false,该属性才有效。如果该属性值为0,则表示对象可以无限期地存在于缓存中。timeToLiveSeconds必须大于timeToIdleSeconds属性,才有意义
  • memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。

常用场景:

  1. 数据存储到内存和硬盘中,当springboot重启时,内存中的数据要转移到硬盘中保留:配置diskPersistent为true、overflowToDisk为true,当内存中的数据超过maxElementsInMemory后,就保存到硬盘中。重启springboot后数据仍在硬盘中。
  2. 数据只存储在硬盘:设置maxElementsInMemory为1即可

五、在springboot中通过@Cacheable、@CachePut等使用EhCache缓存

经过上面的步骤配置好EhCache后,你就可以使用springboot自身的缓存注解来调用EhCache了。网上关于springboot常用的几个缓存注解介绍很多,这里不做详细介绍了,简介一下:

  • @Cacheable:先检查缓存是否存在,不存在的话,执行被注解的函数。结果再更新到缓存。
  • @CachePut:不管缓存是否存在,都执行被注解的函数,然后把结果更新到缓存。

六、常见错误

  1. 所有要被缓存的类,包括类里面的子类,都得实现Serializable接口。
  2. EhCache磁盘缓存目录要有写权限。
  3. 从EhCache中取出的复杂Object对象,如果后续要修改,请先clone一份再修改,否则该修改会被回写EhCache(该问题刚遇到,还没深入了解)。

疑难杂症

作者在使用EhCache的过程中,发现如果遇到意外断电等特殊情况,EhCache保存在磁盘中的数据有一定概率无法再次访问。通过研究发现,数据本身还是存在的,出问题的是EhCache数据目录中的index文件。通过网上查找资料,说是在springboot程序启动的时候,设置一个shutdown ehcache的参数即可,代码如下:

System.setProperty(net.sf.ehcache.CacheManager.ENABLE_SHUTDOWN_HOOK_PROPERTY, "true");

作者正在测试该设置是否有用,后续更新在这里。

2021-12-16更新:作者实测,以上配置可以解决EhCache意外停止导致的数据丢失问题。

版权声明:《springboot中配置使用EhCache做持久化缓存(内存+硬盘)》为CoderBBB作者「ʘᴗʘ」的原创文章,转载请附上原文出处链接及本声明。

原文链接:https://www.coderbbb.com/articles/41

其它推荐: