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…...

wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...