大数跨境
0
0

弃用Spring Cache!首选多级缓存框架JetCache

弃用Spring Cache!首选多级缓存框架JetCache Spring全家桶实战案例
2024-09-13
0
导读:弃用Spring Cache!首选多级缓存框架JetCache

环境:Spring Boot3.2.5



1. 简介

JetCache是一个基于Java的缓存框架,提供统一的API和注解来简化缓存的使用。JetCache与SpringCache相比具有更加强大的注解,可以原生的支持TTL、两级缓存、分布式自动刷新,还提供了Cache接口用于手工缓存操作。当前有四个实现,RedisCacheTairCache(此部分未在github开源)、CaffeineCache(in memory)和一个简易的LinkedHashMapCache(in memory),要添加新的实现也是非常简单的。

JetCache具有以下特性:

  • 通过统一的API访问Cache系统

  • 通过注解实现声明式的方法缓存,支持TTL和两级缓存

  • 通过注解创建并配置Cache实例

  • 针对所有Cache实例和方法缓存的自动统计

  • Key的生成策略和Value的序列化策略是可以配置的

  • 分布式缓存自动刷新,分布式锁 (2.2+)

  • 异步Cache API (2.2+,使用Redis的lettuce客户端时)


接下来,将通过实例讲解基于Spring Boot环境下JetCache的详细使用。

2. 实战案例

2.1 依赖管理

<dependency>  <groupId>com.alicp.jetcache</groupId>  <artifactId>jetcache-starter-redis</artifactId>  <version>2.7.6</version></dependency>

目前最新版本是2.7.6,同时支持Spring Boot3.x、2.x。

2.2 配置文件配置

jetcache:  # 统计间隔,0表示不统计  statIntervalMinutes: 15  # jetcache-anno把cacheName作为远程缓存key前缀,2.4.3以前的版本总是把areaName加在cacheName中,因此areaName也出现在key前缀中。  # 2.4.4以后可以配置,为了保持远程key兼容默认值为true,但是新项目的话false更合理些,2.7默认值已改为false。  areaInCacheName: false  # 下面local,remote说明:缓存类型。tair、redis为当前支持的远程缓存;linkedhashmap、caffeine为当前支持的本地缓存类型  local:    default:      type: caffeine      # 这里大小写都可      keyConvertor: JACKSON  remote:    default:      type: redis      # 序列化器的全局配置。仅remote类型的缓存需要指定,2.7+可选```java```/```kryo```/```kryo5```;2.6-可选```java```/```kryo```      keyConvertor: JACKSON      valueEncoder: java      valueDecoder: java      poolConfig:        minIdle: 5        maxIdle: 20        maxTotal: 50      host: 127.0.0.1      port: 6379

接下来,需要在类中开启缓冲间

@SpringBootApplication@EnableMethodCache(basePackages = "com.pack")public class AppApplication {}

完成以上配置后,接下来就可以在代码中使用了。

2.3 基于注解应用

JetCache方法缓存和SpringCache比较类似,它原生提供了TTL支持,以保证最终一致,并且支持二级缓存。JetCache2.4以后支持基于注解的缓存更新和删除。

在Spring环境下,使用@Cached注解可以为一个方法添加缓存,@CacheUpdate用于更新缓存,@CacheInvalidate用于移除缓存元素。注解可以加在接口上也可以加在类上。

@Servicepublic class JetCacheUserService {  private static final String USER_CACHE_PREFIX = "user:" ;
@Cached(name = USER_CACHE_PREFIX, key = "#user.id", expire = 600, timeUnit = TimeUnit.SECONDS) public User save(User user) { System.err.println("保存用户信息") ; return user ; } @Cached(name = USER_CACHE_PREFIX, key = "#userId") public User get(long userId) { System.err.println("查询用户信息") ; return new User() ; } @CacheUpdate(name = USER_CACHE_PREFIX, key="#user.id", value="#user") public User updateUser(User user) { System.out.println("更新用户信息") ; return user ; }
@CacheInvalidate(name = USER_CACHE_PREFIX, key="#userId") public void deleteUser(long userId) { System.err.printf("删除用户【%s】%n", userId) ; }}

注解属性说明:

@Cached

@CacheUpdate

@CacheInvalidate

用于测试的Controller接口

private static final List<Long> IDS = new ArrayList<>() ;private final JetCacheUserService jetCacheUserServivce ;public JetCacheUserController(JetCacheUserService jetCacheUserServivce) {  this.jetCacheUserServivce = jetCacheUserServivce ;}
@GetMapping("save")public User save() { long id = new Random().nextLong(100000000000L) ; IDS.add(id) ; User user = new User(id, "张三", new Random().nextInt(100)) ; return this.jetCacheUserServivce.save(user) ;}
@GetMapping("/{id}")public User get(@PathVariable Long id) { return this.jetCacheUserServivce.get(id) ;}
@GetMapping("/update/{id}")public User update(@PathVariable Long id) { User user = new User(id, "张三", new Random().nextInt(100)) ; return this.jetCacheUserServivce.updateUser(user) ;}
@GetMapping("/delete/{id}")public void delete(@PathVariable Long id) { IDS.remove(id) ; this.jetCacheUserServivce.deleteUser(id) ;}

首先,调用/save接口

访问多次后,查看redis

接下来,访问/{id}接口

控制台并没有输出任何东西,说明我们Service中的方法体并没有调用,而是查询的缓存。

当你将Redis中的数据删除后,再次访问/get接口,由于本地缓存存在,所以同样不会执行Service中的方法体。注意:@Cached需要设置cacheType = CacheType.BOTH属性。

2.4 缓存统计

当配置文件中的jetcache.statIntervalMinutes大于0时,通过@Cached配置出来的Cache自带监控。JetCache会按指定的时间定期通过logger输出统计信息。默认输出信息类似如下:

以上是完全基于注解的方式。接下来介绍通过编程与注解的方式。

2.5 基于编程方式

使用CacheManager可以创建Cache实例,如下示例:

private final CacheManager cacheManager;public JetCacheProgramUserService(CacheManager cacheManager) {  this.cacheManager = cacheManager ;}private Cache<Long, User> userCache;
@PostConstructpublic void init() { QuickConfig qc = QuickConfig.newBuilder("user:") .expire(Duration.ofSeconds(100)) .cacheType(CacheType.BOTH) .syncLocal(true) .build(); userCache = cacheManager.getOrCreateCache(qc) ;}
public User save(User user) { System.err.println("Program 保存用户信息") ; this.userCache.computeIfAbsent(user.getId(), key -> user) ; return user ;}public User get(long userId) { User user = this.userCache.get(userId) ; if (user == null) { System.err.println("查询用户信息") ; // TODO } return user ;}

如上,最终得到的结果与使用注解是完全一样的。

通过@CreateCache注解创建Cache实例。

@CreateCache(expire = 100)private Cache<Long, User> userCache;

该种方式已经被废弃,不推荐使用。

以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏

推荐文章

运行时修改 Spring Boot 属性的N种方式

生产环境Spring Boot切记要关闭这个开关

强大!SpringBoot几行代码生成word文档

SpringBoot读取配置文件信息8种方式,你会哪几种?

高性能缓存神器Caffeine

我给Spring提交一个Bug,已在最新版修复!请这样修复!

别不信@PathVariable你真不会用

当心!SpringBoot在以下几种情况将导致代理失效

分享几个你不知道的高级SpringBoot最佳实践

总结7种JVM出现OOM时的原因及解决方案

优雅!SpringBoot统一返回结果就该这样处理

Java高级开发必须掌握JMH进行性能测试优化

这才是SpringBoot统一响应和异常处理的最佳实践

警惕!SpringBoot错误发布事件,造成死锁Deadlock

强烈建议JDK升级到17,因为这些功能

SpringBoot多租户3种架构实现方案详解

【声明】内容源于网络
0
0
Spring全家桶实战案例
Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
内容 832
粉丝 0
Spring全家桶实战案例 Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
总阅读285
粉丝0
内容832