SpringBoot整合Caffeine本地缓存

在现代的微服务架构中,缓存已经成为提升系统性能、降低数据库压力和提高响应速度的关键技术之一。对于Java开发者而言,Spring Boot作为一种开发框架,不仅提供了灵活的缓存机制,而且通过与一些缓存库(如Caffeine)结合,能够进一步优化应用性能。

1. 什么是Caffeine缓存?

Caffeine是一个高性能的Java缓存库,它的主要特点包括:

  • 高性能:Caffeine具有极快的读写性能,适合高并发的场景。
  • 丰富的缓存策略:支持基于时间、大小等多种缓存失效策略。
  • 自动回收:内存占用达到限制后会自动回收不常用的缓存。

相较于其他缓存解决方案(如Guava),Caffeine提供了更高的性能和更多的缓存控制选项,适合在Spring Boot中作为本地缓存解决方案。

2. Spring Cache与Caffeine集成

Spring Cache是Spring Framework提供的一种缓存抽象,简化了缓存操作。你可以通过@Cacheable@CachePut@CacheEvict等注解轻松地对方法进行缓存操作,而不需要手动管理缓存的存取。

2.1 Caffeine缓存集成的优势

Spring Boot整合Caffeine可以带来以下优势:

  • 性能提升:Caffeine缓存对常用数据的快速访问能够大幅提高应用性能,减少数据库负载。
  • 内存管理:Caffeine通过LRU(最近最少使用)策略、最大缓存大小限制、缓存过期等机制自动管理内存,避免内存泄漏。
  • 易于集成:Spring Cache抽象使得与Caffeine的集成非常简单,开发者无需管理缓存的底层实现。

3. 集成步骤

3.1 添加依赖

我们需要在Spring Boot项目的pom.xml文件中添加Caffeine和Spring Cache相关依赖:

<dependencies>
    <!-- Spring Boot Cache依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    <!-- Caffeine缓存依赖 -->
    <dependency>
        <groupId>com.github.ben-manes</groupId>
        <artifactId>caffeine</artifactId>
        <version>2.9.2</version>
    </dependency>
</dependencies>

3.2 配置Caffeine缓存

application.propertiesapplication.yml文件中配置Caffeine缓存。比如设置最大缓存大小和过期策略:

# 配置Caffeine缓存
spring.cache.type=caffeine
spring.cache.caffeine.spec=maximumSize=100,expireAfterAccess=600s

这个配置表示缓存最大可以存储100个元素,并且缓存项在600秒后没有被访问则会过期。

3.3 启用缓存支持

在Spring Boot应用的主类或者任意配置类中启用缓存支持。只需要添加@EnableCaching注解:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching  // 启用缓存支持
public class CacheApplication {
    public static void main(String[] args) {
        SpringApplication.run(CacheApplication.class, args);
    }
}

4. 缓存注解的使用

Spring Cache通过注解简化了缓存操作,以下是常用的注解及其功能:

4.1 @Cacheable注解

@Cacheable注解用于缓存方法的返回值。当方法被调用时,Spring会先检查缓存中是否有数据,如果有数据则直接返回缓存值;如果没有,则执行方法并将返回值缓存。

@Cacheable(value = "users", key = "#id")
public User getUserById(Long id) {
    return findUserById(id);  // 查询数据库
}

4.2 @CacheEvict注解

@CacheEvict注解用于清除缓存。它常用于当数据发生变更时,清除相应的缓存。

@CacheEvict(value = "users", key = "#id")
public void updateUser(Long id, String name) {
    // 更新用户信息
}

4.3 @CachePut注解

@CachePut注解用于更新缓存。与@Cacheable不同,它不检查缓存,而是每次执行方法后都会更新缓存。

@CachePut(value = "users", key = "#id")
public User updateUser(Long id, String name) {
    return updateUserInDatabase(id, name);
}

5. 实战案例:缓存查询结果

假设我们正在开发一个简单的用户查询系统,用户可以通过ID查询用户信息。我们希望缓存查询结果,以避免重复查询数据库。

5.1 定义实体类

定义一个User实体类,表示用户信息:

public class User {
    private Long id;
    private String name;
    private int age;

    // Getters and Setters
}

5.2 创建缓存服务

创建一个UserService类,模拟数据库查询操作,并使用@Cacheable注解进行缓存。

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    // 模拟数据库查询
    public User findUserById(Long id) {
        // 模拟查询数据库的操作
        try {
            Thread.sleep(2000);  // 模拟延时
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new User(id, "User" + id, 25);
    }

    // 使用Spring Cache的@Cacheable注解进行缓存
    @Cacheable(value = "users", key = "#id")
    public User getUserById(Long id) {
        return findUserById(id);  // 调用数据库查询方法
    }
}

5.3 控制器层

创建一个UserController,通过REST API提供用户查询接口。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/user/{id}")
    public User getUserById(@PathVariable Long id) {
        return userService.getUserById(id);  // 获取用户信息
    }
}

5.4 运行与测试

运行这个Spring Boot应用。当你第一次访问/user/{id}时,Spring会查询数据库(模拟查询),并将结果存入Caffeine缓存中。第二次访问同样的用户时,Spring将直接从缓存中读取数据,从而大大提高了性能。

6. 缓存管理与过期策略

Caffeine提供了丰富的缓存管理策略。通过maximumSizeexpireAfterWriteexpireAfterAccess等配置,我们可以精细控制缓存的存活时间和最大容量。

6.1 缓存过期策略

Caffeine支持两种常见的过期策略:

  • expireAfterWrite:元素写入缓存后经过一定时间自动过期。
  • expireAfterAccess:元素在一定时间内没有访问则过期。

例如,在application.properties中配置:

spring.cache.caffeine.spec=maximumSize=100,expireAfterWrite=3600s

6.2 设置最大缓存大小

为了避免缓存占用过多内存,我们可以设置缓存的最大元素数量。Caffeine会根据LRU策略自动清除最少使用的元素。

spring.cache.caffeine.spec=maximumSize=100

7. 手动清除缓存

在某些情况下,我们可能需要手动清除缓存。例如,当数据发生变更时,我们需要删除旧的缓存数据。Spring提供了@CacheEvict注解来清除缓存。

@CacheEvict(value = "users", key = "#id")
public void updateUser(Long id, String name) {
    // 更新用户信息
}

@CacheEvict注解可以清除指定缓存的所有数据,或者仅清除某个特定的缓存项。

想获取更多高质量的Java技术文章?欢迎访问 Java技术小馆官网,持续更新优质内容,助力技术成长!

全部评论

相关推荐

1&nbsp;描述最左匹配原则并举例说明失效场景2&nbsp;聚簇索引与普通索引的区别3&nbsp;聚簇索引的缺点4&nbsp;聚簇索引叶子节点存什么5&nbsp;ES与MySQL的区别6&nbsp;ES的基本原理7&nbsp;缓存穿透、击穿、雪崩的概念及区别8&nbsp;缓存穿透的解决方案9&nbsp;布隆过滤器的底层原理10&nbsp;哈希函数越多越好吗11&nbsp;Redis如何实现分布式锁12&nbsp;除Redis外还能用什么实现分布式锁13&nbsp;Redisson是什么14&nbsp;Redisson相比原生Redis加锁的优势15&nbsp;Redis数据过期策略16&nbsp;Redis集群模式有哪些17&nbsp;主从模式有哪些形式18&nbsp;CompletableFuture与Future的区别19&nbsp;CompletableFuture常用的两个方法及区别20&nbsp;不传线程池时CompletableFuture默认使用什么21&nbsp;线程池核心参数如何设置22&nbsp;线程池任务执行流程23&nbsp;动态线程池了解吗24&nbsp;压测在性能调优中的作用25&nbsp;常用的并发安全容器有哪些26&nbsp;ConcurrentHashMap如何保证线程安全27&nbsp;HashTable与ConcurrentHashMap区别28&nbsp;synchronized与Lock的区别29&nbsp;synchronized与Lock谁更优30&nbsp;synchronized可以实现锁升级吗31&nbsp;volatile的作用32&nbsp;常用设计模式有哪些33&nbsp;单例模式在哪些场景使用34&nbsp;最常用的单例实现方式35&nbsp;手写单例(懒汉+双检锁)36&nbsp;单例中volatile的作用37&nbsp;Java&nbsp;GC存在的意义38&nbsp;垃圾对象的判定标准39&nbsp;分代收集机制中Eden与Survivor的作用40&nbsp;Survivor区比例41&nbsp;动态年龄判断机制42&nbsp;Sentinel实现限流的注解/方式43&nbsp;限流与熔断的区别44&nbsp;Caffeine的核心方法45&nbsp;Caffeine相比其他本地缓存的优势46&nbsp;MySQL性能调优流程47&nbsp;消息队列如何保证最终一致性48&nbsp;消息队列幂等性如何设计49&nbsp;Spring常用注解有哪些50&nbsp;@Autowired与@Resource区别51&nbsp;Spring&nbsp;Boot与Spring区别52&nbsp;事务注解@Transactional使用方式53&nbsp;@Transactional在什么场景会失效54&nbsp;算法题:合并两个有序链表
美团秋招笔试
点赞 评论 收藏
分享
评论
2
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务