spring boot + caffeine使用

一、Caffeine 缓存背景

Caffeine是一个高性能、可扩展的Java缓存库,由Google的Ben Manes开发。Caffeine基于ConcurrentHashMap设计,采用了近似LRU(Least Recently Used,最近最少使用)算法,以实现高速缓存淘汰策略。Caffeine广泛应用于各类Java项目中,作为一种提高数据读取性能的优秀解决方案。

二、Caffeine 缓存优点与缺点

优点:

高性能:Caffeine性能优于许多其他缓存库,因其采用了近似LRU算法,实现了高效的缓存淘汰策略。
灵活性:Caffeine提供了丰富的配置选项,用户可根据项目需求灵活定制缓存策略。
易集成:Caffeine可轻松与Spring Boot框架集成,实现便捷的缓存管理。
易于使用:Caffeine API简洁易懂,便于开发者快速上手。

缺点:

仅支持Java:Caffeine为Java特有的缓存库,不能直接应用于其他编程语言。
近似LRU算法:虽然Caffeine采用了高效的近似LRU算法,但在某些场景下,其性能可能不如精确的LRU算法。


三、Caffeine 缓存基本使用方法

1.添加Caffeine依赖:

<!-- caffeine服务器本地缓存 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <!-- caffeine -->
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
            <version>2.9.1</version>
        </dependency>
        <!--   可以对自定义配置的信息进行提示 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
        </dependency>

2.配置yml:

spring:
  cache:
    type: caffeine
    caffeine:
      spec: maximumSize=500,expireAfterWrite=10m

3.自定义缓存:MyCacheComponent.java(一般我都是用自定义的)

import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.Cache;
import org.springframework.stereotype.Component;
import java.io.*;

@Component
public class MyCacheComponent {

    private final Cache<String, byte[]> cache;

    public MyCacheComponent() {
        // 初始化Caffeine缓存,存储键为String类型,值为byte[]类型(序列化后的对象)
        this.cache = Caffeine.newBuilder()
                .maximumSize(100) // 设置缓存的最大容量
                .build();
    }

    public void put(String key, Serializable value) {
        try {
            // 将对象序列化为字节数组
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(value);
            byte[] serializedValue = byteArrayOutputStream.toByteArray();

            // 将序列化后的字节数组存储到缓存中
            cache.put(key, serializedValue);
        } catch (IOException e) {
            // 处理序列化时的异常
            throw new RuntimeException("Failed to serialize value", e);
        }
    }

    public <T extends Serializable> T get(String key, Class<T> type) {
        byte[] serializedValue = cache.getIfPresent(key);
        if (serializedValue != null) {
            try {
                // 将字节数组反序列化为对象
                ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(serializedValue));
                return (T) objectInputStream.readObject();
            } catch (IOException | ClassNotFoundException e) {
                // 处理反序列化时的异常
                throw new RuntimeException("Failed to deserialize value", e);
            }
        }
        return null;
    }

    public <T extends Serializable> T get(String key) {
        byte[] serializedValue = cache.getIfPresent(key);
        if (serializedValue != null) {
            try {
                // 将字节数组反序列化为对象
                ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(serializedValue));
                return (T) objectInputStream.readObject();
            } catch (IOException | ClassNotFoundException e) {
                // 处理反序列化时的异常
                throw new RuntimeException("Failed to deserialize value", e);
            }
        }
        return null;
    }


    public void delete(String key) {
        byte[] serializedValue = cache.getIfPresent(key);
        if (serializedValue != null) {
            try {
                cache.invalidate(key);
            } catch (Exception e) {
                throw new RuntimeException("Failed", e);
            }
        }
    }
}

4.Impl中使用

import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import xx.xxxx.xxx.utils.MyCacheComponent;

@Service
public class BaseServiceImpl implements BaseService {

    @Autowired
    private CacheManager cacheManager;

    @Autowired
    private MyCacheComponent myCacheComponent;

    @Autowired
    private BaseMapper baseMapper;

    
    //新增业务
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(BaseDTO dto) {
        if (dto.getUserId != null) {
            //新增前先删除缓存
            myCacheComponent.delete(userId);
        }
        ···
        ···
        //执行新增操作
        baseMapper.insert(entity);
        
        //新增完删除缓存,避免并发导致脏数据
        if (dto.getUserId != null) {
            //新增完删除缓存
            myCacheComponent.delete(userId);
        }
    }

    
    //修改业务
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(BaseDTO dto) {
        if (dto.getUserId != null) {
            //修改前先删除缓存
            myCacheComponent.delete(userId);
        }
        ···
        ···
        //执行修改操作
        baseMapper.updateById(entity);
        
        //修改完删除缓存,避免并发导致脏数据
        if (dto.getUserId != null) {
            //修改完删除缓存
            myCacheComponent.delete(userId);
        }
    }

    //获取数据
    @Override
    public List<BaseVO> getList(Long userId) {
        //查缓存,有则返回,没有则查询数据库,然后存进缓存
        Object list = myCacheComponent.get(userId);

        if(list != null){
            return (List<BaseVO>) list;
        }
        ···
        ···
        //获取数据库或者redis数据
        List<BaseEntity> dalist = baseMapper.selectList(Wrappers.<BaseEntity>);
        
        //存入缓存
        if (CollectionUtil.isNotEmpty(dalist)) {
            myCacheComponent.put(userId, (Serializable) list);
        }
        
    }
    

    
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值