ThingBoard源码解析-缓存

news2024/9/23 19:22:43

配置

TB支持两种缓存:Caffeine和Redis,通过配置cache.type来指定使用哪种缓存。
在这里插入图片描述
位于 org.thingsboard.server.cache

Caffeine

配置类:CaffeineCacheConfiguration

@Configuration
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true)
@ConfigurationProperties(prefix = "caffeine")
@EnableCaching
@Data
@Slf4j
public class CaffeineCacheConfiguration {

    // 具体缓存的配置
    private Map<String, CacheSpecs> specs;

    // 构造CacheManager对象,被其管理的缓存可以在Cacheable等注解中使用
    @Bean
    public CacheManager cacheManager() {
        log.trace("Initializing cache: {} specs {}", Arrays.toString(RemovalCause.values()), specs);
        SimpleCacheManager manager = new SimpleCacheManager();
        if (specs != null) {
            // 加载配置文件中定义的具体缓存配置
            List<CaffeineCache> caches = specs.entrySet().stream()
                    .map(entry -> buildCache(entry.getKey(), entry.getValue())).collect(Collectors.toList());
            manager.setCaches(caches);
        }

        //SimpleCacheManager is not a bean (will be wrapped), so call initializeCaches manually
        manager.initializeCaches();

        // 支持事务
        return new TransactionAwareCacheManagerProxy(manager);
    }

    // 构造一个缓存对象
    private CaffeineCache buildCache(String name, CacheSpecs cacheSpec) {
        final Caffeine<Object, Object> caffeineBuilder
                = Caffeine.newBuilder()
                 // 使用基于权重的回收策略:设置最大权重,当累计权重超过该值时,会触发驱逐
                 // 相比基于容量(key的数量)的回收策略,权重能考虑值的大小,
                 // 尤其是集合类型的值,可以更精确的控制缓存的大小
                .maximumWeight(cacheSpec.getMaxSize()) 
                // 设置值的权重计算方法
                .weigher(collectionSafeWeigher()) 
                // 设置基于时间的回收策略:在写入之后指定时间时删除
                .expireAfterWrite(cacheSpec.getTimeToLiveInMinutes(), TimeUnit.MINUTES)
                .ticker(ticker());
        return new CaffeineCache(name, caffeineBuilder.build());
    }
    
    @Bean
    public Ticker ticker() {
        return Ticker.systemTicker();
    }
    
    // 计算值的权重,如果值的类型是集合,则权重是集合的大小
    private Weigher<? super Object, ? super Object> collectionSafeWeigher() {
        return (Weigher<Object, Object>) (key, value) -> {
            if (value instanceof Collection) {
                return ((Collection) value).size();
            }
            return 1;
        };
    }    
}

配置类上的 @ConditionalOnProperty(prefix = “cache”, value = “type”, havingValue = “caffeine”, matchIfMissing = true)说明当配置使用caffeine缓存时,该配置类才生效.

回收策略

public static void main(String[] args) throws InterruptedException {
    Cache<Integer, Integer> cache = Caffeine.newBuilder()
            //设置最大权重为20
            .maximumWeight(20)
            //设置值的权重等于值
            .weigher((key, value) -> (int) value)
            .removalListener((Integer key, Object value, RemovalCause cause) ->
                    System.out.printf("Key %s was removed because (%s)%n", key, cause))
            .build();
    // 插入权重为19的键值对
    cache.put(0, 19);
    //打印缓存个数,结果为1
    System.out.println(cache.estimatedSize());
    // 插入权重为2的键值对,累计权重为21,会触发空间回收,基于TinyLRU算法驱逐key=0的键值对
    cache.put(1, 2);
    // 继续插入,累计权重为4,不会触发空间回收
    cache.put(2, 2);
    //稍微休眠一秒
    Thread.sleep(1000);
    //打印缓存个数,结果为2
    System.out.println(cache.estimatedSize());
}

// 控制台打印:
//1
//Key 0 was removed because (SIZE) key 0 被驱逐因为缓存大小限制
//2

支持事务

假设方法updateUser被@CachePut修饰,则更新User后更新缓存
在一个事务方法中先调用updateUser方法,然后调用addUpdateLog方法;
在实际执行时,执行addUpdateLog方法发生异常,导致事务回滚;
如果缓存不支持事务,则会导致缓存脏数据的问题,流程如下:
暂时无法在文档外展示此内容

Redis

配置类:TBRedisCacheConfiguration

// 连接池
@Bean
public RedisConnectionFactory redisConnectionFactory() {
    return loadFactory();
}

// 支持Redis多种部署模式,因此由子类定义
protected abstract JedisConnectionFactory loadFactory();

/**
 * 传入连接工厂Bean定义RedisCacheManager,支持事务
 * Transaction aware RedisCacheManager.
 * Enable RedisCaches to synchronize cache put/evict operations with ongoing Spring-managed transactions.
 */
@Bean
public CacheManager cacheManager(RedisConnectionFactory cf) {
    DefaultFormattingConversionService redisConversionService = new DefaultFormattingConversionService();
    RedisCacheConfiguration.registerDefaultConverters(redisConversionService);
    registerDefaultConverters(redisConversionService);
    RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig().withConversionService(redisConversionService);
    return RedisCacheManager.builder(cf)
            .cacheDefaults(configuration)
            .transactionAware()
            .build();
}

@Bean
public RedisTemplate<String, Object> redisTemplate() {
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(redisConnectionFactory());
    return template;
}

支持Redis的两种模式:Standalone和Cluster;因此构造连接方法在两个子类中定义:
在这里插入图片描述

使用

因为使用了CacheManager因此可以直接使用注解来使用缓存
cacheNmaes指的是使用哪个缓存,当使用Caffeine缓存时会根据配置文件加载多个缓存Bean:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/32512.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HTML CSS 个人网页设计 WEB前端大作业代码

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

【计算机毕业设计】7.线上花店系统maven源码

一、系统截图&#xff08;需要演示视频可以私聊&#xff09; 摘 要 随着互联网突飞猛进的发展及其对人们的生活产生至关重要的影响&#xff0c;线上购花&#xff0c;送货到家的购物方式受到了越来越多顾客的接受与喜爱。线上花卉小铺的设计与实现不仅可以带来更广泛的选择与实…

餐饮业如何现业绩突破性增长?

疫情反复无常&#xff0c;餐饮人每天都面临着极大的挑战&#xff1a;无法预测的关店通知、突如其来的禁止堂食命令......餐饮店客流减少&#xff0c;业绩下滑成为不可避免的趋势。 在这种情形下&#xff0c;不少餐饮老板拒绝“躺平”&#xff0c;上演“花式自救”&#xff1a;…

cpu设计和实现(数据预取)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面说过了一条指令经过cpu处理的时候需要经历几个阶段。通过实验&#xff0c;我们发现&#xff0c;哪怕是再简单的ori指令也要经历取指、译码、执…

MyBatis是什么?使用方式?

目录 前言&#xff1a; 一、概念讲述 1.什么是MyBatis&#xff1f; 2.官网网址 二、使用方式 1.pom.xml里面添加依赖包 2.新建统一配置文件&#xff08;俗称数据库连接文件&#xff09; 3.新建立映射文件 &#xff08;俗称数据库表对应xml&#xff09; 4.建立数据库表…

ArcMap中之提取影像数据边界

1、前言 手里有一些经过裁剪的不规则多边形影像数据&#xff08;如图例所示&#xff09;&#xff0c;希望能批量获取该类影像的边界信息&#xff0c;即影像对应的面信息&#xff0c;边界线信息。这里我们提供一种利用镶嵌数据集Footprint图层的方法来获取&#xff0c;面&#…

基于Python机器学习及深度学习在空间模拟与时间预测应用

了解机器学习的发展历史、计算原理、基本定义&#xff0c;熟悉机器学习方法的分类&#xff0c;常用机器学习方法&#xff0c;以及模型的评估与选择&#xff1b;熟悉数据预处理的流程&#xff0c;掌握python程序包的使用&#xff1b;理解机器学习在生态水文中的应用&#xff0c;…

超实用的图片处理技巧,一分钟轻松完成图片编辑

图片想必大家都很熟悉&#xff0c;无论是我们平时在聊天的时候使用的表情包或者是在工作中插入的插图都属于图片&#xff0c;在使用图片的时候大家会遇到各种各样的问题&#xff0c;比如上传的图片格式不对、使用的图片尺寸太大等等&#xff0c;都会导致图片无法正常使用&#…

[附源码]java毕业设计医院就诊流程管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

c++旅行商问题 (暴力解)

目录一、旅行商问题简介旅行商问题问题概述问题由来二、枚举所有方案1、思路2、代码3、复杂度分析三、深度优先搜索1、思路2、代码3、复杂度分析一、旅行商问题简介 旅行商问题 TSP&#xff0c;即旅行商问题&#xff0c;又称TSP问题&#xff08;Traveling Salesman Problem&am…

白盒测试与黑盒测试

白盒测试技术 白盒测试技术也称结构性测试&#xff0c;是一种设计测试用例的方法&#xff0c;一般用于分析程序的内部结构&#xff0c;使用该方法测试程序时测试者可以看到被测试程序&#xff0c;并分析其内部结构。 按照被测试测试时是否需要执行测试程序可以分为静态和动态…

RK3399平台开发系列讲解(中断篇)中断控制器驱动初始化

🚀返回专栏总目录 文章目录 一、设备树源文件1.1、gic控制器节点1.2、timer节点二、中断控制器匹配表三、中断控制器初始化3.1、函数of_irq_init3.2、函数gicv3_of_init3.3、函数gic_init_bases沉淀、分享、成长,让自己和他人都能有所收获!😄 一、设备树源文件 ARM64架构…

web前端网页制作课作业:甜甜圈蛋糕店(HTML+CSS+JavaScript)

&#x1f380; 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

用DIV+CSS技术设计的水果介绍网站(web前端网页制作课作业)

&#x1f380; 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

NodeJs实战-Express构建照片存储网站(2)-上传、展示文件

Express构建照片存储网站2-上传、展示文件静态资源显示图片photo页面展示文件夹下的图片上传文件增加上传页面的路由增加提交接口的路由网站效果图项目地址上一节使用的静态数据存储的图片的数据&#xff0c;本节增加如下功能 1–上传文件 2–展示文件 静态资源显示图片 app.…

企业微信自建应用手动授权,获取用户详细信息

开始开发 最后更新&#xff1a;2022/10/11 企业微信提供了OAuth的授权登录方式&#xff0c;可以让从企业微信终端打开的网页获取成员的身份信息&#xff0c;从而免去登录的环节。 企业应用中的URL链接&#xff08;包括自定义菜单或者消息中的链接&#xff09;&#xff0c;均可…

宇视高空抛物相机配置指导

宇视高空抛物相机配置指导 登录摄像机网页界面&#xff0c;进入[配置>智能监控>智能功能]页面启用<高空抛物>功能&#xff0c;并进入高空抛物配置界面&#xff1b; 添加/删除检测规则&#xff0c;根据实际高空抛物场景和规则下发要求绘制检测区域&#xff1b; (…

必看!!!客户端requests与服务端request收发请求

当使用代码进行接口访问的时候&#xff0c;请求的发送与请求的接受使用的参数应该怎么如何传输能够请求到正确的响应呢? 一、使用GET请求发送&#xff0c;客户端与服务端的参数传输与接受。 1、服务端&#xff0c;首先使用web框架写一个简单的接口&#xff0c;接收两个参数&…

FineReport常用配置和方法

目录 1、隐藏参数面板的小箭头&#xff1a; 1、隐藏参数面板的小箭头&#xff1a; 查看小箭头的class&#xff0c;css设置如下属性&#xff1a; 隐藏按钮&#xff1a; // 旧版 $(.parameter-container-collapseimg-up).hide(); // 新版 $(.report-main-parameter-container-…

浙大MBA考研经验分享:名校梦不可负~

上大学的时候考研失败&#xff0c;对于没能进入浙大求学一直是我心里的遗憾&#xff01;但是毕业以来至今工作三年&#xff0c;职场上的经历让我意识到持续学习提升的重要性。一边工作一边备考&#xff0c;对于基础普通的我来说&#xff0c;一年备战能够以211分的成绩成功上岸浙…