Ehcache缓存和Redis缓存数据

举报
程序员-上善若水 发表于 2022/06/23 23:18:02 2022/06/23
【摘要】 JVM缓存和使用Redis缓存数据 一、本地缓存Ehcache Ehcache是纯java的开源缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。它主要面向通用缓...

JVM缓存和使用Redis缓存数据

一、本地缓存Ehcache

Ehcache是纯java的开源缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。它主要面向通用缓存、Java EE和轻量级容器,具有内存和磁盘存储、缓存加载器、缓存扩展、缓存异常处理程序。
 Ehcache最初由Greg Luck于2003年开始开发。2009年,该项目被Terracotta购买。软件仍然开源,但一些新的主要功能(例如,快速可重启性之间的一致性的)只能在商业产品中使用。
Ehcache 被广泛用于在Hibernate、Spring、Cocoon等其他开源系统。

1. Ehcache的主要特性

  1. 快速;
  2. 简单;
  3. 多种缓存策略;
  4. 缓存数据有两级:内存和磁盘,因此无需担心容量问题;
  5. 缓存数据会在虚拟机重启的过程中写入磁盘;
  6. 可以通过 RMI、可插入 API 等方式进行分布式缓存;
  7. 具有缓存和缓存管理器的侦听接口;
  8. 支持多缓存管理器实例,以及一个实例的多个缓存区域;
  9. 提供 Hibernate 的缓存实现;

2. Ehcache缓存过期策略

当缓存需要被清理时(比如空间占用已经接近临界值了),需要使用某种淘汰算法来决定清理掉哪些数据。常用的淘汰算法有下面几种:

  1. FIFO:First In First Out,先进先出。判断被存储的时间,离目前最远的数据优先被淘汰。
  2. LRU:Least Recently Used,最近最少使用。判断最近被使用的时间,目前最远的数据优先被淘汰。
  3. LFU:Least Frequently Used,最不经常使用。在一段时间内,数据被使用次数最少的,优先被淘汰。

3. 主要注解

@CachePut 是将数据加入到redis缓存中

@Cacheable 在获取数据的时候会先查询缓存,如果缓存中存在,则不执行查询数据库的方法,如果不存在则查询数据库,并加入到缓存中。
@CacheEvict 一般注解到删除数据的操作上,会将一条或多条数据从缓存中删除。

4. SpringBoot中使用Ehcache

  1. pom
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  1. application.yml
server:
  port: 8081

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/db1
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver

  cache:
    type: ehcache
    ehcache:
      config: classpath:ehcache.xml

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  1. ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
	updateCheck="false">
	<diskStore path="java.io.tmpdir/Tmp_EhCache" />


	<defaultCache maxElementsInMemory="5000" eternal="false"
		timeToIdleSeconds="120" timeToLiveSeconds="120"
		memoryStoreEvictionPolicy="LRU" overflowToDisk="false" />


	<cache name="userCache" maxElementsInMemory="1000" eternal="false"
		timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
		diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000"
		diskPersistent="false" diskExpiryThreadIntervalSeconds="120"
		memoryStoreEvictionPolicy="LRU">
		<cacheEventListenerFactory
			class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" />
		
		<bootstrapCacheLoaderFactory
			class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory" />
	</cache>

</ehcache>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  1. 启动
@EnableCaching
@SpringBootApplication
public class App {
	public static void main(String[] args) {
		SpringApplication.run(App.class, args);
	}
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  1. 使用
@CacheConfig(cacheNames = "userCache")
public interface UserMapper {
	@Select("select * from users where name=#{name}")
	@Cacheable
	UserEntity findName(@Param("name") String name);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
@CacheConfig(cacheNames = "transitoryCache")
@RestController
public class TestController {

    @GetMapping("/GetTest/{id}/{param}")
    @Cacheable(key = "#id.toString()")
    public String getTest(@PathVariable("id")String id,@PathVariable("param")String param){
        return "参数->"+param;
    }

    @GetMapping("/UpdateDate/{id}/{param}")
    @CachePut(key = "#id.toString()")
    public String updateDate(@PathVariable("id")String id,@PathVariable("param")String param){
        return "参数->"+param;
    }

    @GetMapping("/DeleteDate/{id}")
    @CacheEvict(key = "#id.toString()")
    public String deleteDate(@PathVariable("id")String id){
        return "success";
    }

}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

清楚缓存

@Autowired
private CacheManager cacheManager;
@RequestMapping("/remoKey")
public void remoKey() {
	cacheManager.getCache("userCache").clear();
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

二、Redis缓存

springboot已经集成了redis缓存,只需要在pom.xml中加载redis,然后通过注解即可完成配置。

springboot 集成

  1. pom
  		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  1. application.yml 修改
server:
  port: 8080

spring:
  cache:
    type: redis

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  1. 启动类
@SpringBootApplication
@EnableCaching
@MapperScan(value = {"com.bxc.rediscaching.Mapper"})
public class RediscachingApplication {

    public static void main(String[] args) {
        SpringApplication.run(RediscachingApplication.class, args);
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  1. service
@Service
public class UserService {
    @Autowired
    UserMapper userMapper;

    @Cacheable(key = "#root.methodName",value = "userCache")
    public List<UserEntity> getAllUser(){
        System.out.println();
        List<UserEntity> list = userMapper.selectList(null);
        return list;
    }
	
	 //@Cacheable 表示可缓存,如果缓存中存在,就从缓存中查询,不存在,就走数据库
    //其中缓存库位userCache,key表示使用缓存的key(为当前的传递的id.toString())
    @Cacheable(key = "#id.toString()", value = "userCache")
    public UserEntity findUserById(Integer id) {
        System.out.println("从数据库中查询编号为:"+id);
        return userData.get(id);;
        return null;
    }

   //表示向缓存中直接添加数据,添加的库为当前的value,添加的key为当前的key(user的id.toString())
    @CachePut(key = "#user.id.toString()", value = "userCache")
    public void addUser(UserEntity user) {
      userData.put(user.getId(), user);
    }

  //表示向缓存中直接添加数据,添加的库为当前的value,添加的key为当前的key(user的id.toString())
    @CachePut(key = "#user.id.toString()", value = "userCache")
    public void updateUser(UserEntity user) {
        userData.put(user.getId(), user);
    }

   //用来删除数据,指定key表示删除缓存库中的key的字段的内容,value表示删除的缓存的库
    @CacheEvict(key = "#id.toString()", value = "userCache")
    public void deleteUserById(Integer id) {
        userData.remove(id);
    }

 
     //用来删除数据,指定allEntries = true表示删除所有的缓存,value表示删除的缓存的库
    @CacheEvict(allEntries = true, value = "userCache")
    public void clearCache() {
        System.out.println("清空缓存");
    }

}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

三、补充

1. @Cacheable 和 @CachePut注解属性说明

  1. keyGenerator:缓存数据key生成策略;
  2. CacheManager:缓存管理器,管理缓存组件;
  3. CacheResolver:缓存解析器,根据实际情况动态解析决定使用哪个缓存实例;
  4. value:缓存实例(一个缓存实例可以存储多个缓存KV对)的名称,至少需要设置一个;
  5. key:缓存的 key,如果不为空需要要按照 SpEL 表达式编写;如果不为空6. 则缺省按照方法的所有参数进行组合;
  6. condition:缓存条件,使用 SpEL 编写;若不为空,只在条件结果为 true 时才进行缓存;
  7. unless:缓存排除条件,当条件结果为TRUE时不会缓存;
  8. sync:是否同步操作,如为true,那么多个线程访问同一条记录时,会同步执行调用的方法。

2. @CacheEvict注解属性说明

@CacheEvict注解的属性大致同 @Cacheable一致,不过 @CacheEvict还有两个独有的属性:

  1. allEntries:是否清空所有缓存内容,缺省为 false;如果指定为 true,则方法调用后将立即清空所有缓存;
  2. beforeInvocation:是否在方法执行前就清空,缺省为 false;如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存。

3. @CacheConfig注解属性说明

@CacheConfig注解的属性 @Cacheable都有。因为 @CacheConfig注解的作用本来就是统一管理相同类下所有方法的缓存配置。

需要提一下的就是在spring4.1之前是没有 @CacheConfig注解的,那时候需要在每个方法的 @Cacheable注解中设置cacheNames属性。

4. SpEL表达式

名称 位置 描述 示例
methodName root对象 当前被调用的方法名 #root.methodname
method root对象 当前被调用的方法 #root.method.name
target root对象 当前被调用的目标对象实例 #root.target
targetClass root对象 当前被调用的目标对象的类 #root.targetClass
args root对象 当前被调用的方法的参数列表 #root.args[0]
caches root对象 当前方法调用使用的缓存列表 #root.caches[0].name
Argument Name 执行上下文 当前被调用的方法的参数,如findArtisan(Artisan artisan),可以通过#artsian.id获得参数 #artsian.id
result 执行上下文 方法执行后的返回值(仅当方法执行后的判断有效,如 unless cacheEvict的beforeInvocation=false) #result

注意事项:

  1. 当我们要使用root对象的属性作为key时我们也可以将“#root”省略,因为Spring默认使用的就是root对象的属性, 如 @Cacheable(key = “targetClass + methodName +#p0”);
  2. 使用方法参数时我们可以直接使用“#参数名”或者“#p参数index”,如: @Cacheable(value=“users”, key="#id")和 @Cacheable(value=“users”, key="#p0")。

文章来源: blog.csdn.net,作者:小毕超,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/qq_43692950/article/details/107443007

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。