使用redis对热点数据进行缓存

1. 为什么要对热点数据进行缓存?

本人做的是一个博客系统,使用redis对文章的信息进行缓存,比如说要去查询最热文章,首页的文章展示,对项目的查询接口的数据我们可以将其放入缓存中,这样子不仅可以做到查询速度快,当有大量的用户请求该接口时还能够减轻数据库的负担,提高博客浏览的速度。

2.准备工作

其实我现在设计到的是有两种方法对数据进行缓存到redis中,第一种就是使用自定义注解就是AOP思想逻辑去实现。那么本项目用的是第二种,就是之前我在瑞吉外卖学到的整合Sprting Cache框架。

3. Spring Cache简介

Spring Cache 是 Spring 提供的一整套的缓存解决方案。虽然它本身并没有提供缓存的实现,但是它提供了一整套的接口和代码规范、配置、注解等,这样它就可以整合各种缓存方案了,比如 Redis、Ehcache,我们也就不用关心操作缓存的细节。

Cache接口它包含了缓存的各种操作方式,同时还提供了各种xxxCache缓存的实现,比如 RedisCache 针对Redis,EhCacheCache 针对 EhCache,ConcurrentMapCache 针对 ConCurrentMap。

4.在本博客项目中的应用

(1)导入pom依赖

 <!--        cache-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

(2)application.properties配置文件,指定redis的缓存类型


#cache  配置文件指定缓存类型
spring.cache.type=redis

(3)在启动类中开启注解

package com.jia;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableCaching//开启缓存注解
public class BlogApiApplication {

    public static void main(String[] args) {
        SpringApplication.run(BlogApiApplication.class, args);
    }

}

(4)接下来需要去添加一个CacheConfig类,设置Redis的过期时间和序列化,这段代码是配置了三个不同的Redis缓存管理器,分别用于设置缓存的过期时间为1分钟、1小时和1天。


首先,在cacheManager1Minute、cacheManager1Hour和cacheManager1Day方法中,通过调用instanceConig 方法来创建一个RedisCacheConfiguration对象。instanceConig方法接收一个ttl参数,用于设置缓存的过期时间。


接下来,在instanceConig方法中,创建了一个Jackson2JsonRedisSerializer对象,并配置了用于序列化和反序列化的ObjectMapper对象。ObjectMapper用于将对象转换为JSON字符串,并能够处理Java 8的日期时间类型。Jackson2JsonRedisSerializer则用于将对象序列化为JSON字符串,并将其存储到Redis中。


最后,在RedisCacheConfiguration对象的构建过程中,设置了缓存的过期时间、禁止缓存null值、以及使用之前创建的Jackson2JsonRedisSerializer进行值的序列化。

package com.jia.config;/**
 * @author ChenJia
 * @create 2023-06-17 15:12
 */

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;

import java.time.Duration;

/**
 *@ClassName CacheConfig
 *@Description Cache注解类,配置了过期时间和序列化
 *@Author jia
 *@Date 2023/6/17 15:12
 *@Version 1.0
 **/

@Configuration
public class CacheConfig {
    @Bean
    public RedisCacheManager cacheManager1Minute(RedisConnectionFactory connectionFactory){
        RedisCacheConfiguration config = instanceConig(60L);
        return RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(config)
                .transactionAware()
                .build();
    }

    @Bean
    @Primary    // 默认的,没有指定采用默认的
    public RedisCacheManager cacheManager1Hour(RedisConnectionFactory connectionFactory){
        RedisCacheConfiguration config = instanceConig(3600L);
        return RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(config)
                .transactionAware()
                .build();
    }

    @Bean
    public RedisCacheManager cacheManager1Day(RedisConnectionFactory connectionFactory){
        RedisCacheConfiguration config = instanceConig(3600 * 24L);
        return RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(config)
                .transactionAware()
                .build();
    }

    private RedisCacheConfiguration instanceConig(long ttl) {

        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.registerModule(new JavaTimeModule());
        //去掉各种@JsonSerialize注解的解析
        objectMapper.configure(MapperFeature.USE_ANNOTATIONS,false);
        //只针对非空的值进行序列化
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        //将类型序列化到属性json字符串中
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);

        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        return RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(ttl))
                .disableCachingNullValues()     //禁止缓存null的值
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));
    }


}

(5)注解的使用,这里需要解释一下Cacheable注解:

标记在一个方法上,也可以标记在一个类上
缓存标注对象的返回结果,标注在方法上缓存该方法的返回值,标注在类上缓存该类所有方法的返回值
value缓存名称,可以有多个
key缓存的key规则,可以使用springEL表达式,默认是方法参数组合
condition缓存条件,使用springEL编写,返回true才缓存

    /**
     * 首页文章列表
     * @param pageParams
     * return 返回承担返回数据Result的类
     */
    @PostMapping
    //这里我们设置过期时间为1分钟,默认为一小时,统一缓存处理
    @Cacheable(value = {"listArticle"}, key = "#root.methodName",cacheManager = "cacheManager1Hour")
    @LogAnnotation(module = "文章",operator = "获取文章列表")
    public Result listArticle(@RequestBody PageParams pageParams){
//        int i =1/0;统一异常处理的测试
        //对于接受的参数问题,这里是RequestBody接收
        return articleService.listArticle(pageParams);
    }

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于 Redis 热点数据缓存,可以使用 Redis缓存功能来提高系统性能和响应速度。热点数据指的是频繁被访问的数据,通过将这些数据缓存在内存中,可以避免频繁地从数据库中读取,从而减少数据库的压力。 在 Redis 中,可以使用以下两种常见的方式来实现热点数据缓存: 1. 缓存数据存储在 Redis 的字符串类型中:将需要缓存数据序列化为字符串,并使用一个唯一的键来存储在 Redis 中。当需要访问该数据时,先从 Redis 中尝试获取,如果获取不到,则从数据库中读取,并将读取到的数据存储到 Redis 中以供下次使用。这样就可以实现数据的快速读取和缓存更新。 2. 缓存数据存储在 Redis 的哈希类型中:将需要缓存数据组织为一个哈希表,其中每个字段对应一个属性或字段,并使用一个唯一的键来存储在 Redis 中。当需要访问该数据时,同样先从 Redis 中尝试获取,如果获取不到,则从数据库中读取,并将读取到的数据以哈希表的形式存储到 Redis 中。这种方式可以更灵活地处理复杂的数据结构。 需要注意的是,为了保证缓存的一致性和有效性,需要在适当的时机进行缓存的更新和失效操作。例如,在数据更新之后,需要及时更新 Redis 中的缓存数据,以保证缓存数据库的一致性。另外,还可以设置合适的缓存过期时间,避免缓存数据过期但仍然被使用的情况发生。 总的来说,通过 Redis热点数据缓存可以提高系统的性能和响应速度,减少数据库的压力,但需要注意缓存的一致性和有效性的处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值