springboot 集成caffeine单体缓存两种方式及算法简介 (注解/手动)

这篇具有很好参考价值的文章主要介绍了springboot 集成caffeine单体缓存两种方式及算法简介 (注解/手动)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.简介

       Caffeine 是基于 JAVA 8 的高性能缓存库。并且在 spring5 (springboot 2.x) 后,spring 官方放弃了 Guava,而使用了性能更优秀的 Caffeine 作为默认缓存组件。

       Caffeine 因为使用了 Window-TinyLFU 缓存淘汰策略,提供了一个近乎最佳的命中率。综合了 LRU 和 LFU 算法的长处,使其成为本地缓存之王。

        Least Recently Used:如果数据最近被访问过,将来被访问的概率也更高。每次访问就把这个元素放到队列的头部,队列满了就淘汰队列尾部的数据,即淘汰最长时间没有被访问的。缺点是,如果某一时刻大量数据到来,很容易将热点数据挤出缓存,留下来的很可能是只访问一次,今后不会再访问的或频率极低的数据。比如、微博爆出某明星糗事就是一个突发性热点事件。当事件结束后,可能没有啥访问量了,但是由于其极高的访问频率,导致其在未来很长一段时间内都不会被淘汰掉。

        Least Frequently Used:如果数据最近被访问过,那么将来被访问的概率也更高。也就是淘汰一定时间内被访问次数最少的数据(时间局部性原理)需要用 Queue 来保存访问记录,可以用 LinkedHashMap 来简单实现一个基于 LRU 算法的缓存。优点是,避免了 LRU 的缺点,因为根据频率淘汰,不会出现大量进来的挤压掉老的,如果在数据的访问的模式不随时间变化时候,LFU 能够提供绝佳的命中率。其缺点是,偶发性的、周期性的批量操作会导致LRU命中率急剧下降,缓存污染情况比较严重。

       W-TinyLFU 是 Caffeine 提出的一种全新算法,它可以解决频率统计不准确以及访问频率衰减的问题。这个方法让我们从空间、效率、以及适配举证的长宽引起的哈希碰撞的错误率上做均衡。在 W-TinyLFU 算法中,将整个缓存区划分为两大区域:Window Cache 和 Main Cache 。Window Cache 是一个标准的 LRU 缓存,只占整个缓存内存空间大小的 1% ; Main Cache 则是一个 SLRU (Segmented LRU) ,占整个缓存内存空间大小的 99% ,是缓存的主要区域。里面进一步被划分成两个区域:Probation Cache 观察区和 Protected Cache 保护区。Probation 观察区占 Main Cache 大小的 20%;而 Protected 保护区占 Main Cache 大小的 80% ,是 Main Cache 的主要区域。

2.caffeine相关配置说明

参数 类型 描述
initialCapacity integer 初始的缓存空间大小
maximumSize long 缓存的最大条数
maximumWeight long 缓存的最大权重
expireAfterAccess duration 最后一次写入或访问后,指定经过多长的时间过期
expireAfterWrite duration 最后一次写入后,指定经过多长的时间缓存过期
refreshAfterWrite duration 创建缓存或者最近一次更新缓存后,经过指定的时间间隔后刷新缓存
weakKeys boolean 打开 key 的弱引用
weakValues boolean 打开 value 的弱引用
softValues boolean 打开 value 的软引用
recordStats - 开发统计功能

Caffeine提供三种数据驱逐策略:基于大小驱逐、基于时间驱逐、基于引用驱逐

  1. maximumSize 和 maximumWeight 不可以同时使用。
  2. expireAfterWrite 和 expireAfterAccess 同时存在时,以 expireAfterWrite 为准
  3. weakValues 和 softValues 不可以同时使用。

Java中四种引用类型:

引用类型 被垃圾回收时间 用途 生存时间
强引用 Strong Reference 从来不会 对象的一般状态 JVM停止运行时终止
软引用 Soft Reference 在内存不足时 对象缓存 内存不足时终止
弱引用 Weak Reference 在垃圾回收时 对象缓存 gc运行后终止
虚引用 Phantom Reference 从来不会 可以用虚引用来跟踪对象被垃圾回收器回收的活动,当一个虚引用关联的对象被垃圾收集器回收之前会收到一条系统通知 JVM停止运行时终止

3.springboot集成caffeine

  1. 直接引入 Caffeine 依赖,然后创建 Caffeine 方法实现缓存。
  2. 引入 Caffeine 和 SpringCache 依赖,使用 SpringCache 注解方法实现缓存。(推荐)
  3. 引入jar包 版本也可根据不写 根据springboot版本走
        <!-- caffeine本地缓存 -->
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
            <version>2.8.5</version>
        </dependency>
        <!--  对于@EnableCaching注解开启-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
            <version>2.3.2.RELEASE</version>
        </dependency>
  • @Cacheable:先查询缓存是否存在,如果存在,则返回结果;如果不存在,则执行方法,并将结果保存在缓存中。主要用于查询操作
  • @CachePut:不检查缓存中是否存在,直接执行方法,并将结果保存在缓存中。主要用于数据新增和修改操作
  • @CacheEvict:从缓存中移除指定的key数据,如果allEntries属性为true,则清除全部;如果beforeInvocation属性为true,则在方法执行前删除。主要用于删除操作

3.1 方式一 只用Caffeine


/**
 * caffeine缓存配置 
 * - 优点:可以针对每个cache配置不同的参数,比如过期时长、最大容量(定制化配置) 
 * 可定义多个
 **/
@Configuration
public class CaffeineConfig {
    @Bean
    public Cache<Long, ItemStock> userDtoCache() {
        // 构建cache对象
        return Caffeine.newBuilder()
                //0) 驱逐策略:基于容量,时间,引用。
                //0.1 基于时间
                .expireAfterWrite(10, TimeUnit.MINUTES)
                //0.2.1 基于容量
                //初始容量
                .initialCapacity(100)
                .maximumSize(10_000)
//                //0.2.2 权重
//                .weigher(((key, value) -> {
//                    if (key.equals(1)) {
//                        return 1;
//                    } else {
//                        return 2;
//                    }
//                }))
                //0.3 基于引用
                //0.3.1 当进行GC的时候进行驱逐
//                .softValues()
                //0.3.2 当key和缓存元素都不再存在其他强引用的时候驱逐
//                .weakKeys()
//                .weakValues()
                .build();
    }

测试类文章来源地址https://www.toymoban.com/news/detail-774471.html

@SpringBootTest(classes = CaffeineApplication.class)
@RunWith(SpringRunner.class)
public class CaffeineTest{

    @Autowired
    private Cache<Long, UserDto> userDtoCache;
    

    @Test
    public void test1() {
        //1) 新增
        // 添加或者更新一个缓存元素
        userDtoCache.put(1L, UserDto.builder()
                .id(1L)
                .name("迪丽热巴")
                .age(18)
                .build());

        // 查找缓存,如果缓存不存在则生成缓存元素,  如果无法生成则返回null
        UserDto user2 = userDtoCache.get(2L, key -> {
            // 根据key去数据库查询数据
            return UserDto.builder()
                    .id(key)
                    .name("柳岩")
                    .age(24)
                    .build();
        });


        //2) 查询
        // 取数据,上面的get也算
        UserDto user1 = userDtoCache.getIfPresent(1L);

        System.out.println("user1 = " + user1);
        System.out.println("user2 = " + user2);

        //3) 删除
        // 移除一个缓存元素
        userDtoCache.invalidate(1L);
        user1 = userDtoCache.getIfPresent(1L);
        System.out.println("user1 = " + user1);

        // 批量失效key
        userDtoCache.invalidateAll(Arrays.asList(1L, 2L));
        // 失效所有的key
        userDtoCache.invalidateAll();

        System.out.println("defaultGF2 = " + userDtoCache.getIfPresent("defaultGF"));
    }

3.2 加入SpringCache 通过注解方式

@Configuration
@EnableCaching
public class CaffeineConfig {
    /**
     * 配置缓存管理器
     *
     * @return 缓存管理器
     */
    @Bean("caffeineCacheManager")
    public CacheManager cacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager();
        cacheManager.setCaffeine(Caffeine.newBuilder()
                // 设置最后一次写入或访问后经过固定时间过期
//                .expireAfterAccess(60, TimeUnit.SECONDS)
                // 初始的缓存空间大小
                .initialCapacity(100)
                // 缓存的最大条数
                .maximumSize(1000));
        return cacheManager;
    }

}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

  @Autowired
  private UserMapper userMapper;


  @Override
  @Cacheable(key = "#id" , value = "caffeineCacheManager")
  public User selectById(Long id) {
    User user = userMapper.selectById(id);
    return user;
  }

  @Override
  @CachePut(key = "#result.id" , value = "caffeineCacheManager")
  public User addUserInfo(UserDto userDto) {
    User user = new User();
    BeanUtils.copyProperties(userDto, user);
    int insert = userMapper.insert(user);
    return user;
  }

  @Override
  @CachePut(key = "#userDto.id" , value = "caffeineCacheManager")
  public User updateUserInfo(UserDto userDto) {
    User user = new User();
    BeanUtils.copyProperties(userDto, user);
    userMapper.updateById(user);
    return user;
  }

  @Override
  @CacheEvict(key = "#id" , value = "caffeineCacheManager")
  public void deleteById(Long id) {
    UpdateWrapper updateWrapper = new UpdateWrapper();
    updateWrapper.eq("id", id);
    userMapper.delete(updateWrapper);
  }
}

到了这里,关于springboot 集成caffeine单体缓存两种方式及算法简介 (注解/手动)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用Spring管理Caffeine缓存(CacheManager+Caffeine)

    使用Spring管理Caffeine缓存的主要pom依赖如下所示。 CacheManager配置类如下所示。 使用Caffeine在本地缓存查询结果,使用案例如下所示。 (1)关于maximumSize 当首次设置缓存并尝试存入的数据量大于设置的maximumSize时,Caffeine不会直接报错。但是,当尝试将新数据添加到已满的缓存

    2024年01月19日
    浏览(36)
  • 多级缓存架构(二)Caffeine进程缓存

    通过本文章,可以完成多级缓存架构中的进程缓存。 在 item-service 中引入 caffeine 依赖 这是Caffeine官方文档地址 1. 配置Config类 创建 config.CaffeineConfig 类 2. 修改controller 在 ItemController 中注入两个 Cache 对象,并修改业务逻辑 Idea结合Docker将springboot放入docker容器中运行,并指定使用

    2024年02月02日
    浏览(54)
  • 缓存平均的两种算法

    引言         线边库存物料的合理性问题是物流仿真中研究的重要问题之一,如果线边库存量过多,则会对生产现场的布局产生负面影响,增加成本,降低效益。 写在前面         仿真分析后对线边Buffer的使用情况进行合理的评估就是一个非常重要的事情。比较关心的参数

    2024年02月13日
    浏览(35)
  • 实现本地缓存-caffeine

    目录 实现caffeine cache CacheManager Caffeine配置说明 创建自定义配置类 配置缓存管理器 编写自动提示配置文件 测试使用 创建测试配置实体类 创建测试配置类 创建注解扫描的测试实体 创建单元测试类进行测试 实现caffeine cache CacheManager SimpleCacheManager: 这种缓存管理器允许你在应

    2024年02月17日
    浏览(35)
  • Caffeine本地缓存

    简单说,Caffine 是一款高性能的本地缓存组件 由下面三幅图可见:不管在并发读、并发写还是并发读写的场景下,Caffeine 的性能都大幅领先于其他本地开源缓存组件 它是优先淘汰掉最先缓存的数据、是最简单的淘汰算法。 缺点是如果先缓存的数据使用频率比较高的话,那么

    2024年02月09日
    浏览(40)
  • JVM进程缓存Caffeine

    导入坐标: 写一个配置类: 注入bean // 取数据,包含两个参数: // 参数一:缓存的key // 参数二:Lambda表达式,表达式参数就是缓存的key,方法体是查询数据库的逻辑 // 优先根据key查询JVM缓存,如果未命中,则执行参数二的Lambda表达式 增删改 都要清除缓存

    2024年02月11日
    浏览(50)
  • 缓存 - Caffeine 不完全指北

    https://github.com/ben-manes/caffeine wiki: https://github.com/ben-manes/caffeine/wiki Caffeine是一个用于Java应用程序的高性能缓存框架。它提供了一个强大且易于使用的缓存库,可以在应用程序中使用,以提高数据访问的速度和效率。 下面是一些Caffeine缓存框架的主要特点: 高性能:Caffeine的设

    2024年02月16日
    浏览(41)
  • 地表最帅缓存Caffeine

    缓存是程序员们绕不开的话题,像是常用的本地缓存Guava,分布式缓存Redis等,是提供高性能服务的基础。今天敬姐带大家一起认识一个更高效的本地缓存—— Caffeine 。 Caffeine Cache使用了基于内存的存储策略,并且支持高并发、低延迟,同时还提供了缓存过期、定时刷新、缓存

    2024年02月10日
    浏览(52)
  • java缓存框架Caffeine详解

    缓存在日常开发中启动至关重要的作用,基本是存储在内存中,数据的读取速度是非常快的,能大量减少对数据库的访问,减少数据库的压力,本文主要介绍了本地缓存Caffeine基本配置与基本用法,通过阅读本文,你将了解什么是Caffeine,如何使用Caffeine。 1.1 什么是本地缓存

    2024年02月13日
    浏览(26)
  • 基于总线加锁和缓存锁(CPU实现原子操作的两种方式)

    总线锁 就是使用处理器提供的一个LOCK#信号,当一个处理器在总线上输出此信号时,其他处理器的请求将被阻塞住,那么该处理器可以独占共享内存。 CPU和内存之间的通信被锁!! 如果多个处理器同时对共享变量进行读写改操作,那么共享变量就会被多个处理器同时进行操

    2024年02月14日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包