项目第五天

1.无限极数据获取

1.递归

详细见上一篇总结

2.循环

循环-一次性把所以的节点都查询出来,再来组织他们关系
①查询所有节点
②如果是第一级放入返回的list
③如果是非第一级,建立父子关系
1 获取服务 map(id-node)
2 把自己作为父亲一个儿子放进去就ok children=new Array<>();
具体代码如下

@Service
public class CourseTypeServiceImpl extends ServiceImpl<CourseTypeMapper, CourseType> implements ICourseTypeService {
    @Autowired
    private CourseTypeMapper courseTypeMapper;
    //和mapper差不多,mapper操作的是数据库的数据,而换成操作的是redis数据
    @Autowired
    private ICourseTypeCache courseTypeCache;
    @Override
    public List<CourseType> treeData(long pid) {
        
                System.out.println("bd....");
                //否则先查询数据库,放入换成后再返回
                //递归
                // return treeDataRecursion(pid);
                //循环
              
                return treeDataLoop(pid);
             

    }
    //循环方案  一条sql自己组织关系
    private List<CourseType> treeDataLoop(Long pid){
        //1.查询所有节点
        List<CourseType> courseTypes = courseTypeMapper.selectList(null);
        //为了查询父亲方便,我建立所有节点的一个key(Id)-vue(Node)集合 n
        HashMap<Long, CourseType> allNodeDto = new HashMap<>();
        for (CourseType courseType : courseTypes) {
            allNodeDto.put(courseType.getId(),courseType);
        }
        //2.组织关系
        List<CourseType> result=new ArrayList<>();
        for (CourseType courseType : courseTypes) {
            //如果是一级节点就放入result
            if (courseType.getPid().intValue()==0){
                result.add(courseType);
            }else {
                //2.2 不是一级节点要建立父子关系-把自己作为父亲一个儿子添加进去
                //2.2.1 获取父亲
                Long pidTmp = courseType.getPid();
                //提前建立id和Node直接关系,直接获取
                CourseType parent = allNodeDto.get(pidTmp);
                //给父亲添加儿子
                parent.getChildren().add(courseType);
            }
        }
        return result;

    }

2.缓存优化

1.对访问量多但是修改次数少的数据可以使用redis缓存来减少对数据库的压力,从而达到优化

2.使用集群的时候就使用redis缓存,而jpa这些的缓存是在单项目架构的时候使用

3.使用缓存的好处:
减轻数据库压力
提高访问速度,增强用户体验
4.我们缓存数据很多?-redis集群

		主从复制-单主故障
        哨兵模式-每个节点数据都是一样
        redis-cluster: 单点故障,高并发,大量数据

redis的使用步骤

1.设置redis的密码
在此文件中进行修改
在这里插入图片描述然年在文件中搜索requirepass
在这里插入图片描述
2…导入redis

<dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>

3…配置redis的配置文件
redis.properties

redis.host=127.0.0.1  #ip地址
redis.port=6379  #用哪个端口
redis.password=redis的密码
redis.timeout=1000

4.在工具类中设置连接池的方法

/**
 * 获取连接对象
 */
public enum RedisUtils {
    INSTANCE;
    static JedisPool jedisPool=null;
    static {
        //1 创建连接池配置对象
        JedisPoolConfig config = new JedisPoolConfig();
        //2 进行配置-四个配置
        config.setMaxIdle(1);//最小连接数
        config.setMaxTotal(11);//最大连接数
        config.setMaxWaitMillis(10 * 1000L);//最长等待时间
        config.setTestOnBorrow(true);//测试连接时是否畅通
        //3 通过配置对象创建连接池对象
        Properties properties = null;
        try {
            properties = new Properties();
            properties.load(RedisUtils.class.getClassLoader().getResourceAsStream("redis.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        String host = properties.getProperty("redis.host");
        String port = properties.getProperty("redis.port");
        String password = properties.getProperty("redis.password");
        String timeout = properties.getProperty("redis.timeout");
        System.out.println(host);
        System.out.println(port);
        System.out.println(password);
        System.out.println(timeout);
        jedisPool = new JedisPool(config, host, Integer.valueOf(port),Integer.valueOf(timeout), password);
    }

    //获取连接
    public Jedis getSource() {
        return jedisPool.getResource();
    }

    //关闭资源
    public void closeSource(Jedis jedis) {
        if (jedis != null) {
            jedis.close();
        }

    }
    /**
     * 设置字符值
     *
     * @param key
     * @param
     */
    public void del(String key) {
        Jedis jedis = getSource();
        jedis.del(key);
        closeSource(jedis);
    }
    /**
     * 设置字符值
     *
     * @param key
     * @param value
     */
    public void set(String key, String value) {
        Jedis jedis = getSource();
        jedis.set(key, value);
        closeSource(jedis);
    }

    /**
     * 设置
     * @param key
     * @param value
     */
    public void set(byte[] key, byte[] value) {
        Jedis jedis = getSource();
        jedis.set(key, value);
        closeSource(jedis);
    }

    /**
     *
     * @param key
     * @return
     */
    public byte[]  get(byte[] key) {
        Jedis jedis = getSource();
        try {
            return jedis.get(key);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeSource(jedis);
        }
        return null;

    }

    /**
     * 设置字符值
     *
     * @param key
     */
    public String get(String key) {
        Jedis jedis = getSource();
        try {
            return jedis.get(key);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeSource(jedis);
        }

        return null;

    }
}

5.写crud的方法

@RestController
/**
 * 增/修改 set
 * 删除 del
 * 查询 get
 */
@RequestMapping("/redis")
public class RedisController {
    @PostMapping
    public AjaxResult add(
            @RequestParam(value = "key",required = true) String key,
            @RequestParam(value = "value",required = true) String value)
    {
        try
        {
            RedisUtils.INSTANCE.set(key,value);
            return AjaxResult.me();
        }catch (Exception e){
            e.printStackTrace();
            return AjaxResult.me().setSuccess(false).setMessage("添加失败");
        }
    }

    @DeleteMapping
    public AjaxResult del(@RequestParam(value = "key",required = true) String key)
    {
        try
        {
            RedisUtils.INSTANCE.del(key);
            return AjaxResult.me();
        }catch (Exception e){
            e.printStackTrace();
            return AjaxResult.me().setSuccess(false).setMessage("删除失败");
        }
    }

    @GetMapping
    public String get(@RequestParam(value = "key",required = true) String key)
    {
        try
        {
            return RedisUtils.INSTANCE.get(key);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

缓存问题以及一些面试题

缓存穿透,缓存击穿,缓存雪崩-面试必备技能
https://blog.csdn.net/kongtiao5/article/details/82771694
缓存穿透:高并发访问数据库中不存在数据,放入缓存的数据也没有,击穿缓存每次都要查询数据库.
1)有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层数据库的查询压力。

2)另外也有一个更为简单粗暴的方法,如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。
缓存击穿:一个key过期,又来高并发访问. 直接高并发访问数据库.
1)让热点数据永远不过期.
2)加互斥锁,互斥锁参考代码如下 我在访问数据库是你就不要访问
缓存雪崩:一堆key同时过期
设置过期时间不一致就ok. 热点数据永远不过期

if (courseTypesOfDb == null || courseTypesOfDb.size()<1){
//缓存穿透
redisClient.add(COURSETYPE_KEY_IN_CACHE,"[]");
}else{
//转换为json字符串
String jsonArrStr = JSONArray.toJSONString(courseTypesOfDb);
//设置获取
//缓存数据永远不过期 缓存击穿 缓存雪崩
redisClient.add(COURSETYPE_KEY_IN_CACHE,jsonArrStr);
}

三 服务调用

服务间调用–feign-ribbon,hystrix(负载均衡,服务高可用(熔断))
外部调用服务-都是通过zuul-ribbon,hystrix(负载均衡,服务高可用(熔断))
无论是服务间调用或者是外部调用都是进行负载均衡和熔断+降级。
commonService
redis服务是给服务间调用,前端不能直接操作redis
fastdfs直接给前端调用,前端可以直接删除图片和删除图片

微服务架构(springcloud)中是怎么做负载均衡?
feign
微服务架构(springcloud)中是怎么做熔断和降级?
hystrix

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值