EhCache介绍

EhCache简介

EhCache是一个开源的、基于标准的缓存框架,可以提高服务的整性能。
它是使用最广泛的基于Java的缓存,因为它健壮、经过验证、功能齐全,并与其他流行的库和框架集成。
Ehcache可以从进程内缓存扩展到具有TB级缓存的混合进程内/进程外部署。
最新的Ehcache 3 本身符合JSR107(JCache规范),支持堆外存储,并提供磁盘持久化。

EhCache快速入门

本文介绍EhCache的使用,是基于EhCache3版本。
1)使用Idea工具,构建Maven工程
2)引入EhCache3,可通过[官网](https://www.ehcache.org)获取最新版本依赖,并添加单元测试框架依赖
<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>3.10.8</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
</dependency>
3)编写测试代码
public class Demo {
    @Test
    public void test() {
        // 1、初始化好 CacheManager
        CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
                .withCache("user",
                        CacheConfigurationBuilder.newCacheConfigurationBuilder(
                                String.class,
                                String.class,
                                ResourcePoolsBuilder.newResourcePoolsBuilder()
                                        .heap(100)
                                        .build())
                                .build())
                .build(true); // 这里可以初始化
        // cacheManager.init(); // 这里也可以对CacheManager初始化,二选一
        // 2、基于CacheManager 获取 Cache 对象
        Cache<String, String> user = cacheManager.getCache("user", String.class, String.class);
        // 3、将需要缓存的内容,放入Cache对象
        user.put("zhangsan", "第一次缓存数据");
        // 4、取出缓存中的内容
        System.out.println(user.get("zhangsan"));
    }
}
以上就是基于Java配置的EhCache3的入门案例。

EhCache基本配置

EhCache提供了非常丰富的功能,通常情况下,通过简单的配置即可使用,非常方便。
这里主要介绍两种比较重要且常用的功能:

1)缓存方式

EhCache3.x版本中不但提供了堆内缓存heap,堆外缓存off-heap,而且还提供了数据的持久化操作disk,可以将数据落到磁盘中。
heap堆内内存:
heap是将数据直接放到JVM内部,这种缓存数据在获取的时候效率最高。
heap(10) 代表当前Cache最多只能存储10个数据,当put第11个数据时,第一个数据就会被移除。
heap(10, MB) 代表当前Cache最多只能存储10MB数据。
off-heap堆外内存:
off-heap是将数据放到操作系统的一块内存区域存储,不是JVM内部。
这种对象是不能直接被JVM使用的。
存储时,需要对数据进行序列化操作,取出时,需要反序列化操作。
使用效率上比堆内内存稍低。
disk落到磁盘
disk表示将数据序列化到本地磁盘文件中,当服务重启后,会从磁盘文件中反序列化数据到内存,从而减轻数据库的压力。
EhCache提供了三种组合使用方式
heap + off-heap + disk
heap + disk【通常使用这种方式】
heap + off-heap
在组合的情况下,存储数据时,数据先落到堆内内存,同时同步到堆外内存及本地磁盘。
本地磁盘因为空间充裕,所以本地磁盘数据是最全的。
EhCache要求空间大小必须 disk > off-heap > heap。
    @Test
    public void test2() {
        // 1、声明存储位置
        String path = "D:\\ehcache";

        // 2、初始化 CacheManager
        CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
                .with(CacheManagerBuilder.persistence(path)) // 落到哪里要通过CacheManager来指定
                .withCache("order",
                        CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class,
                                String.class,
                                ResourcePoolsBuilder.newResourcePoolsBuilder()
                                        .heap(100)
                                        .offheap(10, MemoryUnit.MB)
                                        .disk(15, MemoryUnit.MB, true)  // 落到磁盘是需要指定位置的。这里如果没有true选项,不会存储到文件
                                        .build())
                                .build())
                .build(true); // 这里可以初始化
        // 3、基于CacheManager 获取到Cache对象
        Cache<String, String> order = cacheManager.getCache("order", String.class, String.class);
        // 4、将需要缓存的内容,放入Cache对象
        order.put("hello", "第二次缓存数据");
        // 5、取出缓存中的内容
        System.out.println(order.get("hello"));
        // 6、保证数据持久化不丢失,需要执行 cacheManager.close();
        cacheManager.close();
    }
本地磁盘存储,一共有三个文件
meta:原数据存储,记录当前cache的key类型和value类型
data:存储具体数据的位置,将数据序列化成字节存储
index:类似索引,帮助查看数据的。
ehcache-disk-store.data
ehcache-disk-store.index
ehcache-disk-store.meta

2)数据生存时间

数据如果一直存放在内存当中,因为数据会不断增长,缓存也会不断地增加,
而不使用的数据还在占用内存,这时可能会造成内存泄露等问题。
EhCache提供了对数据设置生存时间的机制
提供了三种机制:
noExpiration: 不设置生存时间
timeToLiveExpiration: 从数据落到缓存计算生存时间
timeToIdleExpiration: 从最后一个get计算生存时间
	@Test
    public void test3() throws InterruptedException {
        // 1、初始化好 CacheManager
        CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
                .withCache("user",
                        CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class,
                                String.class,
                                ResourcePoolsBuilder.newResourcePoolsBuilder()
                                        .heap(10)
                                        .build())
                                // 不设置生存时间  三选一
//                                .withExpiry(ExpiryPolicy.NO_EXPIRY)
                                // 设置生存时间 timeToLiveExpiration
//                                .withExpiry(ExpiryPolicyBuilder.timeToIdleExpiration(Duration.ofMillis(5000)))
                                // 设置生存时间 timeToIdleExpiration
                                .withExpiry(ExpiryPolicyBuilder.timeToIdleExpiration(Duration.ofSeconds(10)))
                                .build())
                .build(true); // 这里可以初始化
        // 2、基于CacheManager 获取到Cache对象
        Cache<String, String> user = cacheManager.getCache("user", String.class, String.class);
        // 3、将需要缓存的内容,放入Cache对象
        user.put("wangwu", "第三次缓存数据");
        Thread.sleep(4000);
        // 4、取出缓存中的内容
        System.out.println(user.get("wangwu"));
        Thread.sleep(9000);
        System.out.println(user.get("wangwu"));
        Thread.sleep(10000);
        System.out.println(user.get("wangwu"));
        // 5、保证数据持久化不丢失,需要执行cacheManager.close();
        cacheManager.close();

Springboot集成EhCache

这里使用Springboot2.7.2 集成 EhCache3.8.1。
首先是添加springboot及缓存starter等相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.7.2</version>
    </parent>
    <groupId>com.xf</groupId>
    <artifactId>ehcache</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>
        <dependency>
            <groupId>org.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>3.8.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>
springboot集成EhCache有两种方式:

1)纯Java配置

通常在开发的过程中,我们不希望一些可灵活配置的数据被写死在代码中,
所以,这里配置文件application.yml中添加如下配置
hj:
	ehcache:
    heap: 50  # 堆内内存缓存大小限制 单位MB,即最多50MB
    disk: 100   # 磁盘存储数据大小限制 单位MB,即最多100MB
    diskDir: D:/data/cache/   # 磁盘存储缓存文件的位置
    cacheNames:            # 基于CacheManager构建多少个缓存
      - SYSTEM_MANAGER
      - BUSINESS

添加配置类

@Data
@Configuration
@ConfigurationProperties(prefix = "hj.ehcache")
public class EhCachePropertyConfig {
    /**
     * 堆内内存缓存个数
     */
    private Integer heap;
    /**
     * 磁盘存储数据大小 单位MB
     */
    private Integer disk;
    /**
     * 基于CacheManager构建多少个缓存
     */
    private Set<String> cacheNames;
}

@Configuration
@EnableCaching
public class EhCacheConfig {

    @Resource
    private EhCachePropertyConfig ehCachePropertyConfig;

    /**
     * 配置类的方式 注入缓存管理器
     * 目前无法持久化
     * @return
     */
    @Bean
    public CacheManager ehCacheManager() {

        CachingProvider cachingProvider = Caching.getCachingProvider();

        javax.cache.CacheManager cacheManager = cachingProvider.getCacheManager();

        org.ehcache.config.CacheConfiguration<String, Serializable> cacheConfiguration =
                CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, Serializable.class,
                        org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder()
                                .heap(ehCachePropertyConfig.getHeap(), MemoryUnit.MB)
                                .build())
                        .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(10 * 60)))
                        .build();

        javax.cache.configuration.Configuration<String, Serializable> configuration =
                Eh107Configuration.fromEhcacheCacheConfiguration(cacheConfiguration);

        for (String cacheName : ehCachePropertyConfig.getCacheNames()) {
            cacheManager.createCache(cacheName, configuration);
        }

        return new JCacheCacheManager(cacheManager);
    }
}
对当前纯Java配置的方式,没有找到合适的持久化方法,如有大神知道,请指教。
使用方式如下:
    @Cacheable(cacheNames = {CacheConstant.SYSTEM_MANAGER}, key = "T(com.alibaba.fastjson.JSON).toJSONString(#roleIds)")
    @Override
    public Set<String> listPermissionRecordFromRole(List<String> roleIds) {
        log.info("SysRoleManagerImpl.listPermissionRecordFromRole, roleIds={}", JSON.toJSONString(roleIds));
        return sysRoleMapper.listPermissionRecordFromRole(roleIds);
    }

2)使用XML配置

XML配置的方式比较简单,主要是XML配置项,其次需要在application.yml文件中指定cache类型和配置文件位置,
具体配置方式如下:
application.yml配置
spring:
  cache:
    type: jcache
    jcache:
      config: classpath:ehcache.xml
ehcache.xml配置
在工程的resources目录下新建ehcache.xml文件,配置方式如下:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.ehcache.org/v3"
        xmlns:jsr107="http://www.ehcache.org/v3/jsr107"
        xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd
            http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd">
    <!-- 缓存持久化配置: 定义磁盘缓存位置 -->
    <persistence directory="./tmp/ehcache"/>
    <!-- 缓存模板: 未填写缓存名时使用的默认缓存,同时也可被继承 也可以不用模版直接在cache中配置与模版参数相同 -->
<!--    <cache-template name="defaultCache">-->
<!--        <key-type>java.lang.String</key-type>-->
<!--        <value-type>java.lang.Object</value-type>-->
<!--        <expiry>-->
<!--            <ttl unit="minutes">10</ttl>-->
<!--        </expiry>-->
<!--        <resources>-->
<!--            <heap unit="MB">5</heap>-->
<!--        </resources>-->
<!--    </cache-template>-->
    <!-- 缓存列表: 自定义缓存配置 -->
    <cache alias="SYSTEM_MANAGER">
        <key-type>java.lang.String</key-type>
        <value-type>java.io.Serializable</value-type>
        <!--配置缓存策略
            tti:缓存条目在最后一次访问后到被认为过期的时间间隔
            ttl:缓存条目从创建或最后一次更新开始,到被认为过期的时间间隔
            系统管理缓存保存20分钟
        -->
        <expiry>
            <tti unit="minutes">20</tti>
        </expiry>
        <resources>
            <heap unit="MB">500</heap>
            <disk unit="GB" persistent="true">1</disk>
        </resources>
    </cache>
    <cache alias="LDAR_BUSINESS">
        <key-type>java.lang.String</key-type>
        <value-type>java.io.Serializable</value-type>
        <!--配置缓存策略
            tti:缓存条目在最后一次访问后到被认为过期的时间间隔
            ttl:缓存条目从创建或最后一次更新开始,到被认为过期的时间间隔
            业务缓存保存5分钟
        -->
        <expiry>
            <tti unit="minutes">10</tti>
        </expiry>
        <resources>
            <heap unit="MB">500</heap>
            <disk unit="GB" persistent="true">1</disk>
        </resources>
    </cache>
</config>
使用方式同上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值