<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-cacheartifactId>
dependency>
<dependency>
<groupId>org.redissongroupId>
<artifactId>redissonartifactId>
<version>3.17.5version>
dependency>
无需引入redis其他相关依赖,因为Redisson采用了基于NIO的Netty框架,不仅能作为Redis底层驱动客户端,具备提供对Redis各种组态形式的连接功能,对Redis命令能以同步发送、异步形式发送、异步流形式发送或管道形式发送的功能,LUA脚本执行处理,以及处理返回结果的功能,还在此基础上融入了更高级的应用方案

package com.vector.mallproduct.config;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.config.Config;
import org.redisson.spring.cache.CacheConfig;
import org.redisson.spring.cache.RedissonSpringCacheManager;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* @author WangJiaHui
* @description: test
* @ClassName RedissonConfig
* @date 2022/3/5 10:11
*/
@EnableCaching
@Configuration
public class RedissonConfig {
@Bean(destroyMethod = "shutdown")
RedissonClient redisson() throws IOException {
Config config = new Config();
//config.useClusterServers().addNodeAddress("127.0.0.1:6379");
config.useSingleServer().setAddress("redis://192.168.56.101:6379").setPassword("123456");
return Redisson.create(config);
}
// springCache整合Redisson
@Bean
CacheManager cacheManager(RedissonClient redissonClient) {
Map<String, CacheConfig> config = new HashMap<>();
// 创建一个名称为"category"的缓存,过期时间ttl为24分钟,同时最长空闲时maxIdleTime为12分钟。
// 他为springCache注解中相同value="category"或cacheNames="category"的方法配置
config.put("category",new CacheConfig(24*60*1000, 12*60*1000));
RedissonSpringCacheManager cacheManager = new RedissonSpringCacheManager(redissonClient, config);
// 默认jack序列化
cacheManager.setCodec(new JsonJacksonCodec());
cacheManager.setAllowNullValues(true); // 允许缓存空值
// cacheManager.setCacheNames(); // 定义“固定”缓存名称 (Collection names)
// cacheManager.setTransactionAware(true); 定义缓存是否能够识别 Spring 管理的事务。
// cacheManager.setConfig(); 设置按缓存名称映射的缓存配置 (Map config)
return cacheManager;
}
}
* 常规数据(读多写少,即时性,一致性要求不高的数据)﹔完全可以使用spring-Cache
* 特殊薮据:特殊设计
* * 自定义:
* 1)指定缓存使用的key key属性接受一个SpEl
* 2)指定缓存的存活时间
* 3)保存为json格式
* Spring Cache是Spring AOP的最佳实践
* @Cacheable
* @Cacheble注解表示这个方法有了缓存的功能,方法的返回值会被缓存下来,下一次调用该方法前,会去检查是否缓存中已经有值,如 果有就直接返回,不调用方法。如果没有,就调用方法,然后把结果缓存起来。这个注解一般用在查询方法上。
* @CachePut
* 加了@CachePut注解的方法,会把方法的返回值put到缓存里面缓存起来,供其它地方使用。它通常用在新增方法上。
* @CacheEvict
*使用了CacheEvict注解的方法,会清空指定缓存。一般用在更新或者删除的方法上。
*@Caching
*Java注解的机制决定了,一个方法上只能有一个相同的注解生效。那有时候可能一个方法会操作多个缓存(这个在删除缓存操作中比较常见,在 *添加操作中不太常见)。
* springcache的不足
* 读模式
* 缓存穿透: 查询null数据. 解决:缓存空数据
* 缓存击穿: 大量并发同时查询一个过期的数据.解决加锁:降低并发 sync = true 如果有多个线程访问相同key,就加锁
* 缓存雪崩: 大量的key同时过期. 加随机时间
* 写模式:
* 读写加锁
* 引入canal.感知mysql的更新去更新数据库
* 读多写读,直接去数据库查询
*
* 常规数据(读多写少,即时性,一致性要求不高的数据)﹔完全可以使用spring-Cache
* 特殊薮据:特殊设计
*/
// 代表当前方法的结果需要缓存,如果缓存中有,方法不用调用。如果缓存中没有,会调用方法,最后将方法的结果放入缓存!
以关键cache使用为例.
@Cacheable(value = {"category"}, key = "#root.method.name",sync = true)
@Override
public List<CategoryEntity> getLevel1Categorys() {
return baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", 0));
}
产生的结果





其他功能均实现,
但出现 1.左侧只有一条category是我们需要缓存的数据,但还多出了4个文件.
2.ttl值是-1!我们设定的是24分钟
3.虽然ttl是-1但是依然会在规定的24分钟后删除
解释:
1.多出来的是: redisson底层会调用的配置文件,用来服务我们的k-v属性
2.ttl为-1.他是靠redisson底层的定时任务删除的.和redis显示的ttl无关.如下图

3.关于这种设计如何知晓我们是否为key设置了过期属性.在redis层我们无法知晓.但可通过redisson的配置类知道.不设置ttl必为永久.否则以设定时间为准
4.博主水平不够,无法知晓redisson底层调用删除逻辑.仅知道有看门狗定时任务,30s执行一次.一次30s
redis并没有实现对hash元素过期时间的设置。Redisson通过在初始化RedissonMapCache时,设置了一个EvictionScheduler,这个类通过netty的EventloopGroup线程池周期地向以redisson_map_cache_expired前缀名的频道发布消息。RedissonMapCache会订阅这个频道来处理消息。它一次可移除 100 条过期项。
任务的调度时间会根据上次任务中删除的过期项数量自动调整,时间在 1 秒到 2 个小时内。因此若清理任务每次删除了100项数据,它将每秒钟执行一次(最小的执行延迟)。但如果当前过期项数量比前一次少,则执行延迟将扩大为 1.5 倍。
作者:飞翔的意大利炮
链接:https://www.jianshu.com/p/e9b26c743cae
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。