在高并发应用中,缓存能够显著提升系统性能,减少数据库查询压力。相比于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 Cache | Redis |
|---|---|---|
| 存储位置 | JVM 内存 | 独立服务 |
| 访问速度 | 纳秒级 | 毫秒级 |
| 适用场景 | 本地缓存,热点数据 | 分布式缓存,全局共享数据 |
| 过期策略 | LRU+TTL | TTL+LRU |
| 支持分布式 | ❌ | ✅ |
结论:Guava Cache 适用于单机高并发的本地缓存,而 Redis 更适用于分布式系统中的共享缓存。
六、总结
- Guava Cache 是 Spring Boot 轻量级缓存方案,适用于本地热点数据存储。
- 它提供了自动过期、LRU 淘汰、自动加载等特性,并可结合
Spring Boot进行缓存管理。 - 适用场景:本地缓存、配置项缓存、高速查询数据存储,避免 Redis 依赖。
适用于你的业务需求吗?欢迎留言讨论!🚀