ThingBoard源码解析-缓存
创始人
2024-02-12 10:11:38

配置

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 specs;// 构造CacheManager对象,被其管理的缓存可以在Cacheable等注解中使用@Beanpublic CacheManager cacheManager() {log.trace("Initializing cache: {} specs {}", Arrays.toString(RemovalCause.values()), specs);SimpleCacheManager manager = new SimpleCacheManager();if (specs != null) {// 加载配置文件中定义的具体缓存配置List 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 manuallymanager.initializeCaches();// 支持事务return new TransactionAwareCacheManagerProxy(manager);}// 构造一个缓存对象private CaffeineCache buildCache(String name, CacheSpecs cacheSpec) {final Caffeine caffeineBuilder= Caffeine.newBuilder()// 使用基于权重的回收策略:设置最大权重,当累计权重超过该值时,会触发驱逐// 相比基于容量(key的数量)的回收策略,权重能考虑值的大小,// 尤其是集合类型的值,可以更精确的控制缓存的大小.maximumWeight(cacheSpec.getMaxSize()) // 设置值的权重计算方法.weigher(collectionSafeWeigher()) // 设置基于时间的回收策略:在写入之后指定时间时删除.expireAfterWrite(cacheSpec.getTimeToLiveInMinutes(), TimeUnit.MINUTES).ticker(ticker());return new CaffeineCache(name, caffeineBuilder.build());}@Beanpublic Ticker ticker() {return Ticker.systemTicker();}// 计算值的权重,如果值的类型是集合,则权重是集合的大小private Weigher collectionSafeWeigher() {return (Weigher) (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 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);//打印缓存个数,结果为1System.out.println(cache.estimatedSize());// 插入权重为2的键值对,累计权重为21,会触发空间回收,基于TinyLRU算法驱逐key=0的键值对cache.put(1, 2);// 继续插入,累计权重为4,不会触发空间回收cache.put(2, 2);//稍微休眠一秒Thread.sleep(1000);//打印缓存个数,结果为2System.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 redisTemplate() {RedisTemplate template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory());return template;
}

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

使用

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

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...