redis缓存问题引进

举报
yd_249383650 发表于 2023/03/17 11:13:21 2023/03/17
【摘要】 ​ 1、缓存使用为了系统性能的提升,我们一般都会将部分数据放入缓存中,加速访问。而 db 承担数据落 盘工作。哪些数据适合放入缓存? 即时性、数据一致性要求不高的 访问量大且更新频率不高的数据(读多,写少)举例:电商类应用,商品分类,商品列表等适合缓存并加一个失效时间(根据数据更新频率 来定),后台如果发布一个商品,买家需要 5 分钟才能看到新的商品一般还是可以接受的。  ​编辑data...

 1、缓存使用

为了系统性能的提升,我们一般都会将部分数据放入缓存中,加速访问。而 db 承担数据落 盘工作。

哪些数据适合放入缓存?

 即时性、数据一致性要求不高的

 访问量大且更新频率不高的数据(读多,写少)

举例:电商类应用,商品分类,商品列表等适合缓存并加一个失效时间(根据数据更新频率 来定),后台如果发布一个商品,买家需要 5 分钟才能看到新的商品一般还是可以接受的。 

 编辑

data = cache.load(id);//从缓存加载数据

If(data == null){ data = db.load(id);//从数据库加载数据

cache.put(id,data);//保存到 cache 中

}

return data;

注意:在开发中,凡是放入缓存中的数据我们都应该指定过期时间,使其可以在系统即使没有主动更新数据也能自动触发数据加载进缓存的流程。避免业务崩溃导致的数据永久不一致 问题。 

2、整合 redis 作为缓存 

1、引入 redis-starter

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

2、配置 redis 

  redis:
    host: 192.168.107.134
    port: 6379

3、使用 RedisTemplate 操作 redis 

@SpringBootTest(classes = GulimallProductApplication.class)
@RunWith(SpringRunner.class)
public class GUlimallProductApplicationTest {
    
    @Autowired
    StringRedisTemplate stringRedisTemplate
    @Test
    public void testRedis(){
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        ops.set("hello","word"+ UUID.randomUUID().toString());
        String v = ops.get("hello");
        System.out.println(v);
    }
}

4、切换使用 jedis 

//todo 产生堆外内存溢出
//1)springboot2.0以后默认使用lettuce作为操作redis的客户端。他使用netty进行网络通信
//2)lettuce的bug导致netty堆外内存溢出 netty如果没有指定堆外内存,默认使用-Xmx
//可以通过-Dio.netty.maxDirectMemory进行设置

//解决方案:不能使用-Dio.netty.maxDirectMemory只去调大
//1)升级lettuce
//2)切换使用jedis

//lettuce jedis操作redis底层的客户端。spring再次封装成为redisTemplate
<!--        redis依赖-->
        <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>

修改业务代码

  @Override
    public Map<String, List<Catelog2Vo>> getCatalogJson(){
        
        //1.加入缓存逻辑
        String catalogJSON = redisTemplate.opsForValue().get("catalogJSON");

        if (StringUtils.isEmpty(catalogJSON)){
            //2 缓存数据   缓存中没有
            Map<String, List<Catelog2Vo>> catalogJsonForDb = getCatalogJsonForDb();

            //3.查到的数据再放入缓存中,将对象转为json放进
            String s = JSON.toJSONString(catalogJsonForDb);
            redisTemplate.opsForValue().set("catalogJSON",s);
            return catalogJsonForDb;
        }
        //转为我们指定的对象
        Map<String, List<Catelog2Vo>> result = JSON.parseObject(catalogJSON, new TypeReference<Map<String, List<Catelog2Vo>>>() {
        });
       return   result;


    }
/**
     *  从数据库查询数据得到数据
     * @return
     */
    public Map<String, List<Catelog2Vo>> getCatalogJsonForDb() {

        /**
         * 1.将数据库的数据只查一次
         */
        List<CategoryEntity> selectList = baseMapper.selectList(null);

        //1.查出所有一级分类
        List<CategoryEntity> level1Categorys = getLevel1Categorys();
        //2封装数据
        Map<String, List<Catelog2Vo>> parent_cid = level1Categorys.stream().collect(Collectors.toMap(k -> k.getCatId().toString(), v -> {
            //1.每一个的一级分类,查到这个一级分类的二级分类
            List<CategoryEntity> categoryEntities = baseMapper.selectList(new QueryWrapper<CategoryEntity>()
                    .eq("parent_cid", v.getCatId()));
            //2.封装上面的结果
            List<Catelog2Vo> catelog2Vos = null;

            if (categoryEntities != null) {
                catelog2Vos = categoryEntities.stream().map(l2 -> {
                    Catelog2Vo catelog2Vo = new Catelog2Vo(
                            v.getParentCid().toString(), null, v.getName().toString(), v.getCatId().toString()
                    );
                    //找出当前二级分类的三级分类分装成vo
                    List<CategoryEntity> categoryEntities1 = baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", l2.getCatId()));
                    List<Catelog2Vo.Catelog3Vo> collect=null;
                    if (categoryEntities1!=null){
                        collect = categoryEntities1.stream().map(l3 -> {
                            Catelog2Vo.Catelog3Vo catelog3Vo = new Catelog2Vo.Catelog3Vo(l2.getCatId().toString(), l3.getName(), l3.getCatId().toString());
                            return catelog3Vo;

                        }).collect(Collectors.toList());
                    }
                    catelog2Vo.setCatalog3List(collect);
                    return catelog2Vo;
                }).collect(Collectors.toList());
            }
            return catelog2Vos;
        }));
        return  parent_cid;
    }



【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。