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;
    }
}
相关推荐
wjs20243 分钟前
MongoDB 更新集合名
开发语言
monkey_meng6 分钟前
【遵守孤儿规则的External trait pattern】
开发语言·后端·rust
草莓base18 分钟前
【手写一个spring】spring源码的简单实现--bean对象的创建
java·spring·rpc
legend_jz31 分钟前
【Linux】线程控制
linux·服务器·开发语言·c++·笔记·学习·学习方法
drebander43 分钟前
使用 Java Stream 优雅实现List 转化为Map<key,Map<key,value>>
java·python·list
乌啼霜满天2491 小时前
Spring 与 Spring MVC 与 Spring Boot三者之间的区别与联系
java·spring boot·spring·mvc
tangliang_cn1 小时前
java入门 自定义springboot starter
java·开发语言·spring boot
程序猿阿伟1 小时前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端
Grey_fantasy1 小时前
高级编程之结构化代码
java·spring boot·spring cloud
新知图书1 小时前
Rust编程与项目实战-模块std::thread(之一)
开发语言·后端·rust