jetcache缓存

1 介绍

是阿里的双极缓存,jvm-->redis-->数据库

文档:jetcache/docs/CN at master · alibaba/jetcache · GitHub

2 注意事项

  1. 使用的实体类一定实现序列化接口

  2. 定时刷新注解,慎用 它会为每一个key创建一个定时器 :场景为:key少,访问量大

  3. 注解泛型一定和方法泛型保持一致,否则报错

  4. expire:过期时间设置为-1或者不设置 过期时间68年左右。

  5. put入参key是null不会存数据,get入参为null,会报空指针。空字符串没有任务问题。使用缓存时我们要多封装一层,判断key为空时情况

  6. 版本

3 总结

缓存类型为BOTH时:

查询流程:

单机:本地缓存默认是100条数据(初始化数据时,留后查询的数据),redis留所有数据。本地缓存查询不到时,去redis找,保存到本地缓存,同时也去除一条本地缓存数据。

集群:第一次访问服务器A时,流程同上述一样,第二次访问服务器B时,直接去redis找,保存到本地缓存。

删除api:本地和redis都会删除数据

4 实战

4.1 pom

XML 复制代码
        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.30</version>
        </dependency>

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

        <!--        jetcache2.7.x版本需要额外添加该依赖-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>4.3.1</version>
        </dependency>
        <!-- json数据工具 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>

4.2 启动类:

java 复制代码
@EnableMethodCache(basePackages="com.example.jetcache.mapper")
//如果不用@CreateCache注解可以删除 EnableCreateCacheAnnotation
@EnableCreateCacheAnnotation

4.3 配置文件

java 复制代码
jetcache:
  ## 统计间隔,默认值0,0表示不统计,开启后定期在控制台输出缓存信息
  statIntervalMinutes: 15
  ## 默认值false, 是否将 areaName 作为远程缓存key前缀
  areaInCacheName: false
  ## 本地缓存配置
  local:
    default: ## default表示全部生效,也可以指定某个cacheName
      ## 本地缓存类型,其他可选:caffeine/linkedhashmap
      type: caffeine
      # 指定KEY的转换方式, 可选 fastjson2,fastjson,jackson
      keyConvertor: fastjson
  ## 远程缓存配置
  remote:
    default: ## default表示全部生效,也可以指定某个cacheName
      type: redis
      ## key转换器方式n
      keyConvertor: fastjson
      broadcastChannel: projectA
      ## redis序列化方式
      valueEncoder: java
      valueDecoder: java
      ## redis线程池
      poolConfig:
        minIdle: 5
        maxIdle: 20
        maxTotal: 50
      ## redis地址与端口
      host: 127.0.0.1
      port: 6379

4.4 基础查询/删除/更新/定时刷新(慎用)

java 复制代码
import com.alicp.jetcache.anno.*;
import com.example.jetcache.entity.User;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Mapper
public interface UserMapper {

    List<User> queryUserAll();

    List<User> queryUser(User user);

    /**
     * BOTH类型查询
     * expire 过期时间,redis和本地缓存一致
     * 重启服务,本地jvm消失,会先查询redis,然后存入本地缓存
     * 本地缓存存在,不会查询redis
     *
     *
     * @param id
     * @return
     */
    @Cached(name="userCache:", key="#id", expire = 15 ,cacheType = CacheType.BOTH)
    /**
     * 只要是查询过的数据,就会定时刷新,从未查询过,则无定时刷新
     * refresh: 定时器执行查询间隔时间-每过36秒就会执行一次定时器
     * stopRefreshAfterLastAccess: 表示多久不使用对应的key缓存则会停止刷新。,如果不指定会一直刷新
refreshLockTimeout:类型为BOTH/REMOTE的缓存刷新时,同时只会有一台服务器在刷新,这台服务器会在远程缓存放置一个分布式锁,此配置指定该锁的超时时间
       */
    @CacheRefresh(refresh = 36, stopRefreshAfterLastAccess = 3600, timeUnit = TimeUnit.SECONDS)
    /**
     * 注解作用------当缓存访问【未命中】的情况下,对并发进行的加载行为进行保护;当前版本实现的是单JVM内的保护,即同一个JVM中同一个key只有一个线程去加载,其它线程等待结果
     */
    @CachePenetrationProtect
    List<User> queryUserById(String id);

    /**
     * 删除
     * @param id
     * @return
     */
    @CacheInvalidate(name="userCache.", key="#id")
    int delById(int id);

    @CacheUpdate(name="userCache.", key="#user.id", value="#user")
    int save(User user);

}

4.5 CreateCache

//无则新增,有则覆盖

userCache.put(id,users);

//删除

userCache.remove(id);

//删除所有数据暂无api

方式一:废弃了

java 复制代码
    @CreateCache(name= "userCache:", expire = 3600,cacheType = CacheType.BOTH)
    private Cache<String, List<User>> userCache;

    @PostMapping(value = "/queryUserById")
    public List<User> queryUserById(@RequestParam String id)  {
        if(CollectionUtil.isNotEmpty(userCache.get(id) )){
            return  userCache.get(id);
        }
        List<User> users = userMapper.queryUserById(id);
       //无则新增,有则覆盖
        userCache.put(id,users);
        return users;
    }

方式二:spring注入直接使用,如上图使用API

@Autowired

private Cache<Long, Object> userCache;

java 复制代码
@Configuration
public class JetCacheConfig {

    @Autowired
    private CacheManager cacheManager;
    private Cache<String, List<User>> userCache;
    @Resource(name = "userMapper")
    private UserMapper userMapper;
    @PostConstruct
    public void init(){
        QuickConfig qc = QuickConfig.newBuilder("userCache:")
            .expire(Duration.ofSeconds(3600))
            .cacheType(CacheType.BOTH)
            //true 集群模式下,任何本地缓存都会强制删除缓存,fasle,则请求到哪个服务,哪个服务删除本地缓存,其他服务本地缓存保持不变
            // 本地缓存更新后,将在所有的节点中删除缓存,以保持强一致性
            // 两级缓存的情况下,缓存更新时发消息让其它JVM实例中的缓存失效,需要配置broadcastChannel才生效
            .syncLocal(true)
            // 默认100 后面数据会挤掉前面的数据  本地缓存元素个数限制,只对CacheType.LOCAL和CacheType.BOTH有效
            .localLimit(100)
           //不存在时则执行这个方法
            .loader(this::loadOrderSumFromDatabase)

            //newPolicy: 定时器执行查询间隔时间
            // stopRefreshAfterLastAccess:表示多久不使用对应的key缓存则会停止刷新。
          //  .refreshPolicy(RefreshPolicy.newPolicy(6, TimeUnit.SECONDS).stopRefreshAfterLastAccess(10, TimeUnit.SECONDS))
             //cache穿透保护注释表示缓存将在多线程环境中同步加载。
            .penetrationProtect(true)
            .build();
        userCache = cacheManager.getOrCreateCache(qc);
        //查询数据库,初始化全部数据
       // userCache.putAll();
    }

    private List<User> loadOrderSumFromDatabase(String id) {
        return userMapper.queryUserById(id);
    }

    @Bean
    public Cache<String, List<User>> getUserCache(){
        return userCache;
    }
}
相关推荐
asdzx673 小时前
Python PDF 拆分实战指南:单页拆分与按需页码范围拆分
开发语言·python·pdf
孬甭_3 小时前
C++ vector
开发语言·c++
学计算机的计算基4 小时前
操作系统内存管理全解:虚拟内存、页表、COW、malloc、OOM一篇搞定
java·笔记·算法
tachibana24 小时前
hot100 前 K 个高频元素(347)
java·数据结构·算法·leetcode
AOwhisky4 小时前
Python 学习笔记(第五期)——组合数据类型:列表、元组、集合与字典精讲——核心知识点自测与详解
开发语言·笔记·python·学习·云计算
万亿少女的梦1684 小时前
基于Spring Boot、Java与MySQL的网络订餐系统设计与实现
java·spring boot·mysql·系统设计·网络订餐
咩咩啃树皮12 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
灯澜忆梦13 小时前
GO_并发编程---定时器
开发语言·后端·golang
鱟鲥鳚13 小时前
Spring Boot 集成 LangChain4j:从模型调用到 Tool Calling(Demo版)
java·spring boot
-银雾鸢尾-13 小时前
C#中的StringBuilder相关方法
开发语言·c#