• 九、Spring Boot 缓存(3)


    本章概要

    • Redis 集群缓存

    9.3 Redis 集群缓存

    不同于 Redis 单机缓存,Redis 集群缓存的配置要复杂一点,主要体现在配置上,缓存的使用还是和 Ehcache 2.x 缓存、Redis单机缓存一样。搭建 Redis 集群缓存主要分为三个步骤:①搭建 Redis 集群;②配置缓存;③使用缓存。

    9.3.1 搭建 Redis 集群

    Redis 集群的搭建已在 6.1.4 小节说过了,参考本专栏下的《六、Spring Boot 整合 NoSQL(2)》,先将集群搭建成功,并且能够在 Spring Boot 中通过 RedisTemplate 访问成功。

    9.3.2 配置缓存

    当 Redis 集群搭建成功,并且能够从 Spring Boot 项目中访问 Redis 集群后,只需要进行简单的 Redis 缓存配置即可

    @Configuration
    public class RedisCacheConfig {
        @Autowired
        RedisConnectionFactory conFactory;
    
        @Bean
        RedisCacheManager redisCacheManager() {
            Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
            RedisCacheConfiguration redisCacheConfig =
                    RedisCacheConfiguration.defaultCacheConfig()
                            .prefixKeysWith("sang:")
                            .disableCachingNullValues()
                            .entryTtl(Duration.ofMinutes(30));
            configMap.put("sang", redisCacheConfig);
            RedisCacheWriter cacheWriter =
                    RedisCacheWriter.nonLockingRedisCacheWriter(conFactory);
            RedisCacheManager redisCacheManager =
                    new RedisCacheManager(
                            cacheWriter,
                            RedisCacheConfiguration.defaultCacheConfig(),
                            configMap);
            return redisCacheManager;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    代码解释:

    • 在配置 Redis 集群时,已经向 Spring 容器中注册了一个 JedisConnectionFactory 的实例,这里将其注入到 RedisCacheConfi 配置文件中备用(RedisConnectionFactory 是 JedisConnectionFactory 的父类)
    • 在 RedisCacheConfig 中提供 RedisCacheManager 实例,该实例的构建需要三个参数,第一个参数是一个 cacheWriter,直接通过 nonLockingRedisCacheWriter 方法构造出来即可;第二个参数是默认的缓存配置;第三个参数是提前定义好的缓存配置
    • RedisCacheManager 构造方法中第三个参数是一个提前定义好的缓存参数,他是一个 Map 类型的参数,该 Map 中的 key 就是指缓存名字,value 就是该名称的缓存所对应的缓存配置,例如key 的前缀、缓存过期时间等,若缓存注册中使用的缓存名称不存在于 Map 中,则使用 RedisCacheManager 构造方法中第二个参数所定义的缓存策略进行数据缓存。(例如:@Cacheable(value=“c1”) @Cacheable(value=“c2”)),c1存在于 configMap 集合中,因此使用的缓存策略是默认的缓存策略
    • 此处默认缓存策略通过调用 RedisCacheManager 中的 defaultCacheConfig 方法获取,该方法的源码如下,由这段源码可以看到,默认的缓存过期时间为 0 ,即永不过期;第二个参数 true 表示允许存储 null ,第三个 true 表示开启 key 的前缀,第四个参数表示 key 的默认前缀是 “缓存名::”,接下来两个参数表示 key 和 value 的序列化方式,最后一个参数则是一个类型转换器
    public static RedisCacheConfiguration defaultCacheConfig() {
    
        DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
    
        registerDefaultConverters(conversionService);
    
        return new RedisCacheConfiguration(Duration.ZERO, true, true, CacheKeyPrefix.simple(),
                                           SerializationPair.fromSerializer(new StringRedisSerializer()),
                                           SerializationPair.fromSerializer(new JdkSerializationRedisSerializer()), conversionService);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • .prefixKeysWith(“sang:”) 设置了 key 的前缀为“sang:”,.disableCachingNullValues() 禁止缓存一个 null,.entryTtl(Duration.ofMinutes(30) 设置过期时间为 30 分钟

    9.3.3 使用缓存

    缓存配置完成后,首先在项目启动类中通过 @EnableCaching 注解开启缓存

    @SpringBootApplication
    @EnableCaching
    public class RedisclustercacheApplication {
        public static void main(String[] args) {
            SpringApplication.run(RedisclustercacheApplication.class, args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    然后创建一个 BookDao 使用缓存

    @Repository
    public class BookDao {
        @Cacheable(value = "c1")
        public String getBookById(Integer id) {
            System.out.println("getBookById");
            return "这本书是三国演义";
        }
        @CachePut(value = "c1")
        public String updateBookById(Integer id) {
            return "这是全新的三国演义";
        }
        @CacheEvict(value = "c1")
        public void deleteById(Integer id) {
            System.out.println("deleteById");
        }
        @Cacheable(value = "c2")
        public String getBookById2(Integer id) {
            System.out.println("getBookById2");
            return "这本书是红楼梦";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    最后创建单元测试

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class RedisclustercacheApplicationTests {
        @Autowired
        BookDao bookDao;
        @Test
        public void contextLoads() {
            bookDao.getBookById(100);
            String book = bookDao.getBookById(100);
            System.out.println(book);
            bookDao.updateBookById(100);
            String book2 = bookDao.getBookById(100);
            System.out.println(book2);
            bookDao.deleteById(100);
            bookDao.getBookById(100);
            bookDao.getBookById2(99);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    运行结果如下

    getBookById
    这本书是三国演义
    这是全新的三国演义
    deleteById
    getBookById
    getBookById2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    由单元测试可以看到,一开始做了两次查询,但是查询方法只调用了一次,因为第二次使用了缓存;接下来执行了更新,当更新成功后再去查询,此时缓存也已更新成功;接下来执行了删除,删除成功后再去执行查询,查询方法又被调用,说明缓存也被删除了;最后查询了一个id为99的记录,这次使用的是指定的缓存配置。在 Redis 服务器上也可以看到缓存结果,如图:
    在这里插入图片描述

    id 为 99 的记录使用的缓存名为 c2 ,因此key前缀是 sang: ,过期时间为 1670 ;而 id 为 100 的记录使用的缓存名称为 c1 ,因此使用了默认的缓存配置,默认的前缀为“缓存名::”,即 “c1::”,默认的过期时间是永不过期的。

  • 相关阅读:
    【毕业设计】基于YOLO实现的口罩佩戴检测 - python opemcv 深度学习
    Tomcat部署及优化
    【记录】go语言编程规范梳理总结
    巧用Prometheus来扩展kubernetes调度器
    JVM----GC(垃圾回收)详解
    DeFi明斯基时刻:压力测试与启示
    蓝牙方案|伦茨科技最新ESL蓝牙电子价签方案
    USB学习(1):USB基础之接口类型、协议标准、引脚分布、架构、时序和数据格式
    【笔试题】【day16】
    PTA 网红店打卡攻略(带权建图搜索)
  • 原文地址:https://blog.csdn.net/GXL_1012/article/details/126259864