Spring Boot整合Guava Cache:轻量级缓存方案解析

350 阅读4分钟

在高并发应用中,缓存能够显著提升系统性能,减少数据库查询压力。相比于Redis等分布式缓存,Guava Cache 作为本地缓存方案,适用于单机高效缓存场景,具有自动过期、大小限制和LRU淘汰策略等特性。

本文将带你深入了解Guava Cache的原理,并通过Spring Boot示例实现高效的本地缓存,适用于热点数据存储、配置项缓存等场景。

一、为什么选择Guava Cache?

Guava Cache 是 Google 开源的高效内存缓存库,它适用于单机环境,特点如下:

  • 轻量级:无需外部依赖,直接运行在JVM内存中。
  • 自动失效:支持基于时间(TTL)、访问次数等策略自动清理数据。
  • LRU淘汰:基于**最近最少使用(LRU)**策略清理缓存,保证热点数据优先存储。
  • 预加载 & 异步刷新:可预先加载数据,避免缓存击穿。

适用场景:

  • 热点数据:如用户登录信息、本地配置缓存等。
  • 短时间内高频访问数据:如数据字典、热门排行榜等。
  • 非分布式环境:如单节点API服务,无需Redis等分布式缓存时。

二、引入Guava Cache依赖

Guava Cache 已集成在 Google Guava 库 中,我们可以在 Spring Boot 项目中引入它:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>32.1.2-jre</version>
</dependency>

三、使用Guava Cache进行本地缓存

1. 基本用法

首先,我们来创建一个简单的Guava Cache,并添加、获取数据:

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.concurrent.TimeUnit;

public class GuavaCacheExample {
    public static void main(String[] args) throws InterruptedException {
        // 创建缓存,设置最大容量100,数据10秒后过期
        Cache<String, String> cache = CacheBuilder.newBuilder()
                .maximumSize(100) // 设置最大缓存数,超过后按LRU策略淘汰
                .expireAfterWrite(10, TimeUnit.SECONDS) // 10秒后过期
                .build();

        // 添加缓存
        cache.put("key1", "value1");

        // 读取缓存
        System.out.println("获取缓存:" + cache.getIfPresent("key1")); // 输出: value1

        // 等待缓存过期
        TimeUnit.SECONDS.sleep(11);
        System.out.println("缓存过期后:" + cache.getIfPresent("key1")); // 输出: null
    }
}

缓存策略解析

  • maximumSize(100):限制缓存最大100个对象,超过后使用LRU淘汰策略。
  • expireAfterWrite(10, TimeUnit.SECONDS):数据写入后10秒过期。

2. 在Spring Boot中使用Guava Cache

我们可以在 Spring Boot 中创建本地缓存服务,用于存储热点数据,如用户信息。

① 创建 GuavaCacheConfig 配置类

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;

@Configuration
public class GuavaCacheConfig {

    @Bean
    public Cache<String, Object> guavaCache() {
        return CacheBuilder.newBuilder()
                .maximumSize(200) // 设置最大缓存数
                .expireAfterWrite(5, TimeUnit.MINUTES) // 5分钟过期
                .build();
    }
}

② 创建缓存服务

import com.google.common.cache.Cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Optional;

@Service
public class UserCacheService {

    @Autowired
    private Cache<String, Object> guavaCache;

    // 添加用户信息到缓存
    public void saveUser(String userId, String userInfo) {
        guavaCache.put(userId, userInfo);
    }

    // 获取缓存中的用户信息
    public String getUser(String userId) {
        return Optional.ofNullable((String) guavaCache.getIfPresent(userId))
                .orElse("缓存未命中");
    }

    // 删除缓存
    public void removeUser(String userId) {
        guavaCache.invalidate(userId);
    }
}

③ 创建Controller,提供API访问

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/cache")
public class CacheController {

    @Autowired
    private UserCacheService userCacheService;

    // 添加缓存
    @PostMapping("/save/{userId}")
    public String saveUser(@PathVariable String userId, @RequestParam String userInfo) {
        userCacheService.saveUser(userId, userInfo);
        return "用户信息已缓存:" + userInfo;
    }

    // 获取缓存
    @GetMapping("/get/{userId}")
    public String getUser(@PathVariable String userId) {
        return userCacheService.getUser(userId);
    }

    // 删除缓存
    @DeleteMapping("/remove/{userId}")
    public String removeUser(@PathVariable String userId) {
        userCacheService.removeUser(userId);
        return "缓存已删除:" + userId;
    }
}

四、Guava Cache进阶特性

1. 自动加载数据

使用 CacheLoader 可以在缓存未命中时自动加载数据

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.util.concurrent.TimeUnit;

public class GuavaCacheWithLoader {
    public static void main(String[] args) throws Exception {
        LoadingCache<String, String> cache = CacheBuilder.newBuilder()
                .maximumSize(100)
                .expireAfterWrite(10, TimeUnit.MINUTES)
                .build(new CacheLoader<String, String>() {
                    @Override
                    public String load(String key) {
                        return "加载的数据:" + key;
                    }
                });

        System.out.println(cache.get("user123")); // 缓存未命中时,自动调用load方法
    }
}

2. 定时清理缓存

使用 expireAfterAccess 控制数据最后一次访问后多久过期

Cache<String, String> cache = CacheBuilder.newBuilder()
        .expireAfterAccess(5, TimeUnit.MINUTES) // 最后访问5分钟后过期
        .build();

适用于长时间未访问的缓存数据自动清理

五、Guava Cache vs. Redis

特性Guava CacheRedis
存储位置JVM 内存独立服务
访问速度纳秒级毫秒级
适用场景本地缓存,热点数据分布式缓存,全局共享数据
过期策略LRU+TTLTTL+LRU
支持分布式

结论:Guava Cache 适用于单机高并发的本地缓存,而 Redis 更适用于分布式系统中的共享缓存

六、总结

  • Guava Cache 是 Spring Boot 轻量级缓存方案,适用于本地热点数据存储
  • 它提供了自动过期、LRU 淘汰、自动加载等特性,并可结合 Spring Boot 进行缓存管理。
  • 适用场景:本地缓存、配置项缓存、高速查询数据存储,避免 Redis 依赖。

适用于你的业务需求吗?欢迎留言讨论!🚀