项目缓存之Caffeine咖啡因

理论

🍎缓存
	缓存是提升系统性能的一个不可或缺的工具,通过缓存可以避免大部分重复的请求到数据库层,减少IO连接次数,进而提升整体的响应速率;
	缓存工具可以分为本地缓存(如Caffeine)和分布式缓存(如Redis),优先使用本地缓存,一般情况下使用分布式缓存有点大材小用;
🍎Caffeine
定义:
	是一个现代化的 Java 缓存库,设计用于提供高性能和可伸缩性的本地缓存解决方案。
	是一种自带存储和移除策略的Map;
	适用于高并发以及快速访问数据的场景,因为内部实现了基于 ConcurrentHashMap 的数据结构,从而保证并发访问时的线程安全和高性能。
优点:
	使用caffeine做本地缓存,取数据可以达到微秒的级别,通常一次取数据用时不足1毫秒;
	支持并发,与ConcurrentMap很像,并且支持O(1)时间复杂度的数据存取;
	二者的主要区别在于:	ConcurrentMap将存储所有存入的数据,直到显式将其移除; 
						Caffeine将通过给定的配置,自动移除“不常用”的数据,以保持内存的合理占用。

本地缓存的三种实现方式

手动实现

同步实现

异步实现

使用

redis+caffeine本地缓存

  1. 依赖导入
<dependency>
   <groupId>com.github.ben-manes.caffeine</groupId>
   <artifactId>caffeine</artifactId>
</dependency>
  1. 注入caffeine配置,结合redis实现本地缓存
@Component
// 一个Spring框架中的组件,可以被Spring容器自动发现并管理。
public class xxxCache {
    @Autowired
    // 依赖注入
    private RedisOperations redisOperations;

    private Cache<String, xxxInfoVo> xxxCache;

    @PostConstruct
    // 在该bean的所有依赖注入完成后被调用。
    public void init() {
	    // Caffeine缓存实例
        xxxCache = Caffeine.newBuilder()
                // 写入或者更新1天后,缓存过期并失效
                .expireAfterWrite(1, TimeUnit.DAYS)
                // 初始的缓存空间大小 500个条目
                .initialCapacity(500)
                // 缓存的最大条数,通过 Window TinyLfu算法控制整个缓存大小
                .maximumSize(5000)
                // 打开数据收集功能
                .recordStats()
                .build(new CacheLoader<String, MsAppInfoVo>() {
                // 当尝试访问不存在于缓存中的键时,CacheLoader将被用来加载数据。
                    @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方法会触发缓存加载逻辑,其性能取决于加载逻辑的复杂程度,可能会有较大的性能开销,特别是当加载操作涉及到网络请求数据库查询或者复杂计算时。

最后

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值