JetCache多级缓存实现用户信息快速查询

        在我们的项目中,经常会需要查询用户信息,比如前端页面需要展示,用户校验权限需要,可以说我们做的几乎所有操作都需要查询。

        而这些用户信息,很多内容都是不变的,比如用户的昵称、手机号等,或者说是变化不频发的。所以这些数据我们就可以做缓存。

在缓存选择上,我们不仅用了分布式缓存,同时为了提升性能,还做了本地缓存。也就是说我们的一次查询,会先查询本地缓存,如果本地缓存查不到,再查询分布式缓存。并且在分布式缓存中查询到之后保存到本地缓存中一份。

public String query(String key){


	String localResult = localCache.get(key);


	if(localResult == null){
  	String remoteResult = remoteCache.get(key);
  	if(remoteResult != null){
    	localCache.put(remoteResult);
    }
  }
	return localResult;

}

现在有一个缓存框架可以帮我们干这件事,我们选择用通用的二级缓存框架,阿里开源的 JetCache。

JetCache是一个基于java的缓存系统封装,提供统一的API和注解简化缓存的使用。 JetCache提供了比SpringCache更强大的注解,可以原生的支持TTL、两级缓存、分布式自动刷新,提供了Cache接口用于手动缓存操作。它支持多种缓存策略和缓存存储类型,包括本地缓存(如 Caffeine、Guava 等)和分布式缓存( Redis、Memcached 等)

我们以Caffeine和Redis为例,讲一下,如何接入进来。

1、引入依赖:

<!--    Caffeine    -->
<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>3.1.8</version>
</dependency>


<!--    JetCache    -->
<dependency>
    <groupId>com.alicp.jetcache</groupId>
    <artifactId>jetcache-starter-redisson</artifactId>
    <version>2.7.5</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>


<!--     Redis  -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2、编写相应的文件配置:

jetcache:
  statIntervalMinutes: 1        # 设置统计信息收集的时间间隔为1分钟
  areaInCacheName: false        # 禁用在缓存名称中包含区域名称
  local:
    default:
      type: caffeine            # 使用Caffeine作为本地缓存实现
      keyConvertor: fastjson2   # 使用Fastjson2进行键转换
  remote:
    default:
      type: redisson            # 使用Redisson作为远程缓存实现
      keyConvertor: fastjson2   # 使用Fastjson2进行键转换
      broadcastChannel: ${spring.application.name}  # 广播频道名称设置为Spring应用程序名称
      keyPrefix: ${spring.application.name}         # 键前缀设置为Spring应用程序名称
      valueEncoder: java        # 使用Java进行值编码
      valueDecoder: java        # 使用Java进行值解码
      defaultExpireInMillis: 5000  # 设置默认过期时间为5000毫秒(5秒)


3、开启注解

在启动类上增加@EnableMethodCache注解

@EnableMethodCache(basePackages = "org.h2cn")
public class DemoApplication {
}

接入后,我们在我们的用户查询接口中增加注解:

@Service
public class UserService extends ServiceImpl<UserMapper, User> implements InitializingBean {




    @Autowired
    private UserMapper userMapper;




    /**
     * 通过用户ID查询用户信息
     *
     * @param userId
     * @return
     */
    @Cached(name = ":user:cache:id:", expire = 3000, cacheType = CacheType.BOTH, key = "#userId", cacheNullValue = true)
    @CacheRefresh(refresh = 60, timeUnit = TimeUnit.MINUTES)
    public User findById(Long userId) {
        return userMapper.findById(userId);
    }


  
    /**
     * 更新用户信息
     *
     * @param userModifyRequest
     * @return
     */
    @CacheInvalidate(name = ":user:cache:id:", key = "#userModifyRequest.userId")
    public Boolean modify(UserModifyRequest userModifyRequest) {
        User user = userMapper.findById(userModifyRequest.getUserId());
        Assert.notNull(user, () -> new UserException(USER_NOT_EXIST));
        Assert.isTrue(user.canModifyInfo(), () -> new UserException(USER_STATUS_CANT_OPERATE));
        if (StringUtils.isNotBlank(userModifyRequest.getNickName()) && nickNameExist(userModifyRequest.getNickName())) {
            throw new UserException(NICK_NAME_EXIST);
        }
        BeanUtils.copyProperties(userModifyRequest, user);


        if (StringUtils.isNotBlank(userModifyRequest.getPassword())) {
            user.setPasswordHash(DigestUtil.md5Hex(userModifyRequest.getPassword()));
        }
        if (updateById(user)) {
            addNickName(userModifyRequest.getNickName());
            return true;
        }
        return false;
    }


}


@Cached:为一个方法添加缓存,创建对应的缓存实例,注解可以添加在接口或者类中的方法上面,该类必须是spring bean

        name:指定缓存实例名称,如果没有指定,会根据类名+方法名自动生成。

        expire:超时时间。如果注解上没有定义,会使用全局配置,如果此时全局配置也没有定义,则为无穷大。

        cacheType:缓存的类型,支持:REMOTE、LOCAL、BOTH,如果定义为BOTH,会使用LOCAL和REMOTE组合成两级缓存。

        key:使用SpEL指定缓存key,如果没有指定会根据入参自动生成。

        cacheNullValue:当方法返回值为null的时候是否要缓存。

@CacheRefresh:用于标识这个缓存需要自动刷新

        refresh:刷新的时间间隔

        timeUnit:时间单位

@CacheInvalidate:用于标识这个方法被调用时需要移除缓存

        name:指定缓存的唯一名称,一般指向对应的@Cached定义的name。

        key:使用SpEL指定key,如果没有指定会根据入参自动生成。

除此之外,JetCache 还提供了@CreateCache、@CacheUpdate等常用注解,这就是我们基于缓存的自动更新+失效,来保证缓存的一致性的一般做法。

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值