谷粒商城实战笔记-153-缓存-缓存使用-改造三级分类业务

文章目录

一,153-缓存-缓存使用-改造三级分类业务

这一节的主要内容是改造查询三级分类的接口,将Redis缓存加入进来。

在查询三级分类时,先查redis,如果redis中有数据,则使用redis的数据,如果没有再查数据库,并将结果保存在redis中供后续请求使用。

c 复制代码
    private List<CategoryEntity> getCategoryCache() {
        long l = System.currentTimeMillis();

        String catelogJson = stringRedisTemplate.opsForValue().get(BasicTypeConstants.CATELOG_JSON);
        log.info("查询redis结束{}", System.currentTimeMillis() - l);
        List<CategoryEntity> cateList;
        if (StrUtil.isEmpty(catelogJson)) {
            //将数据库的多次查询变为一次
            cateList = this.baseMapper.selectList(null);
            stringRedisTemplate.opsForValue().set(BasicTypeConstants.CATELOG_JSON, JSON.toJSONString(cateList));
        } else {
            cateList = JSON.parseObject(catelogJson,  new TypeReference<List<CategoryEntity>>() {});
        }

        log.info("查询结束{}", System.currentTimeMillis() - l);
        return cateList;
    }

二,154-缓存-缓存使用-压力测试出的内存泄露及解决

在压测的过程中,可能会出现如下错误。

这是由于Spring Boot 2.0以后默认使用的Lettuce客户端所引发的一种内存溢出问题。

Lettuce客户端的引入

自Spring Boot 2.0版本起,Lettuce成为了操作Redis的默认客户端。Lettuce是基于Netty的网络通信框架实现的,它提供了异步的Redis操作能力,可以显著提高应用程序的性能。

堆外内存溢出问题

在使用Lettuce客户端时,可能会遇到OutOfDirectMemoryError错误。这是因为Lettuce使用Netty进行网络通信,而Netty默认的堆外内存设置可能不足以满足应用程序的需求。

问题分析

问题原因

  1. Lettuce的Bug:Lettuce客户端存在一个Bug,导致Netty在使用默认的堆外内存设置时,可能会发生内存溢出。

  2. 默认堆外内存设置 :Netty如果没有指定堆外内存,默认使用-Xmx300m,这可能不足以应对高并发场景。

解决方案

方案一:调整堆外内存

可以通过设置系统属性-Dio.netty.maxDirectMemory来增加Netty的堆外内存。但这种方法并不是最佳实践,因为它只是简单地增加内存,而没有解决根本问题。

方案二:切换到Jedis客户端

  1. 升级Lettuce客户端:如果问题是由Lettuce的Bug引起的,可以尝试升级到最新版本的Lettuce客户端。

  2. 切换到Jedis:如果升级Lettuce客户端后问题仍然存在,可以考虑切换回Jedis客户端。Jedis是Spring Boot之前默认使用的Redis客户端,它没有使用Netty,因此不会遇到堆外内存溢出的问题。在redis的starter中排除对lettuce的依赖,然后引入jedis的依赖。

c 复制代码
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>

三,155-缓存-缓存使用-缓存击穿、穿透、雪崩

Redis在实际使用过程中,可能会遇到缓存击穿、缓存穿透和缓存雪崩等问题,这些问题严重影响了缓存的效率和系统的稳定性。

缓存击穿(Cache Breakthrough)

问题描述

缓存击穿是指一个非常热点的数据在某个时间点过期时,大量请求直接打在数据库上,导致数据库瞬时压力过大。

解决方案

  1. 设置过期时间:为缓存数据设置合理的过期时间,避免同时过期。
  2. 互斥锁:在缓存失效时,通过互斥锁保证同一时间只有一个请求能够访问数据库,其他请求等待或重试。
  3. 预热机制:在缓存数据即将过期前,提前更新缓存数据。

缓存穿透(Cache Penetration)

问题描述

缓存穿透是指查询一个不存在的数据,由于缓存和数据库中都没有,导致请求直接穿透缓存查询数据库。

解决方案

  1. 布隆过滤器:使用布隆过滤器拦截不存在的数据请求,避免对数据库的查询。
  2. 缓存空值:对于查询结果为空的操作也进行缓存,但可以设置较短的过期时间。
  3. 限制访问频率:对用户访问频率进行限制,避免恶意攻击。

缓存雪崩(Cache Avalanche)

问题描述

缓存雪崩是指在某一时刻,大量的缓存数据同时过期,导致大量请求直接访问数据库,造成数据库压力过大。

解决方案

  1. 分散缓存过期时间:使用随机时间或分片策略来分散缓存的过期时间,避免同时过期。
  2. 限流降级:在系统访问量剧增时,通过限流和降级策略保护系统。
  3. 高可用架构:使用Redis集群,提高缓存系统的可用性和容错性。

实例分析

缓存击穿示例

假设一个电商平台的商品详情页非常热门,缓存设置为10分钟过期。当缓存过期时,如果大量用户同时访问该页面,会导致数据库压力剧增。解决方案是在缓存数据中设置互斥锁,确保同一时间只有一个请求访问数据库。

缓存穿透示例

在电商平台搜索一个不存在的商品,如果没有布隆过滤器,每次搜索都会查询数据库,这会给数据库带来不必要的压力。解决方案是使用布隆过滤器拦截这些请求,避免对数据库的查询。

缓存雪崩示例

电商平台的促销活动导致大量商品缓存在某一时刻同时过期,如果此时用户访问量激增,数据库将承受巨大压力。解决方案是使用Redis集群分散缓存过期时间,并通过限流降级策略保护系统。

相关推荐
.生产的驴1 小时前
SpringBoot 对接第三方登录 手机号登录 手机号验证 微信小程序登录 结合Redis SaToken
java·spring boot·redis·后端·缓存·微信小程序·maven
Hejjon1 小时前
SpringBoot 整合 SQLite 数据库
笔记
西洼工作室4 小时前
【java 正则表达式 笔记】
java·笔记·正则表达式
初学者7.4 小时前
Webpack学习笔记(2)
笔记·学习·webpack
新手上路狂踩坑5 小时前
Android Studio的笔记--BusyBox相关
android·linux·笔记·android studio·busybox
kong79069286 小时前
电商项目-网站首页高可用(二)
缓存·二级缓存·网站首页高可用
stm 学习ing7 小时前
HDLBits训练3
c语言·经验分享·笔记·算法·fpga·eda·verilog hdl
一个懒鬼7 小时前
Windows脚本清理C盘缓存
windows·缓存
尘觉7 小时前
算法的学习笔记—扑克牌顺子(牛客JZ61)
数据结构·笔记·学习·算法
bohu837 小时前
sentinel学习笔记1-为什么需要服务降级
笔记·学习·sentinel·滑动窗口