电商项目——缓存——第五章——中篇

电商项目——全文检索-ElasticSearch——第一章——中篇
电商项目——商城业务-商品上架——第二章——中篇
电商项目——商城业务-首页——第三章——中篇
电商项目——性能压测——第四章——中篇
电商项目——缓存——第五章——中篇
电商项目——商城业务-检索服务——第六章——中篇
电商项目——商城业务-异步——第七章——中篇
电商项目——商品详情——第八章——中篇
电商项目——认证服务——第九章——中篇
电商项目——购物车——第十章——中篇
电商项目——消息队列——第十一章——中篇
电商项目——订单服务——第十二章——中篇
电商项目——分布式事务——第十三章——中篇

文章目录

  • 1:缓存使用
    • 1.1 本地缓存与分布式缓存
    • 1.2 整合redis测试
    • 1.3 改造三级分类业务
    • 1.4 压力测试出现的内存泄露及解决
    • 1.5 缓存击穿,穿透,雪崩
    • 1.6 加锁解决缓存击穿问题
    • 1.7 本地锁在分布式下的问题
  • 2:分布式锁
    • 2.1 分布式锁原理与使用
    • 2.2 Redisson简介&整合
    • 2.3 Redisson-lock锁测试
      • 2.3.1 可重入锁
    • 2.4 Redisson-lock看门狗原理-redisson如何解决死锁
    • 2.5 Redisson-读写锁测试
    • 2.6 Redisson-读写锁补充
    • 2.7 Redisson- 闭锁测试
    • 2.8 Redisson- 信号量测试
    • 2.9 缓存一致性解决
  • 3: SpingCache
    • 3.1 简介
    • 3.2 整合&体验@Cacheable
    • 3.3 @Cacheable细节设置
    • 3.4 自定义缓存配置
    • 3.5 @CacheEvict
    • 3.6 原理与不足

1:缓存使用

1.1 本地缓存与分布式缓存

本地缓存与分布式缓存

1.2 整合redis测试

整合redis测试

1.3 改造三级分类业务

前面我们整合了redis,并且使用了stringRedisTemplate,现在我们来对如下的三级分类使用缓存进行业务优化
IndexController

    //以json格式返回
    @ResponseBody
    @GetMapping("index/json/catalog.json")
    public  Map<String, List<Catelog2Vo>> getCatalogJson(){
   
        Map<String, List<Catelog2Vo>> indexJson=categoryService.getCatalogJson();
        return indexJson;
    }

categoryServiceImpl

 @Override
    public Map<String, List<Catelog2Vo>> getCatalogJson() {
   
        //给缓存中放入json字符串,拿出json字符串,还要逆转为可用的对象类型【序列化,反序列化】
        /**
         * 由于网络传输,我们相当于给内存创建了一个对象catalogJsonFromDb,要存到redis里面,必须要整成一个可传输的流数据,从redis里面拿到这个串又的逆转为对象
         * 这就是序列化,反序列化
         */

        //1:加入缓存逻辑(缓存存放的数据是json字符串)
        //json跨语言,跨平台兼容
        //1.1判断redis中是否有catalogJSON数据
        String catalogJSON = stringRedisTemplate.opsForValue().get("catalogJSON");
        if (StringUtils.isEmpty(catalogJSON)){
   

            //1.2缓冲中没有,就查询数据库
            Map<String, List<Catelog2Vo>> catalogJsonFromDb = getCatalogJsonFromDb();
            //1.3 查到数据库在放入缓存
            String string = JSON.toJSONString(catalogJsonFromDb);
            stringRedisTemplate.opsForValue().set("catalogJSON",string);

            return catalogJsonFromDb;
        }

        Map<String, List<Catelog2Vo>> result = JSON.parseObject(catalogJSON, new TypeReference<Map<String, List<Catelog2Vo>>>() {
   
        });

        return result;
    }
  • json跨语言,跨平台兼容,比如做一个物流系统,使用php,它也要从缓存中获取数据,如果它拿到的是json数据,那么大家都一样都可以解析,如果存的是对象字节流,默认的是java序列化机制,php拿到的就是java序列化的流数据,那么php就不可以拿到这个流(没有java的系统),所以我们以后给redis都保存以json格式,全语言,全平台
  • 给缓存中放入json字符串,拿出json字符串,还要逆转为可用的对象类型【序列化,反序列化】
        /**
         * 由于网络传输,我们相当于给内存创建了一个对象catalogJsonFromDb,
         * 要存到redis里面,必须要整成一个可传输的流数据串,
         * 从redis里面拿到这个串又的逆转为对象
         * 这就是序列化,反序列化
         */

进行测试查看是否使用缓存性能会比,不使用缓存和直接每一次查询数据库的性能要好

查看是否可以成功获取数据
http://localhost:30000/index/json/catalog.json电商项目——缓存——第五章——中篇_第1张图片
电商项目——缓存——第五章——中篇_第2张图片

1.4 压力测试出现的内存泄露及解决

进行压力测试
电商项目——缓存——第五章——中篇_第3张图片
电商项目——缓存——第五章——中篇_第4张图片
电商项目——缓存——第五章——中篇_第5张图片
产生如上的原因:如下
在这里插入图片描述
电商项目——缓存——第五章——中篇_第6张图片
解决办法:
在这里插入图片描述
操作步骤:先排除掉redis里面的lettuce,在引入依赖jedis
mall-product

		
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-data-redisartifactId>
			<exclusions>
				<exclusion>
					<groupId>io.lettucegroupId>
					<artifactId>lettuce-coreartifactId>
				exclusion>
			exclusions>
		dependency>

		<dependency>
			<groupId>redis.clientsgroupId>
			<artifactId>jedisartifactId>
		dependency>

再次进行压力测试
得出如下对比数据
电商项目——缓存——第五章——中篇_第7张图片
小知识:stringRedisTemplate和lettuce,jedis的关系
在这里插入图片描述
查看RedisAutoConfiguration 的源码,你会发现上面的@Import注解就是引入了Lettuce和Jedis

@Import({
    LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
   
//.....

1.5 缓存击穿,穿透,雪崩

缓存击穿,穿透,雪崩

1.6 加锁解决缓存击穿问题

第一个方法:加如下代码块

     synchronized (){
   
            
        }

我们要去哪里加锁呢?我们要去查询数据库的时候加锁如下

   /**
         * 1:将数据库的多次查询变为1次
         * @return
         */
    //从数据库查询并且封装db的
    public Map<String, List<Catelog2Vo>> getCatalogJsonFromDb() {
   

        //只要是同一把锁,就可以锁住需要这个锁的所有线程
        /**
         * 1:synchronized (this){ Springboot所有组件在容器值都是单例的,加this可以
         */
        synchronized (this){
   
            //第二个人得到锁以后就要去缓存中确定一次,如果第一个人已经在数据库中查询到数据放入缓存中,第二个人就不用在去查询数据库了
            String catalogJSON = stringRedisTemplate.opsForValue().get("catalogJSON");
            if (!StringUtils.isEmpty(catalogJSON)){
   
                Map<String, List<Catelog2Vo>> result = JSON.parseObject(catalogJSON, new TypeReference<Map<String, List<Catelog2Vo>>>() {
   
                });
            }
            //将数据库的多次查询变为1次
            List<CategoryEntity> selectList = baseMapper.selectList(null);
            //1:查出所有1级分类
            List<CategoryEntity> level1Category = getParent_cid(selectList,0L);

            //2:封装数据
            Map<String, List<Catelog2Vo>> parent_cid = level1Category.stream().collect(Collectors.toMap(k -> k.getCatId().toString(), v -> {
   
                // 1.每一个的一级分类,查到这个一级分类的二级分类
                List<CategoryEntity> categoryEntities = getParent_cid(selectList,v.getCatId());
                //2:封装上面的结果
                List<Catelog2Vo> catelog2Vos = null;
                if (categoryEntities != null) {
   
                    catelog2Vos = categoryEntities.stream().map(item -> {
   
                        Catelog2Vo catelog2Vo = new Catelog2Vo(v.getCatId().toString(), null, item.getCatId().toString(), item.getName());

                        //1.给当前二级分类的三级分类封装成vo
                        List<CategoryEntity> level3Category = getParent_cid(selectList,item.getCatId());
                        //2:封装成指定格式

                        if (level3Category!=null){
   
                            List<Catelog2Vo.Catelog3Vo> collect = level3Category.stream().map(items -> {
   
                                Catelog2Vo.Catelog3Vo catelog3Vo = new Catelog2Vo.Catelog3Vo(item.getCatId().toString(),items.getCatId().toString(),items.getName());

                                return catelog3Vo;

                            }).collect(Collectors.toList());
                            catelog2Vo.setCatalog3List(collect

你可能感兴趣的:(电商项目,分布式,redis,java)