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 缓存写入的详细流程。

  1. 当应用程序请求写入一个数据项到 Ehcache 中时,这个数据项被传递给Ehcache API。

  2. Ehcache首先根据该数据项的键值对定位其对应的Cache对象。

  3. Ehcache根据配置中的缓存策略,比如是否应该在缓存中创建一个新的元素,以及新元素是否会淘汰老的元素。

  4. 如果需要创建一个新缓存元素,则Ehcache创建一个新的元素并将其添加到Cache对象中。

  5. 如果缓存中已经存在该元素,Ehcache会根据缓存策略对该元素进行更新或替换。

  6. Ehcache将更新后的Cache对象返回给应用程序。

2. 缓存查找

当应用程序需要查询缓存中的数据时,Ehcache 首先会检查该数据是否存在于缓存中。如果数据存在于缓存中,则直接返回缓存数据;否则,从数据库或其他资源获取数据,并将其存入缓存中。以下是 Ehcache 缓存查找的详细流程。

  1. 当应用程序请求从 Ehcache 中读取一个数据项时,这个请求被传递给Ehcache API。

  2. Ehcache首先根据该数据项的键值对定位其对应的Cache对象。

  3. Ehcache检查该数据项是否已经存在于缓存中。

  4. 如果数据项存在于缓存中,Ehcache可以直接将其返回给应用程序。

  5. 如果数据项不存在于缓存中,Ehcache就需要从数据库或其他数据源(如文件、网络等)中获取数据。

  6. 获取到数据后,Ehcache会将其添加到缓存中并返回给应用程序。

3. 缓存过期和驱逐

Ehcache 提供了多种缓存失效策略,例如基于时间的缓存失效、基于访问的缓存失效、基于大小的缓存失效等。当缓存数据过期或缓存空间不足时,Ehcache 会选择一部分缓存元素进行驱逐以腾出更多的内存空间。以下是 Ehcache 缓存过期和驱逐的详细流程。

  1. Ehcache会周期性地扫描缓存中的元素来标记那些已经过期的元素。

  2. Ehcache根据缓存策略(如基于时间、基于访问、基于大小等)判断哪些缓存元素应该被驱逐。

  3. 驱逐过程通常是异步执行的,Ehcache会在后台线程上执行这个操作。

4. 缓存持久化

Ehcache 还提供了缓存持久化功能,它可以将缓存中的数据持久化到磁盘或者其他数据源。在应用程序重启或者缓存失效后,Ehcache 可以从持久化存储中恢复数据,从而保证数据的完整性和可靠性。以下是 Ehcache 缓存持久化的详细流程。

  1. Ehcache使用磁盘存储或数据库等持久化技术来存储缓存数据。

  2. 当缓存中的数据更新时,Ehcache会自动将此数据持久化到持久化存储中。

  3. 在应用程序重启或者缓存失效后,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 {

    @Autowired
    private CacheManager cacheManager;

}

在上述代码中,我们注入了 CacheManager 类型的 cacheManager 实例。

3.2.2 获取缓存实例

获取缓存实例的方式也很简单,可以通过缓存管理器的 getCache() 方法获取:

@Service
public class UserService {

    @Autowired
    private 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 {

    @Autowired
    private 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 实现缓存数据的复制和同步。

需要注意的是,分布式缓存的配置和使用与单机缓存有所不同,同时也需要考虑到网络通信等问题,因此更加复杂和耗费资源。在选择是否需要使用分布式缓存时,需要权衡其带来的性能、复杂性和成本等因素。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/663775.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

战略合作 | 竹云赋能雁塔区数字经济高质量发展

2024年5月30日&#xff0c;由西安市数据局指导&#xff0c;中共西安市雁塔区委、西安市雁塔区人民政府主办的 “雁塔区企业数字化转型发展大会” 在西安开幕。 本次活动以“数智雁塔&#xff0c;引领未来”为主题&#xff0c;特邀业内150余位政府、数字化服务企业、传统行业企…

木叶飞舞之【机器人ROS2】篇章_第三节、给turtlebot3安装realsense深度相机

我们做视觉slam时会用到深度相机&#xff0c;但是gazebo的turtlebot3中只有rgb相机&#xff0c;没有深度&#xff0c;因此本节会修改代码&#xff0c;来给我们的小乌龟增加一个rgbd相机。 效果展示 发布topic如下图 图片大小都是640*480 1. 修改model.sdf文件 1.1 路径位置…

idea项目一直在build

IDEA项目一直在build的原因可能包括构建进程堆大小过小、缓存问题、依赖包下载缓慢或网络问题。12 构建进程堆大小过小&#xff1a;如果IDEA的构建进程堆大小设置得不够大&#xff0c;可能会导致构建过程缓慢或卡顿。解决方法是将构建进程堆大小参数扩大&#xff0c;例如将700…

Pont在小程序开发的使用

Pont是一个很好的前后端桥&#xff0c;但是有个问题。默认产生的代码&#xff0c;无法支持微信小程序开发。根本原因是因为使用了window给全局的对象注入了API和refs属性&#xff0c;由于小程序没有window属性&#xff0c;当然就无法使用了&#xff0c;解决办法也比较简单。只需…

618适合入手哪些数码好物?实用数码好物清单分享,错过拍烂大腿!

在一年一度的618购物狂欢节里&#xff0c;许多数码爱好者们都在这次盛大的购物盛宴中觅得心仪的数码好物&#xff0c;数码产品不仅改变了我们的生活方式&#xff0c;更让我们享受到了前所未有的便捷和乐趣&#xff0c;那么在这个618&#xff0c;哪些数码好物值得我们入手呢&…

Vulnhub项目:doubletrouble

1、靶机地址 靶机地址&#xff1a;doubletrouble: 1 ~ VulnHubdoubletrouble: 1, made by tasiyanci. Download & walkthrough links are available.https://vulnhub.com/entry/doubletrouble-1,743/ 靶机介绍&#xff1a;看这个名字&#xff0c;就觉得内有玄机&#xff…

git随记

git status 查看文件状态 git status -s 比较简洁的查看文件状态。如下代表此文件是新建的&#xff0c;没有被git跟踪的文件&#xff1a; $ git status -s ?? abc.txtgit add abc.txt 将abc添加到暂存区。后再次git status -s $ git status -s A abc.txtgit reset 将暂存…

Java中的枚举(Enum)

基本概念 Java 枚举是一个特殊的类&#xff0c;一般表示一组常量&#xff0c;比如一年的 4 个季节&#xff0c;一个年的 12 个月份&#xff0c;一个星期的 7 天&#xff0c;方向有东南西北等。 Java 枚举类使用 enum 关键字来定义&#xff0c;各个常量使用逗号&#xff08;,&…

android gradle8.3 发布插件踩过的坑

之前写过gradle6.x和gradle7.x的插件&#xff0c;会有一些改动&#xff0c;到8.x我发现又有一些变化&#xff0c;记录一下&#xff0c;防止后边再遇到相同的情况 下边是插件的gradle文件配置 plugins {id("java-gradle-plugin") //会自动引入java-library、gradleAp…

【Linux】 管道扩展 — 开始使用命名管道

送给大家一句话&#xff1a; 人生有六个字&#xff0c;前面三个是不害怕&#xff0c;后面三个是不后悔。 -- 董卿 &#x1f506;&#x1f506;&#x1f506;&#x1f506;&#x1f506;&#x1f506;&#x1f506;&#x1f506; 命名管道的功能实现 1 命名管道的原理2 代码实…

ROS2从入门到精通2-1:launch多节点启动与脚本配置

目录 0 专栏介绍1 ROS2的启动脚本优化2 ROS2多节点启动案例2.1 C架构2.2 Python架构 3 其他格式的启动文件3.1 .yaml启动3.2 .xml启动 0 专栏介绍 本专栏旨在通过对ROS2的系统学习&#xff0c;掌握ROS2底层基本分布式原理&#xff0c;并具有机器人建模和应用ROS2进行实际项目的…

博客星球大冒险:用Spring Boot和JWT打造你的数字王国

揭秘如何在Spring Boot中无缝集成JWT&#xff0c;为你的应用打造一个高度可扩展且安全的认证系统。从添加依赖到创建JWT过滤器&#xff0c;再到实现令牌的有效性管理和刷新机制&#xff0c;每一步都精心设计&#xff0c;确保你的乐园能够迎接成千上万的游客&#xff01; 文章目…

AltiumDesigner/AD添加数据库连接

1.首先确保本机电脑有无对应的数据库驱动&#xff0c;例如我这边要添加MySQL的数据&#xff0c;则需要首先下载MySQL数据驱动&#xff1a;MySQL :: Download MySQL Connector/ODBC (Archived Versions) 2.运行“odbcad32.exe”&#xff0c;如下图添加对应的数据库配置&#xf…

基于深度学习的模糊认知图方法

1 文章信息 文章题目为“Deep Fuzzy Cognitive Maps for Interpretable Multivariate Time Series Prediction”&#xff0c;该文于2019年发表于“IEEE TRANSACTIONS ON FUZZY SYSTEMS”。文章提出了深度模糊认知图&#xff08;FCM&#xff09;用于多变量时间序列预测&#xff…

一个良好的嵌入式系统框架(基于FreeRTOS)

目录 Unix操作系统里的优先级嵌入式系统里的优先级 Unix操作系统里的优先级 在《Unix传奇》中有这样一句话&#xff0c;用户态的进程/线程是三等公民、root线程是二等公民、硬件中断是一等公民。 在操作系统中&#xff0c;"用户态"和"内核态"是两种不同的…

BERT模型学习(1)

BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;由谷歌在2018年推出&#xff0c;迅速成为自然语言处理&#xff08;NLP&#xff09;领域的一个突破性成果。 基本概念 在深入了解BERT之前&#xff0c;需要先简单了解一下自然语言处理&a…

五分钟“手撕”链表

为了提高大家的学习效率&#xff0c;我把代码放开头&#xff0c;供查阅。 目录 一、链表的实现代码 二、什么是链表 三、链表的分类 四、链表的常见操作 插入 删除 五、Java自带的LinkedList 两个构造方法 一些常用方法 六、LinkedList的遍历 七、ArrayList和Linke…

达梦数据库写文件的方式探索

0x01 前沿 这篇文章整体算是《达梦数据库手工注入笔记》的续集&#xff0c;达梦作为国内优秀的信创数据库&#xff0c;在关基单位中拥有越来越大的用户使用量。 通过SQL注入来写文件一直以来都是SQL注入漏洞深入利用的一种方式&#xff0c;对于不同的数据库通常写文件的方式也是…

探索无限可能性——微软 Visio 2021 改变您的思维方式

在当今信息化时代&#xff0c;信息流动和数据处理已经成为各行各业的关键。微软 Visio 2021 作为领先的流程图和图表软件&#xff0c;帮助用户以直观、动态的方式呈现信息和数据&#xff0c;从而提高工作效率&#xff0c;优化业务流程。本文将介绍 Visio 2021 的特色功能及其在…

【管理咨询宝藏119】翰威特组织架构设计优化方案

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏119】翰威特组织架构设计优化方案 【格式】PDF版本 【关键词】人力资源、组织设计、组织架构 【核心观点】 - 城镇化建设和居民可支配收入的增长…