Redis的认识和使用

文章介绍了Redis作为内存数据结构存储系统,用于提高查询性能和应对高并发场景。提到了通过SpringBoot配置Redis依赖,设置序列化器,以及使用RedisTemplate操作数据库。文章还讨论了两种缓存开发方式——注解和编程实现,并给出了具体的代码示例,强调了缓存策略在防止穿透和雪崩问题上的应用。
摘要由CSDN通过智能技术生成

Redis

Redis (全称:Remote Dictionary Server 远程字典服务)是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。它是一个运行在内存中的数据结构存储系统,它可以用作数据库、缓存消息中间件

针对类目信息发现一般很少修改,但是经常需要执行查询,例如添加商品等操作。比较适合使用redis缓存数据,通过浪费内存以减少数据库的查询此时,从而提供执行性能,应对更高的并发性需求。

redis缓存开发一般有2种方式,使用注解【推荐】和使用自定义编程实现。缓存可以添加在不同的层面上,一般针对controller缓存,多使用本地缓存Ehcache;如果针对业务层缓存,一般使用支持分布式的Redis;也可以在持久层添加缓存,例如开启的MyBatis的缓存。

Redis使用流程

1.添加依赖

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-pool2</artifactId>
    </dependency>

2.添加Redis序列化器和反序列化器的配置

@SpringBootConfiguration
    public class MyRedisConfig {
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory
                                                                   factory) {
            RedisTemplate<String, Object> template = new RedisTemplate<>(); //创建模板
            类对象
            RedisSerializer<String> redisSerializer = new StringRedisSerializer();//
            创建String序列化类
            Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new
                    Jackson2JsonRedisSerializer(Object.class); //指定使用jackson工具负责具体的序列化操作
            ObjectMapper om = new ObjectMapper(); //创建jackson的核心api的 ObjectMapper
,将bean,list,map,数组等等转成字符串
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 使用objectmapper设置bean的属性,修饰符
            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); //设置默认
            类型
            om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); //设置将本地时
            间转成字符串
            jackson2JsonRedisSerializer.setObjectMapper(om); //将核心api objectmapper
            设置给jackson
            template.setConnectionFactory(factory); // 通过工厂得到连接对象
            template.setKeySerializer(redisSerializer); //设置key序列化方式: 转成字符串
            template.setValueSerializer(jackson2JsonRedisSerializer); // 设置value序列: 字符串
            template.setHashValueSerializer(jackson2JsonRedisSerializer); // value
            hashmap序列化
            return template;
        }
    }

3.RedisTemplate调用API操作Redis数据库

通过spring框架提供的模板类RedisTemplate调用API操作Redis数据库。在使用redis缓存之前应该充分沟通,定义一个key的标准,或者查询公司旧有标准,注意不能随机起名

@Service
public class CatalogServiceImpl extends ServiceImpl<CatalogMapper, Catalog>
        implements CatalogService {
    @Autowired
    private RedisTemplate redisTemplate;
    private ThreadLocalRandom random = ThreadLocalRandom.current();
    @Override
    public List<Catalog> listByPage(PageBean pages) {
        List<Catalog> res = new ArrayList<>();
        9.5、使用postman测试,可以在控制台上查看是否有对应的SQL语句输出以判断缓存是否生效
                注解开发
        注解提供了更声明式和方便的方式,而编码方式允许更精细的控制和定制。
        if (pages == null || pages.getRowsPerPage() < 1) {
//查询所有,避免缓存穿透,索引允许存储数据为空集
            if (redisTemplate.hasKey("catalog::all")) {
//如果在具体开发种比较倾向于使用常量的方式
                Object obj = redisTemplate.opsForValue().get("catalog::all");
                if (obj != null && obj instanceof List)
                    res = (List<Catalog>) obj;
            } else {
                res = this.getBaseMapper().selectList(null);
//为了避免雪崩问题,所以生存周期引入随机数
                int kk = 100 + random.nextInt(100);
                redisTemplate.opsForValue().set("catalog::all", res,
                        Duration.ofSeconds(kk));
            }
        } else {
//分页查询。实际上具体应用中不一定针对分页数据进行缓存 catalog::page::size
            if (pages.getPageNum() < 1)
                pages.setPageNum(1);
            String key = "catalog::" + pages.getPageNum() + "::" +
                    pages.getRowsPerPage();
            if (this.redisTemplate.hasKey(key)) {
                Object obj = redisTemplate.opsForValue().get(key);
                if (obj != null && obj instanceof List)
                    res = (List<Catalog>) obj;
                if(this.redisTemplate.hasKey(key+"::page")){
                    obj = redisTemplate.opsForValue().get(key+"::page");
                    if (obj != null && obj instanceof PageBean) {
                        PageBean tmp = (PageBean) obj;
                        BeanUtils.copyProperties(tmp,pages);
                    }
                }
            }
            if (res == null || res.size() < 1) {
                Page<Catalog> pageInfo = new Page<>(pages.getPageNum(),
                        pages.getRowsPerPage());
                pageInfo = this.getBaseMapper().selectPage(pageInfo, null);
                res = pageInfo.getRecords();
                pages.setPageNum(pageInfo.getCurrent());
                pages.setRowsNum(pageInfo.getTotal());
                pages.setMaxPage(pageInfo.getPages());
                int kk = 100 + random.nextInt(100); //随机数时长用于避免雪崩
                redisTemplate.opsForValue().set(key, res,
                        Duration.ofSeconds(kk));
                redisTemplate.opsForValue().set(key+"::page", pages,
                        Duration.ofSeconds(kk));
            }
        }
        return res;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值