Spring Boot —— Caffeine(内存缓存器)
如果你的应用对于低延迟的响应非常关键,例如实时数据查询或高频率的请求处理,Caffeine 可以提供快速的缓存访问,以满足这些要求。如果你的应用在内存敏感的环境中运行,例如云计算平台或资源受限的设备,Caffeine 可以帮助减少内存占用并提高应用的可伸缩性。相比于远程缓存方案,本地缓存具有更低的访问延迟和更高的吞吐量,特别适用于需要快速访问和频繁更新的数据。如果你的应用需要处理大量并发的读写操作
Spring Boot Caffeine
优点
- 内存管理优化
Caffeine 使用了一种基于堆内内存的存储模型,通过直接内存访问,避免了 Java 堆内存的垃圾回收开销。这种内存管理优化可以减少垃圾回收对应用性能的影响,提供更高的缓存读写性能。 - 高效的缓存策略
Caffeine 提供了多种缓存策略,包括基于容量、基于时间、基于引用等。这些策略可以根据应用的需求进行灵活配置,以获得最佳的缓存性能和命中率。 - 并发性能优化
Caffeine 在并发访问时表现出色。它采用了细粒度的锁机制和无锁的数据结构,有效地减少了并发冲突的影响,并提供了较低的锁竞争和高并发的访问性能。 - 功能丰富
Caffeine 提供了丰富的功能,例如异步加载、缓存监听器、过期策略、缓存统计等。这些功能可以帮助开发者更好地控制和管理缓存,满足各种业务需求。
对比
- Guava Cache 相比
Caffeine 在读写性能、并发性能、内存管理方面有明显的提升,并提供了更多的配置选项和功能扩展。 - Ehcache 相比
Caffeine 在读写性能、并发性能、内存管理方面也表现出更好的性能,并且具有更灵活的缓存策略和配置选项。 - Redis 等远程缓存存储进行比较时
Caffeine 作为本地缓存库具有更低的访问延迟和更高的吞吐量,适用于高性能的本地缓存场景。
适用场景
-
高并发读写
Caffeine 在并发读写的场景下具有出色的性能表现。如果你的应用需要处理大量并发的读写操作,例如缓存数据的读取和更新,Caffeine 可以提供高吞吐量和低延迟的访问性能。 -
低延迟要求
Caffeine 采用了一些优化技术,如直接内存访问和细粒度的锁机制,以降低访问延迟。如果你的应用对于低延迟的响应非常关键,例如实时数据查询或高频率的请求处理,Caffeine 可以提供快速的缓存访问,以满足这些要求。 -
内存敏感应用
Caffeine 提供了高效的内存管理策略,可以优化内存使用并减少垃圾回收的开销。如果你的应用在内存敏感的环境中运行,例如云计算平台或资源受限的设备,Caffeine 可以帮助减少内存占用并提高应用的可伸缩性。 -
热数据缓存
Caffeine 提供了多种缓存策略,包括基于容量、基于时间和基于引用的策略。这使得 Caffeine 在热数据缓存方面非常适用,可以根据数据的访问频率和最近使用时间来调整缓存策略,以提高热数据的命中率。 -
本地缓存需求
Caffeine 是一个本地缓存库,适用于需要在应用内部管理和存储数据的场景。相比于远程缓存方案,本地缓存具有更低的访问延迟和更高的吞吐量,特别适用于需要快速访问和频繁更新的数据。
总体而言,Caffeine 适用于需要高性能、低延迟、内存敏感以及本地缓存需求的应用场景。它在处理并发访问、内存管理、缓存策略和性能优化方面具有优势,并提供了丰富的功能和配置选项,能够满足各种应用需求。
实战
依赖
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<!-- jdk8用2.x.x -->
<!-- jdk11+用3.x.x -->
<!-- 版本3.x.x是通过java11编译的 -->
<version>2.9.3</version>
</dependency>
工具类
public class CaffeineUtil {
/**
* 缓存的最大容量
*/
private static final int MAXIMUM_SIZE = 1000;
/**
* 缓存项的写入后过期时间
*/
private static final int EXPIRE_AFTER_WRITE_DURATION = 30;
/**
* 过期时间单位(分钟)
*/
private static final TimeUnit EXPIRE_AFTER_WRITE_TIMEUNIT = TimeUnit.MINUTES;
private static Cache<String, Object> cache;
/**
* 初始化Caffeine缓存配置
*/
static {
cache = Caffeine.newBuilder()
.maximumSize(MAXIMUM_SIZE)
.expireAfterWrite(EXPIRE_AFTER_WRITE_DURATION, EXPIRE_AFTER_WRITE_TIMEUNIT)
.build();
}
/**
* 获取缓存值
*
* @param key 缓存键
* @return 缓存值
*/
public static Object get(String key) {
return cache.getIfPresent(key);
}
/**
* 设置缓存值
*
* @param key 缓存键
* @param value 缓存值
*/
public static void put(String key, Object value) {
cache.put(key, value);
}
/**
* 移除缓存项
*
* @param key 缓存键
*/
public static void remove(String key) {
cache.invalidate(key);
}
/**
* 清空缓存
*/
public static void clear() {
cache.invalidateAll();
}
/**
* 获取缓存中的所有值
*
* @return 缓存中的所有值集合
*/
public static Collection<Object> getAllValues() {
return cache.asMap().values();
}
/**
* 清空缓存中的所有值
*/
public static void removeAllValues() {
cache.invalidateAll();
}
}
使用
@Service
public class CaffeineServiceImpl implements CaffeineService {
@Override
public Result operate() {
// 向缓存中放入数据
CaffeineUtil.put("key1", "value1");
CaffeineUtil.put("key2", "value2");
// 从缓存中获取数据
String value1 = String.valueOf(CaffeineUtil.get("key1"));
String value2 = String.valueOf(CaffeineUtil.get("key2"));
// 输出: Value 1: value1
System.out.println("Value 1: " + value1);
// 输出: Value 2: value2
System.out.println("Value 2: " + value2);
Collection<Object> values = CaffeineUtil.getAllValues();
for (Object value : values) {
System.out.println("所有Value:"+value);
}
// 从缓存中移除数据
CaffeineUtil.remove("key2");
// 再次获取数据
String value2AfterInvalidation = String.valueOf(CaffeineUtil.get("key2"));
// 输出: Value 2 after invalidation: null
System.out.println("Value 2 after invalidation: " + value2AfterInvalidation);
return Result.success();
}
}
单元测试
@Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = CaffeineApplication.class)
public class CaffeineServiceImplTest {
@Autowired
private CaffeineServiceImpl caffeineService;
@Before
public void before() throws Exception {
}
@After
public void after() throws Exception {
}
@Test
public void method() {
log.info(JSONObject.toJSONString(caffeineService.operate()));
}
}
更多推荐
所有评论(0)