Spring Boot —— Caffeine(内存缓存器)
项目中需要用一个替代concurrenthashmap 能够帮忙过期或者防止一直put oom所以使用
优点
内存管理优化
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())); } }
其他博客参考
https://blog.csdn.net/guo_123258/article/details/115716413