Caffeine本地缓存技术
  TEZNKK3IfmPf 24天前 21 0

说明:Caffeine是本地缓存方案,在所有本地缓存中命中率最佳,参考下图,本文介绍Caffeine在SpringBoot项目中的应用。

Caffeine本地缓存技术

使用

例如现在有两个接口,一个查询所有用户,一个根据ID查询用户,数据访问层使用的是Mybatis-plus;

controller层代码如下:

import com.hzy.pojo.User;
import com.hzy.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/user")
public class UserController {
     
       

    @Autowired
    private UserService userService;

    @GetMapping("list")
    public List<User> getUsers() {
     
       
        return userService.list();
    }

    @GetMapping("{id}")
    public User getUserById(@PathVariable Long id) {
     
       
        return userService.getById(id);
    }
}

第一步:引入依赖

使用Caffeine前先引入相关依赖:

	<dependency>
	    <groupId>com.github.ben-manes.caffeine</groupId>
	    <artifactId>caffeine</artifactId>
	</dependency>

第二步:创建Bean对象

针对需要用本地缓存的接口,创建对应的缓存对象,注意导包是"com.github……"里面的

(创建一个配置类)

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.hzy.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CaffeineConfig {
     
       

    /** * 创建User相关接口的Cache对象,缓存数量上限为100,初始容量为10 * @return */
    @Bean
    public Cache<Long, User> userCache(){
     
       
        return Caffeine.newBuilder()
                .initialCapacity(10)
                .maximumSize(100)
                .build();

    }
}

顺便一提,Caffeine提供了三种缓存驱逐策略,分别如下:

  • 基于容量,设置缓存数量的上限;
Cache<String, String> cache = Caffeine.newBuilder()
    .maximumSize(100)	// 设置缓存数量上限
    .build();
  • 基于时间,设置缓存的有效时间;
Cache<String, String> cache = Caffeine.newBuilder()
    .expireAfterWrite(Duration.ofSeconds(10)) 	  // 设置缓存有效期为最后一次写入后的10秒
    .build();
  • 基于引用,设置缓存为软件引用或者弱引用,利用JVM虚拟机的GC来回收缓存,性能差,不推荐;

第三步:修改代码

可以针对这两个接口,在Service层输入信息,来判断缓存是否生效,有没有每次都访问数据库;

(controller层,方法改为访问Service的方法,查询所有的接口不使用缓存)

@RestController
@RequestMapping("/user")
public class UserController {
     
       

    @Autowired
    private UserService userService;

    @Autowired
    private Cache<Long, User> userCache;

    /** * 不使用缓存 * @return */
    @GetMapping("list")
    public List<User> getUsers() {
     
       
        return userService.list();
    }

    /** * 使用缓存 * @param id * @return */
    @GetMapping("{id}")
    public User getUserById(@PathVariable Long id) {
     
       
        return userCache.get(id, new Function<Long, User>() {
     
       
            @Override
            public User apply(Long key) {
     
       
                return userService.getUserById(key);
            }
        });
    }
}

(Service层代码,每次访问数据库前打印信息)

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

    @Override
    public User getUserById(Long id) {
     
       

        System.out.println("根据ID查询用户接口====访问了数据库");

        return getById(id);
    }
}

第四步:测试使用

启动项目,使用Postman访问根据ID查询用户的接口,查看控制台结果;

(首次访问,控制台打印信息,请求访问了数据库)

Caffeine本地缓存技术

Caffeine本地缓存技术

清空控制台,二次访问,未打印信息,说明这次没有访问数据库,缓存生效了。此时即使停用数据库,这条请求依旧可以访问到结果

Caffeine本地缓存技术

Caffeine本地缓存技术

注意事项

使用Caffeine可以减轻数据库压力,但是需要注意,因为Caffeine是本地缓存,重启项目后发送请求还是直接访问数据库的。

另外,Caffeine好像不能使用Mybatis-Plus提供的,list()、selectList()这种全查的API,就是说只能在单条记录的查询下使用Caffeine,比较受限。

即便可以对list()、selectList()查询结果缓存,那Caffeine有没有对缓存进行管理呢?比如全查了所有用户信息,保留了缓存。此时首次查询一条用户信息,Caffeine有没有相关判断,直接从缓存中获取此次查询结果,而不访问数据库呢?值得思考。

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 24天前 0

暂无评论

推荐阅读
  TEZNKK3IfmPf   2024年03月22日   61   0   0 缓存
  TEZNKK3IfmPf   2024年03月22日   66   0   0 缓存
TEZNKK3IfmPf