EhCache介绍

0 阅读7分钟

EhCache介绍

EhCache简介
EhCache快速入门
EhCache基本配置
    1)缓存方式
        heap堆内内存:
        off-heap堆外内存:
        disk落到磁盘
        EhCache提供了三种组合使用方式
    2)数据生存时间
        EhCache提供了对数据设置生存时间的机制
        Springboot集成EhCache

1)纯Java配置 2)使用XML配置

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

EhCache快速入门 本文介绍EhCache的使用,是基于EhCache3版本。 1)使用Idea工具,构建Maven工程 2)引入EhCache3,可通过官网获取最新版本依赖,并添加单元测试框架依赖

<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文件,配置方式如下: AI写代码 1

<!-- 缓存列表: 自定义缓存配置 -->
<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>

使用方式同上。

原文链接:blog.csdn.net/xiefeng88/a…