Ehcache Java 缓存框架
详解
下图是 Ehcache 在应用程序中的位置:
Ecache 是一个广泛使用的 Java 缓存框架,能够有效提升应用性能,并减少与后端数据库的交互次数。它采用了一系列高级缓存策略,包括内存缓存、磁盘缓存、分布式缓存等,并提供了丰富的 API 和工具类,可以方便地完成缓存的读写和管理。快速:Ecache 采用了一系列高效的缓存策略,能够实现快速的数据访问和读写,从而提高应用程序的性能。可扩展:Ecache 支持分布式缓存,可以方便地扩展到多台服务
一、Ehcache 简
Ehcache 是一个广泛使用的 Java 缓存框架,能够有效提升应用性能,并减少与后端数据库的交互次数。它采用了一系列高级缓存策略,包括内存缓存、磁盘缓存、分布式缓存等,并提供了丰富的 API 和工具类,可以方便地完成缓存的读写和管理。
Ehcache 主要有以下特点:
- 快速:Ehcache 采用了一系列高效的缓存策略,能够实现快速的数据访问和读写,从而提高应用程序的性能。
- 可扩展:Ehcache 支持分布式缓存,可以方便地扩展到多台服务器上,从而提高系统的容错性和吞吐量。
- 可靠性高:Ehcache 内置了多种缓存策略,支持数据持久化和恢复,同时还提供了完善的故障检测和纠正机制,从而保证了缓存数据的可靠性和稳定性。
- 易于使用:Ehcache 提供了丰富的 API 和工具类,可以方便地完成缓存的读写和管理。同时,它还与多种框架和技术集成,如 Spring、Hibernate、MyBatis 等,使得用户可以更加便捷地使用 Ecache。
二、工作原理
1. 缓存写入
当应用程序向 Ehcache 中写入数据时,Ehcache 会首先检查该数据是否已经存在于缓存中。如果数据已经存在于缓存中,则更新该数据;否则,将该数据写入缓存。以下是 Ehcache 缓存写入的详细流程。
-
当应用程序请求写入一个数据项到 Ehcache 中时,这个数据项被传递给Ehcache API。
-
Ehcache首先根据该数据项的键值对定位其对应的Cache对象。
-
Ehcache根据配置中的缓存策略,比如是否应该在缓存中创建一个新的元素,以及新元素是否会淘汰老的元素。
-
如果需要创建一个新缓存元素,则Ehcache创建一个新的元素并将其添加到Cache对象中。
-
如果缓存中已经存在该元素,Ehcache会根据缓存策略对该元素进行更新或替换。
-
Ehcache将更新后的Cache对象返回给应用程序。
2. 缓存查找
当应用程序需要查询缓存中的数据时,Ehcache 首先会检查该数据是否存在于缓存中。如果数据存在于缓存中,则直接返回缓存数据;否则,从数据库或其他资源获取数据,并将其存入缓存中。以下是 Ehcache 缓存查找的详细流程。
-
当应用程序请求从 Ehcache 中读取一个数据项时,这个请求被传递给Ehcache API。
-
Ehcache首先根据该数据项的键值对定位其对应的Cache对象。
-
Ehcache检查该数据项是否已经存在于缓存中。
-
如果数据项存在于缓存中,Ehcache可以直接将其返回给应用程序。
-
如果数据项不存在于缓存中,Ehcache就需要从数据库或其他数据源(如文件、网络等)中获取数据。
-
获取到数据后,Ehcache会将其添加到缓存中并返回给应用程序。
3. 缓存过期和驱逐
Ehcache 提供了多种缓存失效策略,例如基于时间的缓存失效、基于访问的缓存失效、基于大小的缓存失效等。当缓存数据过期或缓存空间不足时,Ehcache 会选择一部分缓存元素进行驱逐以腾出更多的内存空间。以下是 Ehcache 缓存过期和驱逐的详细流程。
-
Ehcache会周期性地扫描缓存中的元素来标记那些已经过期的元素。
-
Ehcache根据缓存策略(如基于时间、基于访问、基于大小等)判断哪些缓存元素应该被驱逐。
-
驱逐过程通常是异步执行的,Ehcache会在后台线程上执行这个操作。
4. 缓存持久化
Ehcache 还提供了缓存持久化功能,它可以将缓存中的数据持久化到磁盘或者其他数据源。在应用程序重启或者缓存失效后,Ehcache 可以从持久化存储中恢复数据,从而保证数据的完整性和可靠性。以下是 Ehcache 缓存持久化的详细流程。
-
Ehcache使用磁盘存储或数据库等持久化技术来存储缓存数据。
-
当缓存中的数据更新时,Ehcache会自动将此数据持久化到持久化存储中。
-
在应用程序重启或者缓存失效后,Ehcache会从持久化存储中读取缓存数据并重新加载到内存中。
三、Ehcache 的基本使用
Spring Boot 中集成 Ehcache 缓存代码示例。
1. 添加 Ehcache 依赖
首先需要在项目的 pom.xml
文件中添加 Ehcache 缓存依赖,如下所示:
<dependency><groupId>org.ehcache</groupId><artifactId>ehcache</artifactId><version>3.9.3</version> </dependency>
2. 配置 Ehcache
在 application.yml
或 application.properties
配置文件中添加 Ehcache 的配置信息,例如:
spring:ehcache:config: classpath:ehcache.xml
在上述配置中,我们指定了 Ehcache 的配置文件为 classpath:ehcache.xml
,这样 Spring Boot 在启动时会自动加载该配置文件。
接下来,需要在 src/main/resources
目录下添加 ehcache.xml
配置文件,并编写相应的 Ehcache 配置信息。例如,下面是一个简单的 Ehcache 配置文件:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://www.ehcache.org/v3"xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd"><cache alias="myCache"><key-type>java.lang.String</key-type><value-type>java.lang.String</value-type><expiry><ttu value="10m"/></expiry><heap>100</heap></cache></config>
在上述配置中,我们定义了一个名为 myCache
的缓存,配置了键值类型、过期时间、最大存储数量等参数。
3. 使用 Ehcache
在完成 Ehcache 的配置后,就可以在 Spring Boot 中使用 Ehcache 缓存了。Spring Boot 提供了 @Cacheable
、@CachePut
、@CacheEvict
等注解来简化缓存操作,同时也支持基于缓存管理器的编程方式。
3.1 基于注解的缓存
首先介绍一下基于注解的缓存。Spring Boot 中,可以通过 @Cacheable
、@CachePut
和 @CacheEvict
注解来实现对缓存的读写和删除操作。
3.1.1 @Cacheable
注解
@Cacheable
注解用于指定方法的返回值可被缓存,同时也可以指定缓存的 key 和 cacheNames,例如:
@Service public class UserService {@Cacheable(cacheNames = "myCache", key = "#userId")public User getUserById(String userId) {System.out.println("get user by id: " + userId);return new User(userId, "张三");}}
在上述代码中,我们使用 @Cacheable
注解将 getUserById()
方法返回值进行缓存,并指定了缓存的 key 为 userId
,缓存名称为 myCache
。
3.1.2 @CachePut
注解
@CachePut
注解用于更新缓存中的数据,例如:
@Service public class UserService {@CachePut(cacheNames = "myCache", key = "#user.id")public User updateUser(User user) {System.out.println("update user: " + user);return user;}}
在上述代码中,我们使用 @CachePut
注解更新了缓存中键为 user.id
的缓存数据。
3.1.3 @CacheEvict
注解
@CacheEvict
注解用于清除缓存中的数据,例如:
@Service public class UserService {@CacheEvict(cacheNames = "myCache", key = "#userId")public void deleteUserById(String userId) {System.out.println("delete user by id: " + userId);}}
在上述代码中,我们使用 @CacheEvict
注解清除了缓存中键为 userId
的缓存数据。
3.2 基于缓存管理器的编程方式
除了注解方式外,还可以基于缓存管理器的编程方式来实现对缓存的读写和删除操作。Spring Boot 中,可以使用 CacheManager
和 Cache
接口来实现缓存的管理和操作。
3.2.1 注入缓存管理器
使用基于缓存管理器的编程方式,首先需要注入使用的缓存管理器,例如:
@Service public class UserService {@Autowiredprivate CacheManager cacheManager;}
在上述代码中,我们注入了 CacheManager
类型的 cacheManager
实例。
3.2.2 获取缓存实例
获取缓存实例的方式也很简单,可以通过缓存管理器的 getCache()
方法获取:
@Service public class UserService {@Autowiredprivate CacheManager cacheManager;public User getUserById(String userId) {Cache cache = cacheManager.getCache("myCache");Element element = cache.get(userId);if (element != null) {System.out.println("get user by id from cache: " + userId);return (User) element.getObjectValue();}System.out.println("get user by id from db: " + userId);User user = new User(userId, "张三");cache.put(new Element(userId, user));return user;}}
在上述代码中,我们使用缓存管理器的 getCache()
方法获取名为 myCache
的缓存实例。然后,我们使用缓存实例的 get()
方法获取指定 key 对应的缓存元素,如果获取到了元素,则直接返回缓存数据;否则,从数据库中获取数据,并将其存入缓存中。
3.2.3 缓存操作
除了读取缓存数据外,我们还可以使用缓存实例的 put()
方法向缓存中添加数据,使用 remove()
方法删除缓存数据,例如:
@Service public class UserService {@Autowiredprivate CacheManager cacheManager;public User updateUser(User user) {Cache cache = cacheManager.getCache("myCache");cache.put(new Element(user.getId(), user));return user;}public void deleteUserById(String userId) {Cache cache = cacheManager.getCache("myCache");cache.remove(userId);}}
在上述代码中,我们分别使用了缓存实例的 put()
和 remove()
方法对缓存数据进行了更新和清除操作。
四、 Ehcache 的高级用法
1. 缓存策略
Ehcache 提供了多种缓存策略,可以根据实际需求选择合适的策略。其中,最常用的包括:
- LRU(Least Recently Used):移除最近最少使用的缓存项。
- LFU(Least Frequently Used):移除最不经常使用的缓存项。
- FIFO(First In, First Out):先进先出,即移除最早加入的缓存项。
- TTL(Time To Live):根据缓存项的过期时间来判断是否要移除该项。
- 随机替换:随机选择一项进行移除。
在 Ehcache 中,默认使用的是 LRU 策略。如果需要更改策略,可以在 ehcache.xml
配置文件中进行设置。
2. 内存缓存和磁盘缓存
Ehcache 支持将缓存数据同时存储在内存和磁盘上,并根据实际情况调整数据的存储位置。例如,可以将经常访问的缓存数据存储在内存中,而不常使用的数据则存储在磁盘上,从而达到提高缓存效率和降低成本的目的。
在 ehcache.xml
配置文件中,可以通过 <heap>
、<offheap>
和 <disk>
标签来定义缓存存储的位置。例如,下面的配置将缓存数据存储在内存中,并限制最大存储数量为 100 个:
<cache alias="myCache"><key-type>java.lang.String</key-type><value-type>java.lang.String</value-type><heap>100</heap> </cache>
如果需要将部分缓存数据存储在磁盘上,可以添加如下配置:
<cache alias="myCache"><key-type>java.lang.String</key-type><value-type>java.lang.String</value-type><heap>10</heap> <!-- 最多存储 10 个缓存项到堆中 --><offheap>1MB</offheap> <!-- 最多存储 1MB 缓存项到堆外内存中 --><diskPersistent>true</diskPersistent> <!-- 开启磁盘持久化,即使程序重启后,缓存仍然有效 --><diskSpoolBufferSizeMB>30</diskSpoolBufferSizeMB> <!-- 磁盘缓存区大小,缓存数据先以临时文件的形式写入磁盘缓存区,待达到一定阈值后再写入磁盘 --><diskExpiryThreadIntervalSeconds>120</diskExpiryThreadIntervalSeconds> <!-- 磁盘数据过期检测间隔时间,单位为秒 --><maxEntriesLocalDisk>1000</maxEntriesLocalDisk> <!-- 磁盘缓存最大存储数量 --> </cache>
3. 分布式缓存
Ehcache 提供了分布式缓存的支持,并可以通过 RMI、JMS、Spring 等方式进行实现。在分布式环境下,每个缓存节点都可以通过网络访问远程节点上的缓存数据,从而实现数据共享和分布式缓存的目的。
在 ehcache.xml
配置文件中,可以添加 <cacheManagerPeerProviderFactory>
和 <cacheManagerPeerListenerFactory>
标签来定义缓存节点的配置信息。例如,下面的配置定义了一个名为 myCache
的缓存,采用了 RMI 方式实现分布式缓存:
<cache-manager-peer-provider-factory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"properties="peerDiscovery=automatic,multicastGroupAddress=230.0.0.1,multicastGroupPort=4446,timeToLive=32"/><cache-manager-peer-listener-factory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"properties="port=40001,socketTimeoutMillis=2000"/><cache alias="myCache"><key-type>java.lang.String</key-type><value-type>java.lang.String</value-type><diskPersistent>true</diskPersistent><diskSpoolBufferSizeMB>30</diskSpoolBufferSizeMB><maxEntriesLocalDisk>1000</maxEntriesLocalDisk><cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"properties="replicateAsynchronously=true,replicatePuts=true,replicateUpdates=true,replicateUpdatesViaCopy=false,replicateRemovals=true"/> </cache>
在上述配置中,我们首先定义了一个 RMI 的缓存管理器提供者工厂 RMICacheManagerPeerProviderFactory
和一个 RMI 的缓存管理器监听器工厂 RMICacheManagerPeerListenerFactory
,并分别指定了自动发现、组播地址、端口等相关参数。
接着,我们定义了名为 myCache
缓存添加了一个 cacheEventListenerFactory
属性,用于定义缓存事件的处理方式,即使用 RMICacheReplicatorFactory
实现缓存数据的复制和同步。
需要注意的是,分布式缓存的配置和使用与单机缓存有所不同,同时也需要考虑到网络通信等问题,因此更加复杂和耗费资源。在选择是否需要使用分布式缓存时,需要权衡其带来的性能、复杂性和成本等因素。
相关文章:

Ehcache Java 缓存框架
详解 下图是 Ehcache 在应用程序中的位置: Ecache 是一个广泛使用的 Java 缓存框架,能够有效提升应用性能,并减少与后端数据库的交互次数。它采用了一系列高级缓存策略,包括内存缓存、磁盘缓存、分布式缓存等,并提供了…...

详解Spring IoCDI(二)
目录 承接上文:详解Spring IoC&DI (一) 1.IoC详解 1.1方法注解Bean 1.2方法注解要配合类注解使用 1.3定义多个对象 1.4重命名Bean 1.5扫描路径 2.DI详解 2.1DI与IoC的关系 2.2属性注入 2.3构造方法注入 2.4Setter注入 2.5 三…...

说明白计算机网络之TCP的流量控制与拥塞控制之慢开始算法与拥塞避免算法
TCP的流量控制 利用滑动窗口实现流量控制 设A向B发送数据,连接建立时候,B告诉A自身的接收窗口大小,A的发送窗口大小不能超过接收方B的窗口大小 流量控制:发送方发送速率不要太快,要让接收方来得及接收。窗口大小的单…...

这款信创FTP软件,可实现安全稳定的文件传输
信创,即信息技术应用创新,2018年以来,受“华为、中兴事件”影响,国家将信创产业纳入国家战略,并提出了“28n”发展体系。“8”具体指金融、石油、电力、电信、交通、航空航天、医院、教育等主要行业。目前企业使用比较…...

代码随想录算法训练营第十天|232.用栈实现队列、225. 用队列实现栈
232.用栈实现队列 题目链接:232. 用栈实现队列 文档讲解:代码随想录 状态:写出来 ,但差强人意 思路: 定义两个容器,可以是Stack,也可以是Deque,stackIn相当于临时容器,用来存放元素&…...

STM32 IIC协议
本文代码使用 HAL 库。 文章目录 前言一、什么是IIC协议二、IIC信号三、IIC协议的通讯时序1. 写操作2. 读操作 四、上拉电阻作用总结 前言 从这篇文章开始为大家介绍一些通信协议,包括 UART,SPI,IIC等。 UART串口通讯协议 SPI通信协议 一、…...
Java生成随机数的几种方式
随机数,在一些特殊场景下,是非常常用的。比如一些测试和验证场景、安全加密、随机抽样等都有随机数的‘身影’。 一、 使用java.util.Random类 java.util.Random类提供了更全面的随机数生成功能,包括随机整数、随机浮点数、随机布尔值等。 p…...
【面试】什么是Java虚拟机
目录 1. 说明2. 关键点 1. 说明 1.Java虚拟机(Java Virtual Machine,简称JVM)是运行所有Java程序的抽象计算机,是Java语言的运行环境。2.JVM是Java平台无关性的关键,它允许Java程序在任何支持JVM的硬件和操作系统上运…...
Go 语言的基本构成、要素与编写规范
Go 语言,作为由 Google 开发的现代编程语言,以其简洁、高效和并发编程能力而著称。在构建高性能分布式系统和现代软件开发中,Go 语言正日益受到欢迎。本篇文章将详细探讨 Go 语言程序结构的各个要素,包括函数定义、注释规范、数据…...

从了解到掌握 Spark 计算框架(二)RDD
文章目录 RDD 概述RDD 组成RDD 的作用RDD 算子分类RDD 的创建1.从外部数据源读取2.从已有的集合或数组创建3.从已有的 RDD 进行转换 RDD 常用算子大全转换算子行动算子 RDD 算子综合练习RDD 依赖关系窄依赖宽依赖宽窄依赖算子区分 RDD 血统信息血统信息的作用血统信息的组成代码…...

香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试(三)
整期笔记索引 香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试(一) 香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试(二) 香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试(…...
【git】常用命令
删除 删除本地分支: // 删除本地分支 git branch -d localBranchName 删除远程仓库分支 git push origin --delete <branch_name> 验证远程分支是否删除 git fetch -p //会清理已经删除的远端分支的引用 git branch -r //列出所有远端分支࿰…...

JavaWeb_MySQL数据库
数据库: MySQL数据模型: MySQL是关系型数据库。 SQL: 简介 分类: 数据库设计-DDL 对数据库操作: 表操作: 小练习: 创建下表 SQL代码: create table tb_user (id int primar…...

中国BI步入增长大周期,腾讯云ChatBI加速AI+BI融合
过去十年,大数据技术的快速发展,让数据消费前进一大步,数据价值得到一定程度的挖掘与释放,真正开启了“用数”的大时代。但数据分析繁杂的技术栈、复杂的处理过程以及程式化的交互方式,让“数据消费”的门槛始终降不下…...

揭秘Python:下划线的特殊用法,你绝对想不到!
在Python编程中,下划线(underscore)是一个常见而又强大的工具。它不仅仅是一个普通的字符,而是具有特殊含义和用法的符号。今天,我们就来揭开Python下划线的神秘面纱,探索它的各种妙用。 下划线的基本用法…...

深入探索Java世界中的Jackson魔法:玩转JsonNode
哈喽,大家好,我是木头左! 揭秘Jackson库:JSON处理的瑞士军刀 在Java的世界里,处理JSON数据就像是一场探险。幸运的是,Jackson库就像一把多功能的瑞士军刀,为提供了强大而灵活的工具来解析和操作…...

为什么要使用动态代理IP?
一、什么是动态代理IP? 动态代理IP是指利用代理服务器来转发网络请求,并通过不断更新IP地址来保护访问者的原始IP,从而达到匿名访问、保护隐私和提高访问安全性的目的。动态代理IP在多个领域中都有广泛的应用,能够帮助用户…...

【PB案例学习笔记】-09滚动条使用
写在前面 这是PB案例学习笔记系列文章的第8篇,该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习,提高编程技巧,以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码,小凡都上传到了gitee…...
C++中常见的构造函数类别
目录 摘要 默认构造函数(Default Constructor): 带参数的构造函数(Parameterized Constructor): 拷贝构造函数(Copy Constructor): 移动构造函数(Move C…...

万界星空科技MES系统功能介绍
制造执行系统或MES 是一个全面的动态软件系统,用于监视、跟踪、记录和控制从原材料到成品的制造过程。MES在企业资源规划(ERP) 和过程控制系统之间提供了一个功能层,为决策者提供了提高车间效率和优化生产所需的数据。 万界星空科技MES 系统基础功能&am…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...

页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...