项目JetCache的常见配置与使用

Hello, 大家好,今天本汪给大家带来的是JetCache在项目中的常见配置与用法讲解,接下来,随本汪一起来看看吧
请添加图片描述

一、介绍

官网地址:https://github.com/alibaba/jetcache

JetCache 是一种 Java 缓存抽象,它为不同的缓存解决方案提供了统一的用法。 它提供了比 Spring Cache 中的注释更强大的注释。JetCache 中的注解支持原生 TTL, 两级缓存,并在分散的环境中自动刷新,也可以通过代码操作实例。支持多种缓存类型:本地缓存、分布式缓存、多级缓存、缓存统计、自动刷新、异步调用、数据报表等等,能够满足不同业务场景的缓存需求。 目前,有四种实现:、(在 github 上不是开源的)、(在内存中)和简单(在内存中)。JetCache具有上手简单、性能高效、拓展性强的特点。支持缓存预热 、缓存key前缀等功能。结合spring-cache使用,可以实现十分优雅的缓存类型切换 JetCache的全部功能:CacheRedisCacheTairCacheCaffeineCacheLinkedHashMapCache

通过统一的缓存 API 操作缓存。
使用带有 TTL(Time To Live) 的注释和两级缓存支持的声明性方法缓存
使用缓存管理器创建和配置实例Cache
自动收集实例级和方法级缓存的访问统计信息Cache
密钥生成和值序列化策略可定制
支持缓存密钥转换器: //支持的值转换器:fastjson 、fastjson2、jackson、java、kryo、kryo5
分布式缓存自动刷新和分布式锁。(2.2+)
使用缓存 API 进行异步访问(2.2+,使用 redis 生菜客户端)
更新后使本地缓存失效(在所有 JVM 进程中) (2.7+)
Spring Boot 支持
要求:

JDK1.8
Spring Framework4.0.8+(可选,支持注解),jetcache 2.7需要5.2.4+
Spring Boot1.1.9+(可选),jetcache 2.7需要2.2.5+

多级缓存方案
本地缓存:(local)

​ ●LinkedHashMap (在内存中)

​ ●Caffeine (在内存中)

远程缓存:(remote)

​ ●Redis

​ ●Tair (在 github 上不是开源的)

二、配置说明

首先要引入maven依赖:

		<dependency>
            <groupId>com.alicp.jetcache</groupId>
            <artifactId>jetcache-starter-redis</artifactId>
            <version>2.7.4</version>
        </dependency>
        // jetcache 2.7.x 需要和 jedis 一同使用
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>5.0.0</version>
        </dependency>

在启动类上加入两个注解@EnableCreateCacheAnnotation @EnableMethodCache(basePackages = “io.github.pnoker.center”) 这是jetcache启用注解缓存的开关

远程缓存:(remote) 默认的缓存方式
在yml配置文件中写入:

jetcache:
  remote:
    default:      #默认的配置
      type: redis
      host: localhost
      port: 6379
      poolConfig:    #配置必须要写,如果不写将报一个初始化错误
        maxTotal: 50   #最大连接数

在需要添加缓存的类中加入:

  @CreateCache(name = "jetcache" 
                ,expire = 3600 //定义超时时间
                ,timeUnit = TimeUnit.MINUTES //定超时时间单位
                 )
    private Cache<String,String> cache;

将获取的值存入到缓存中:

   cache.put(key,value); //存入缓存 

从缓存中取值:

  String value= cache.get(key); //从缓存中取出数据

重要:

当springboot版本>=2.6版本时则会报一个循环依赖的错误,则需要在配置文件中写入即可:
	spring:
		  main:
   			 allow-circular-references: true //默认为false 	

本地缓存(local):linkedhashmap
在yml文件中:

jetcache:
  local:
    default:
      type: linkedhashmap
      keyConvertor: fastjson #类型转换

在需要添加缓存的类中加入:

在需要添加缓存的类中加入:

    @CreateCache(name = "jetScape"
                ,expire = 3600 //定义超时时间
                ,timeUnit = TimeUnit.MINUTES //定超时时间单位
                ,cacheType = CacheType.LOCAL //确定使用什么缓存,使用本地缓存 默认是使用远程,本地都要缓存
            )
    private Cache<String,String> cache;

将获取的值存入到缓存中:

   cache.put(key,value); //存入缓存 

从缓存中取值:

  String value= cache.get(key); //从缓存中取出数据

三、项目中实际使用

jetcache方法缓存
启用方法注解

@SpringBootApplication(scanBasePackages = {"com.alicp.jetcache.autoconfigure"})
@EnableCreateCacheAnnotation //开启注解缓存
@EnableMethodCache(basePackages = "io.github.pnoker.center") //开启方法注解缓存
@EnableDiscoveryClient
@EnableTransactionManagement
public class ManagerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ManagerApplication.class, args);
    }
}

1、Spring 项目中常用的,使用方法注解操作缓存(这是使用实例,也是文章核心)

	// 使用注释声明方法缓存。
	// 表示元素将在设置后 3600 秒内过期。 JetCache 会自动生成包含所有参数的缓存密钥。@Cachedexpire = 3600
	@Cached(expire = 3600, cacheType = CacheType.REMOTE)
    User getUserById(long userId);
    
    //使用 attribute 使用 [SpEL 脚本](https://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/expressions.html)
    //指定缓存键。key
    @Cached(name = "iot:device:info:deviceName:",key = "#deviceName", expire = 3600,timeUnit = TimeUnit.MINUTES
,cacheType = CacheType.REMOTE) 

    // 缓存名 name 来获取hashMap, deviceName 为key, 查询结果DeviceInfo 作为value 存入缓存, 默认是远程缓存
    @CacheRefresh(refresh = 10) //经过一段时间后刷新一次缓存
    DeviceInfo selectDeviceInfoByDeviceName(String deviceName);
    
    // 多个参数作为key时,可以使用SpEL 脚本对参数进行拼接使用
    @Cached(name = "iot:device:info:device:",key = "#driverId.concat(':').concat(#deviceName)") 
    // driverId:deviceName 作为 key
    DeviceInfo selectDeviceInfoByDeviceNameAndDriveId(String deviceName, String driverId);
    
	@Cached(expire = 3600, cacheType = CacheType.REMOTE)
    @CacheRefresh(refresh = 1800, stopRefreshAfterLastAccess = 3600, timeUnit = TimeUnit.SECONDS)
    @CachePenetrationProtect // CachePenetrationProtect 注解表示缓存将在多线程环境中同步加载。
    DeviceInfo selectDeviceInfoByDeviceName(String deviceName);

2、显示使用缓存实例,定义一个两级缓存(本地内存缓存和远程缓存系统),其中本地元素限制为 50(基于 LRU 的逐出)

@Autowired
private CacheManager cacheManager;
private Cache<String, UserDO> userCache;

@PostConstruct
public void init() {
    QuickConfig qc = QuickConfig.newBuilder("userCache")
        .expire(Duration.ofSeconds(100))
        .cacheType(CacheType.BOTH) // 二级缓存
        .localLimit(50) // 本地元素限制为 50(基于 LRU 的逐出)
        .syncLocal(true) // 更新后使所有jvm进程中的本地缓存无效
        .build();
    userCache = cacheManager.getOrCreateCache(qc);
}

高级 API

1、异步 API:

CacheGetResult r = cache.GET(userId);
CompletionStage<ResultData> future = r.future();
future.thenRun(() -> {
    if(r.isSuccess()){
        System.out.println(r.getValue());
    }
});

2、分布式锁:

cache.tryLockAndRun("key", 60, TimeUnit.SECONDS, () -> heavyDatabaseOperation());

3、数据读取并自动刷新

@Autowired
private CacheManager cacheManager;
private Cache<String, Long> orderSumCache;

@PostConstruct
public void init() {
    QuickConfig qc = QuickConfig.newBuilder("userCache")
        .expire(Duration.ofSeconds(3600)) // 表示元素将在设置后 3600 秒内过期。
        .loader(this::loadOrderSumFromDatabase) // 
        .refreshPolicy(RefreshPolicy.newPolicy(60, TimeUnit.SECONDS).stopRefreshAfterLastAccess(100, TimeUnit.SECONDS))
        .penetrationProtect(true) // 注解表示缓存将在多线程环境中同步加载。
        .build();
    orderSumCache = cacheManager.getOrCreateCache(qc);
}

缓存对象必须保证可序列化

public class DeviceInfo implements Serializable {

RedisCacheConfig

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import javax.annotation.Resource;
import java.time.Duration;

/**
 * Redis Cache
 *
 * @author pnoker
 * @since 2022.1.0
 */
@Configuration
@ConfigurationProperties(prefix = "spring.cache.redis")
public class RedisCacheConfig extends CachingConfigurerSupport {

    @Resource
    private RedisConnectionFactory factory;

    @Setter
    private Duration timeToLive;

    /**
     * 自定义缓存 Key 生成策略
     *
     * @return KeyGenerator
     */
    @Bean
    public KeyGenerator firstKeyGenerator() {
        return (target, method, params) -> params[0].toString();
    }

    /**
     * 自定义缓存 Key 生成策略
     *
     * @return KeyGenerator
     */
    @Bean
    public KeyGenerator commonKeyGenerator() {
        final String dot = ".";
        final String hashTag = "#";
        return (target, method, params) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append(dot);
            sb.append(method.getName());
            sb.append(hashTag);
            for (Object obj : params) {
                sb.append(obj.toString());
            }
            return sb.toString();
        };
    }

    /**
     * 自定义 RedisCacheManager 类,主要是设置序列化,解决乱码问题
     *
     * @return CacheManager
     */
    @Bean
    @Override
    public CacheManager cacheManager() {
        RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager.builder(factory);

        // Json 序列化配置
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        serializer.setObjectMapper(new ObjectMapper()
                .setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY)
                .activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL));

        // 配置 Key & Value 序列化
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer))
                .disableCachingNullValues().entryTtl(timeToLive);
        return builder.cacheDefaults(config).build();
    }

}

yml配置

jetcache:
  statIntervalMinutes: 15 #查看缓存统计报告 15min
  remote:
    default:      #默认的配置
      type: redis
      host: localhost
      port: 6379
      keyConvertor: fastjson
      valueEncode: java #序列化存
      valueDecode: java #取得时候转换成java
      poolConfig:    #配置必须要写
        maxTotal: 50   #最大连接数

yml 整体配置

jetcache:
  statIntervalMinutes: 15 #查看缓存统计报告 15min
  areaInCacheName: false
  hiddenPackages: com.alibaba

  local:
    default:
      type: linkedhashmap
      limit: 100
      keyConvertor: fastjson
      expireAfterWriteInMillis: 100000
    otherArea:
      type: linkedhashmap
      limit: 100
      keyConvertor: none
      expireAfterWriterInMillis: 100000
  remote:
    default:
      type: redis
      keyConvertor: fastjson #支持的值转换器:fastjson 、fastjson2、jackson、java、kryo、kryo5
      valueEncoder: java
      valueDecoder: java
      poolConfig:
        minIdle: 5
        maxIdle: 20
        maxTotal: 50
      host: 120.27.122.182
      port: 6379
      password: Tabr_68686626
      database: 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咖啡汪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值