理论
🍎缓存
缓存是提升系统性能的一个不可或缺的工具,通过缓存可以避免大部分重复的请求到数据库层,减少IO连接次数,进而提升整体的响应速率;
缓存工具可以分为本地缓存(如Caffeine)和分布式缓存(如Redis),优先使用本地缓存,一般情况下使用分布式缓存有点大材小用;
🍎Caffeine
定义:
是一个现代化的 Java 缓存库,设计用于提供高性能和可伸缩性的本地缓存解决方案。
是一种自带存储和移除策略的Map;
适用于高并发以及快速访问数据的场景,因为内部实现了基于 ConcurrentHashMap 的数据结构,从而保证并发访问时的线程安全和高性能。
优点:
使用caffeine做本地缓存,取数据可以达到微秒的级别,通常一次取数据用时不足1毫秒;
支持并发,与ConcurrentMap很像,并且支持O(1)时间复杂度的数据存取;
二者的主要区别在于: ConcurrentMap将存储所有存入的数据,直到显式将其移除;
Caffeine将通过给定的配置,自动移除“不常用”的数据,以保持内存的合理占用。
本地缓存的三种实现方式
手动实现
同步实现
异步实现
使用
redis+caffeine本地缓存
- 依赖导入
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
- 注入caffeine配置,结合redis实现本地缓存
@Component
public class xxxCache {
@Autowired
private RedisOperations redisOperations;
private Cache<String, xxxInfoVo> xxxCache;
@PostConstruct
public void init() {
xxxCache = Caffeine.newBuilder()
.expireAfterWrite(1, TimeUnit.DAYS)
.initialCapacity(500)
.maximumSize(5000)
.recordStats()
.build(new CacheLoader<String, MsAppInfoVo>() {
@Override
public @Nullable xxxInfoVo load(@NonNull String xxxId) {
String appStr = redisOperations.get(ApiConstant.XXX + xxxId);
if (appStr == null) {
return null;
}
try {
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
return gson.fromJson(appStr, xxxInfoVo.class);
} catch (Exception e) {
return null;
}
}
});
}
}
getIfPresent和get方法
1. 在缓存命中时,当缓存中存在要获取的键值对时,getIfpresent方法通常比get方法性能更好。
因为 getIfPresent 只是一个简单的査找操作,而 get方法虽然也能返回值,但它有一些额外的逻辑检査(例如检査是否需要重新加载等),尽管在这种情况下不会执行加载操作,但这些逻辑检查仍然会带来少量的性能开销。
2. 在缓存未命中时,如果缓存中不存在要获取的键值对,getrfPresent 会立即返回 nu11,性能开销很小。
而get方法会触发缓存加载逻辑,其性能取决于加载逻辑的复杂程度,可能会有较大的性能开销,特别是当加载操作涉及到网络请求数据库查询或者复杂计算时。
最后