zoukankan      html  css  js  c++  java
  • 内存缓存Caffeine

    Caffeine是什么?

    Caffeine是使用Java8对Guava缓存的重写版本。大大改善了设计Guava's cache 和 ConcurrentLinkedHashMap 的体验。
    Caffeine是一种高性能的缓存库,是基于Java 8的最佳(最优)缓存框架。

    Guava Cache是什么?

    Google Guava Cache是一种非常优秀本地缓存解决方案,提供了基于容量,时间和引用的缓存回收方式。

    Caffeine能做什么?

    数据缓存在jvm中,大幅提升性能

    为什么要用本地缓存

    相对于IO操作,速度快,效率高
    相对于Redis,Redis是一种优秀的分布式缓存实现,受限于网卡等原因,远水救不了近火

    本地缓存的缺点

    节点重启、缓存丢失
    无法大量存储,受限于jvm
    集群多节点缓存不一致问题

    什么时候使用

    相同的结果被大量访问
    愿意消耗一些内存空间来提升速度
    缓存中存放的数据总量不会超出内存容量

    主流缓存对比

    Caffeine淘汰算法比较先进,并且得到 Spring Cache 的支持(新版的 Spring Cache 不再支持 Guava Cache)

    spring2.x接入

    第一步、添加依赖

    <dependency>
      <groupId>com.github.ben-manes.caffeine</groupId>
        <artifactId>caffeine</artifactId>
        <version>2.9.2</version>
    </dependency>
    

    第二步创建CaffeineCacheConfig.java

    @Configuration
    public class CacheConfig {
    
        @Bean
        public Cache<String, Object> caffeineCacheObject() {
            return Caffeine.newBuilder()
                    // 设置最后一次写入或访问后经过固定时间过期
                    .expireAfterWrite(60, TimeUnit.SECONDS)
                    // 初始的缓存空间大小
                    .initialCapacity(100)
                    // 缓存的最大条数
                    .maximumSize(1000)
                    .build();
        }
    }
    

    第三步、注入

    @Autowired
    Cache<String, Object> caffeineCache;
    

    第四步、使用

    ####(1)添加到缓存
      caffeineCache.put("abc","def");
    
    ####(2)从缓存获取
      Object obj = caffeineCache.getIfPresent("abc");
    
    ####(3)从缓存获取,若获取不到,则调用createInfo("abc")加载到缓存,再返回结果
      Object o = caffeineCache.get("abc",k -> createInfo("abc"));
    
    ####(4)存入实体类
      caffeineCache.put("obj",new UserInfo(3,"cat"));
      Object obj2 = caffeineCache.getIfPresent("obj");
      UserInfo ui2 = (UserInfo)obj2;
    
    ####(5)存入List<String>
      List<String> strList = new ArrayList<>();
      strList.add("a");
      strList.add("b");
      strList.add("c");
      strList.add("d");
      caffeineCache.put("strList",strList);
      Object strListCache = caffeineCache.getIfPresent("strList");
      List<String> strList2 = (List<String>)strListCache;
    
    ####(6)存入List<UserInfo>
      //测试list
      List<UserInfo> objList = new ArrayList<>();
      objList.add(new UserInfo(3,"cat"));
      objList.add(new UserInfo(34,"cat4"));
      caffeineCache.put("objList",objList);
      Object objListCache = caffeineCache.getIfPresent("objList");
      List<String> objList2 = (List<String>)objListCache;
    
    ####(7)存入Map<String,List<UserInfo>>
      Map<String,List<UserInfo>> map = new HashMap<>();
      List<UserInfo> oneList = new ArrayList<>();
      oneList.add(new UserInfo(55,"bird"));
      map.put("11",oneList);
    
      List<UserInfo> twoList = new ArrayList<>();
      twoList.add(new UserInfo(55,"bird"));
      twoList.add(new UserInfo(56,"tomcat"));
      map.put("12",twoList);
    
      caffeineCache.put("map",map);
      Object mapCache = caffeineCache.getIfPresent("map");
      Map<String,List<UserInfo>> map2 = (Map<String,List<UserInfo>>)mapCache;
    

    相关代码

    import lombok.Data;
    import lombok.ToString;
    
    @Data
    @ToString
    public class UserInfo {
    
        public UserInfo(){}
    
        public UserInfo(int id ,String name){
            this.id = id;
            this.name = name;
        }
    
        private Integer id;
        private String name;
        private String sex;
        private Integer age;
    }
    
    import com.github.benmanes.caffeine.cache.Cache;
    import com.github.benmanes.caffeine.cache.Caffeine;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    /**
     * Caffeine是使用Java8对Guava缓存的重写版本
     *
     * 在Spring Boot 2.0中将取代Guava。如果出现Caffeine,CaffeineCacheManager将会自动配置。
     *
     * DB + Redis + LocalCache = 高效存储,高效访问
     *
     *
     * 什么时候用?
     * 愿意消耗一些内存空间来提升速度
     * 预料到某些键会被多次查询
     * 缓存中存放的数据总量不会超出内存容量
     *
     *
     * 可以做什么?
     * 设置缓存容量
     * 设置超时时间
     * 提供移除监听器
     * 提供缓存加载器
     * 构建缓存
     *
     *
     * spring2.x只需要引入
     * <dependency>
     *      <groupId>com.github.ben-manes.caffeine</groupId>
     *      <artifactId>caffeine</artifactId>
     * </dependency>
     *
     *
     * initialCapacity=[integer]: 初始的缓存空间大小
     * maximumSize=[long]: 缓存的最大条数
     * maximumWeight=[long]: 缓存的最大权重
     * expireAfterAccess=[duration]: 最后一次写入或访问后经过固定时间过期
     * expireAfterWrite=[duration]: 最后一次写入后经过固定时间过期
     * refreshAfterWrite=[duration]: 创建缓存或者最近一次更新缓存后经过固定的时间间隔,刷新缓存
     * weakKeys: 打开key的弱引用
     * weakValues:打开value的弱引用
     * softValues:打开value的软引用
     * recordStats:开发统计功能
     * 注意:
     * expireAfterWrite和expireAfterAccess同事存在时,以expireAfterWrite为准。
     * maximumSize和maximumWeight不可以同时使用
     * weakValues和softValues不可以同时使用
     *
     */
    @Configuration
    public class CacheConfig {
    
        @Bean
        public Cache<String, Object> caffeineCacheObject() {
            return Caffeine.newBuilder()
                    // 设置最后一次写入或访问后经过固定时间过期
                    .expireAfterWrite(60, TimeUnit.SECONDS)
                    // 初始的缓存空间大小
                    .initialCapacity(100)
                    // 缓存的最大条数
                    .maximumSize(1000)
                    .build();
        }
    
    
    }
    
    package com.example.alldemo.me.util.cache.guava;
    
    import com.github.benmanes.caffeine.cache.Cache;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    @Slf4j
    @RestController
    @RequestMapping("/cache")
    public class UserInfoController {
    
        @Autowired
        Cache<String, Object> caffeineCache;
    
    
    
        public Object createInfo(String key){
            return "大老虎一只";
        }
    
        public void test() {
            log.info("enter test");
    
            Object obj = caffeineCache.getIfPresent("abc");
            log.info("abc is [" + obj + "].");
    
    
            Object o = caffeineCache.get("abc",k -> createInfo("abc"));
    
    
            caffeineCache.put("abc","def");
            obj = caffeineCache.getIfPresent("abc");
            if(obj != null){
                log.info("abc is [" + obj.toString() + "].");
            }
    
    
    
    
            //测试Object
            caffeineCache.put("obj",new UserInfo(3,"cat"));
            Object obj2 = caffeineCache.getIfPresent("obj");
            UserInfo ui2 = (UserInfo)obj2;
    
    
            //测试list<String>
            List<String> strList = new ArrayList<>();
            strList.add("a");
            strList.add("b");
            strList.add("c");
            strList.add("d");
            caffeineCache.put("strList",strList);
            Object strListCache = caffeineCache.getIfPresent("strList");
            List<String> strList2 = (List<String>)strListCache;
    
            //测试list
            List<UserInfo> objList = new ArrayList<>();
            objList.add(new UserInfo(3,"cat"));
            objList.add(new UserInfo(34,"cat4"));
            caffeineCache.put("objList",objList);
            Object objListCache = caffeineCache.getIfPresent("objList");
            List<String> objList2 = (List<String>)objListCache;
    
    
    
    
    
            //测试map
            Map<String,List<UserInfo>> map = new HashMap<>();
    
            List<UserInfo> oneList = new ArrayList<>();
            oneList.add(new UserInfo(55,"bird"));
            map.put("11",oneList);
    
            List<UserInfo> twoList = new ArrayList<>();
            twoList.add(new UserInfo(55,"bird"));
            twoList.add(new UserInfo(56,"tomcat"));
            map.put("12",twoList);
    
    
            caffeineCache.put("map",map);
            Object mapCache = caffeineCache.getIfPresent("map");
            Map<String,List<UserInfo>> map2 = (Map<String,List<UserInfo>>)mapCache;
    
    
    
    
            log.info("exit test");
        }
    
    }
    
  • 相关阅读:
    [搬运工系列]-JMeter(十三)压力测试--数据库(mysql)压力测试
    [搬运工系列]-JMeter(十二)处理Cookie与Session
    [搬运工系列]-JMeter(十一)问题与方案--内存溢出解决方法
    [搬运工系列]-JMeter(十) 命令行(非GUI)模式
    [搬运工系列]-JMeter (九)分布式测试
    [搬运工系列]-JMeter(八)HTTP属性管理器HTTP Cookie Manager、HTTP Request Defaults
    Python-Selenium 之控制浏览器的操作,WebDriver常用方法
    Selenium常见的无法定位到元素的原因
    接口测试实战
    jmeter做websocket协议的接口测试
  • 原文地址:https://www.cnblogs.com/jis121/p/15656757.html
Copyright © 2011-2022 走看看