暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Java面试:2021.05.12

Java面试百分百 2021-08-17
193

1、redis中RDB和AOF的使用情况分别是什么?

如果是保存不重要的数据可以使用RDB方式(比如缓存数据),如果是保存很重要的数据就要使用AOF,但是两种方式也可以同时使用。

RDB触发机制:

第一种:
save(同步)
1 客户端输入save命令----》redis服务端----》同步创建RDB二进制文件
2 会造成redis的阻塞(数据量非常大的时候)
3 文件策略:如果老的RDB存在,会替换老的
4 复杂度 o(n)

第二种:
bgsave(异步,Backgroud saving started)
1 客户端输入save命令----》redis服务端----》异步创建RDB二进制文件(fork函数生成一个子进程(fork会阻塞reids),执行createRDB,执行成功,返回给reids消息)
2 此时访问redis,会正常响应客户端
3 文件策略:跟save相同,如果老的RDB存在,会替换老的
4 复杂度 o(n)

第三种:(常用方式)(******)
自动(通过配置文件)
配置 seconds changes
save 900 1
save 300 10
save 60 10000
如果60s中改变了1w条数据,自动生成rdb
如果300s中改变了10条数据,自动生成rdb
如果900s中改变了1条数据,自动生成rdb


以上三条符合任意一条,就自动生成rdb,内部使用bgsave。

RDB触发机制一般使用第三种方式,但是这种方式也会有缺点。如果修改的条数没有在设置范围内那么就不会触发,就会引发很多数据没有持久化的情况。所以我们一般采用下面方式:AOF。


AOF

问题:耗时,耗性能。不可控,可能会丢失数据。

实现策略:

日志不是直接写到硬盘上,而是先放在缓冲区,缓冲区根据一些策略,写到硬盘上
#第一种:
always:redis
--》写命令刷新的缓冲区---》每条命令fsync到硬盘---》AOF文件
#第二种:
everysec(默认值):redis——》写命令刷新的缓冲区
---》每秒把缓冲区fsync到硬盘--》AOF文件
#第三种:
no:redis——》写命令刷新的缓冲区
---》操作系统决定,缓冲区fsync到硬盘--》AOF文件


RDB和AOF的选择

rdb最佳策略

rdb关掉,主从操作时;
集中管理:按天,按小时备份数据;

主从配置,从节点打开。

aof最佳策略

开:缓存和存储,大部分情况都打开,
aof重写集中管理
everysec:通过每秒刷新的策略

最佳策略

小分片:每个redis的最大内存为4g;
缓存或存储:根据特性,使用不通策略;
时时监控硬盘,内存,负载网络等;
有足够内存。


2、斐波那契数列的实现。

实现一:基于递归形式实现

    public static int getFib(int n){
    if(n < 0){
    return -1;
    }else if(n == 0){
    return 0;
    }else if(n == 1 || n ==2){
    return 1;
    }else{
    return getFib(n - 1) + getFib(n - 2);
    }
        }

    递归是最简单的实现方式,但递归有很多的问题,在n的值非常大时,会占用很多的内存空间,既然该数列定义F(n)=F(n-1)+F(n-2)(n≥2,n∈N*),那么我们可以从头到尾进行计算,先计算前面的值,然后逐步算出第n个值。

    方式二:基于变量形式实现

      public static int getFib2(int n){
      if(n < 0){
      return -1;
      }else if(n == 0){
      return 0;
      }else if (n == 1 || n == 2){
      return 1;
      }else{
      int c = 0, a = 1, b = 1;
      for(int i = 3; i <= n; i++){
      c = a + b;
      a = b;
      b = c;
      }
      return c;
      }
          }

      从上面的实现中我们定义了3个变量a、b、c其中c=a+b,然后逐步进行计算从而得到下标为n的值。
      既然我们可以定义变量进行存储,那么同样我们还可以定义一个数组,该数组的每一个元素即一个斐波那契数列的值,这样我们不仅能得到第n个值,还能获取整个斐波那契数列。

      方式三:基于数组的实现

        public static int getFib3(int n){
        if(n < 0){
        return -1;
        }else if(n == 0){
        return 0;
        }else if (n == 1 || n == 2){
        return 1;
        }else{
        int[] fibAry = new int[n + 1];
        fibAry[0] = 0;
        fibAry[1] = fibAry[2] = 1;
        for(int i = 3; i <= n; i++){
        fibAry[i] = fibAry[i - 1] + fibAry[i - 2];
        }
        return fibAry[n];
        }
            }


        3、数据库插入大批量数据的优化方案。

        3.1、数据有序插入;

        由于数据库插入时,需要维护索引数据无序的记录会增大维护索引的成本
        。我们可以参照InnoDB使用的B+tree索引,如果每次插入记录都在索引的最后面,索引的定位效率很高,并且对索引调整较小;如果插入的记录在索引中间,需要B+tree进行分裂合并等处理,会消耗比较多计算资源,并且插入记录的索引定位效率会下降,数据量较大时会有频繁的磁盘操作。

        3.2、在事务中进行插入处理;

        使用事务可以提高数据的插入效率,这是因为进行一个INSERT操作时,MySQL内部会建立一个事务,在事务内才进行真正插入处理操作。通过使用事务可以减少创建事务的消耗,所有插入都在执行后才进行提交操作


        结论:

        合并数据+事务的方法在较小数据量时,性能提高是很明显的,数据量较大时(1千万以上),性能会急剧下降,这是由于此时数据量超过了innodb_buffer的容量,每次定位索引涉及较多的磁盘读写操作,性能下降较快。而使用合并数据+事务+有序数据的方式在数据量达到千万级以上表现依旧是良好,在数据量较大时,有序数据索引定位较为方便,不需要频繁对磁盘进行读写操作,所以可以维持较高的性能


        注意事项:

        1. SQL语句是有长度限制
          ,在进行数据合并在同一SQL中务必不能超过SQL长度限制,通过max_allowed_packet配置可以修改,默认是1M,测试时修改为8M。

        2. 事务需要控制大小
          ,事务太大可能会影响执行的效率。MySQL有innodb_log_buffer_size配置项,超过这个值会把innodb的数据刷到磁盘中,这时,效率会有所下降。所以比较好的做法是,在数据达到这个这个值前进行事务提交。

        3.3、存储过程;

        3.4、加缓存,使用redis等对数据进行预加载;

        3.5、临时表;

        3.6、队列;

        3.7、分库分表(更大的数据量)等。


        今日份其他面试问题:

        1. 哈希原理;

        2. 哈希结构和b+tree谁的速度更快;

        3. 如何分库分表;

        4. 分布式事务解决方案;

        5. kafka如何解决不能传送大于10k的消息;

        6. nacos和eruika如何选型;

        7. 你的项目上线了吗?日火多少,统计用户是多少?

        8. 说说多表子查询;

        9. 刷盘策略是什么;

        10. dc分布式中心;

        11. 关于项目的问题;

        12. 项目从开发到结束是怎么个流程;

        13. 项目团队有多人人;

        14. 项目怎么部署发布的;

        15. Redis的应用场景,请列举一个场景,并说明怎么实现的;

        16. SQL优化;

        17. 项目为什么选择了spring cloud ,不用Dubbo;

        18. 介绍一下使用了Spring cloud哪些组件;

        19. MongoDB的应用场景,为什么选择MongoDB,不选择mysql;

        20. 介绍一下你了解的MQ;

        21. Spring Boot常用注解及作用;

        22. Vue怎么使用的,常用标签;

        23. 如果让你设计消息队列,你怎么设计;

        24. 开发代码的规范,你谈一谈;

        25. Mybatis和mybatis-plus的区别,怎么选型;

        26. 说说bean的生命周期;

        27. 缓存雪崩如何解决? 缓存穿透如何解决?

        28. 如何使用Redis完成订单列表场景?

        29. MySQL里有2000w数据,Redis中只存20w的数据,如何保证Redis中的都是热点数据?

        30. Redis相比memcached有哪些优势?

        31. 假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如何将它们全部找出来?

        32. 我说的登录验证.加密方式是什么?

        33. 有没有参与部署?

        34. 为什么用mq不是kafuka?

        35. 说一下你对高并发线程的理解?

        36. 说一下mysql调优?

        37. 项目中第三方支付接口是什么?

        38. 讲一下项目中用到的搜索引擎?

        39. redis的增量更新;

        40. 懒汉式在多线程中如何保证唯一又不影响效率的;

        41. springboot的启动类,为什么添加上后就可以启动了;

        42. MQ生产者生产消息如何保证消息被消费了;

        43. 冒泡排序后开始索引值与输出结果对应;

        44. 词典,set存储,如何获取词典中的词汇;

        45. 你以后的职业规划是什么。


        文章转载自Java面试百分百,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

        评论