• 分享一个本地缓存解决方案 Caffeine Cache


    关于Caffeine Cache

    Google Guava Cache是一种非常优秀本地缓存解决方案,提供了基于容量,时间和引用的缓存回收方式。基于容量的方式内部实现采用LRU算法,基于引用回收很好的利用了Java虚拟机的垃圾回收机制。其中的缓存构造器CacheBuilder采用构建者模式提供了设置好各种参数的缓存对象,缓存核心类LocalCache里面的内部类Segment与jdk1.7及以前的ConcurrentHashMap非常相似,都继承于ReetrantLock,还有六个队列,以实现丰富的本地缓存方案。 ​ 通俗的讲,Guva是google开源的一个公共java库,类似于Apache Commons,它提供了集合,反射,缓存,科学计算,xml,io等一些工具类库。cache只是其中的一个模块。使用Guva cache能够方便快速的构建本地缓存。

    Caffeine是使用Java8对Guava缓存的重写版本,在Spring Boot 2.0中将取代Guava。如果出现Caffeine,CaffeineCacheManager将会自动配置。

    1.1.1 为什么要用本地缓存

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

    -- 下面来看看,各种本地缓存框架的读写对比

     引入依赖:

      <!-- springboot 缓存-->
            <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>
            </dependency>

    在启动类上加入注解:

    Caffeine在springboot中集成非常简单,可以通过配置文件来设置

    spring:
      cache:
        cache-names: outLimit,notOutLimit
        caffeine:
          spec: initialCapacity=50,maximumSize=500,expireAfterWrite=5s,refreshAfterWrite=7s
        type: caffeine
    

      

    或者使用注解的形式注入 

    package cn.aiaudit.model.config;
    
    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.concurrent.TimeUnit;
    
    /**
     *配置caffeine作为模型的本地缓存
     */
    @Configuration
    public class CacheConfig {
    
        @Bean
        public Cache caffeineCache() {
            return Caffeine.newBuilder()
                    // 设置最后一次写入或访问后经过固定时间过期
                    .expireAfterWrite(60, TimeUnit.SECONDS)
                    // 初始的缓存空间大小
                    .initialCapacity(100)
                    // 缓存的最大条数
                    .maximumSize(500)
                    .build();
        }
    
    }
    

     下面介绍获取和存储缓存数据,可以基于注解的形式,也可以使用手动的形式

    1.

      @Autowired
        Cache<String, Object> caffeineCache;
    
    caffeineCache.put(String.valueOf(po.getId()), vo);
    
    
    
    // 先从缓存读取
            caffeineCache.getIfPresent(id);
            SqlInsertIntoProgressVO vo = (SqlInsertIntoProgressVO)caffeineCache.asMap().get(id);
    

    2.

    @Slf4j
    @Service
    @CacheConfig(cacheNames = "caffeineCacheManager")
    public class UserInfoServiceImpl implements UserInfoService {
    
        /**
         * 模拟数据库存储数据
         */
        private HashMap<Integer, UserInfo> userInfoMap = new HashMap<>();
    
        @Override
        @CachePut(key = "#userInfo.id")
        public void addUserInfo(UserInfo userInfo) {
            log.info("create");
            userInfoMap.put(userInfo.getId(), userInfo);
        }
    
        @Override
        @Cacheable(key = "#id")
        public UserInfo getByName(Integer id) {
            log.info("get");
            return userInfoMap.get(id);
        }
    
        @Override
        @CachePut(key = "#userInfo.id")
        public UserInfo updateUserInfo(UserInfo userInfo) {
            log.info("update");
            if (!userInfoMap.containsKey(userInfo.getId())) {
                return null;
            }
            // 取旧的值
            UserInfo oldUserInfo = userInfoMap.get(userInfo.getId());
            // 替换内容
            if (!StringUtils.isEmpty(oldUserInfo.getAge())) {
                oldUserInfo.setAge(userInfo.getAge());
            }
            if (!StringUtils.isEmpty(oldUserInfo.getName())) {
                oldUserInfo.setName(userInfo.getName());
            }
            if (!StringUtils.isEmpty(oldUserInfo.getSex())) {
                oldUserInfo.setSex(userInfo.getSex());
            }
            // 将新的对象存储,更新旧对象信息
            userInfoMap.put(oldUserInfo.getId(), oldUserInfo);
            // 返回新对象信息
            return oldUserInfo;
        }
    
        @Override
        @CacheEvict(key = "#id")
        public void deleteById(Integer id) {
            log.info("delete");
            userInfoMap.remove(id);
        }
    

      -- 以上

      

      

    岁月无声无息的溜走,除了带走一个无聊者的时光,还会沉淀一个努力者的人生。
  • 相关阅读:
    特征选择方法之信息增益
    6 个优秀的开源 OCR 光学字符识别工具
    Python中type与Object的区别
    Python type类具体的三大分类:metaclasses,classes,instance
    如何去除List中的重复值?
    type,isinstance判断一个变量的数据类型
    Python图形界面开发包 PyGTK
    python使用easygui写图形界面程序
    opencv-python 学习笔记2:实现目光跟随(又叫人脸跟随)
    Tomcat全攻略
  • 原文地址:https://www.cnblogs.com/dayandday/p/14607323.html
Copyright © 2020-2023  润新知