面经1

发布时间 2023-11-14 18:38:57作者: UpZhou

面经1

  1. 自我介绍
  2. 介绍项目
  3. ES作用?
  4. ES的搜索和数据库的模糊查询有何区别?
  5. 介绍Spring的AOP、IOC
  6. SpringBoot常用注解?
  7. @Autowired注解中想要其中某属性在注入时有优先权,怎么做?
  8. 介绍MySQL事务?什么时候会回滚?
  9. 介绍MySQL索引?索引有哪些类型?为什么要用索引?
  10. 设置索引时要考虑什么因素(索引的设计原则)?
  11. B+树索引、hash索引区别?
  12. 栈和队列的区别?
  13. Mybatis的优点?
  14. Redis的作用?为什么快?
  15. Kafka的作用?为什么快?
  16. 为什么要用到消息队列?
  17. 平时如何学习提升自己?
  18. 开源项目是否有学习?

1. 自我介绍(个人信息 + 项目)

2. 介绍项目

1、明确项目是做什么的 
2、明确项目的价值。(为什么做这个项目,它解决了用户什么痛点,它带来什么价值?) 
3、明确项目的功能。(这个项目涉及哪些功能?) 
4、明确项目的技术。(这个项目用到哪些技术?) 
5、明确个人在项目中的位置和作用。(你在这个项目的承担角色?) 
6、明确项目的整体架构。 
7、明确项目的优缺点,如果重新设计你会如何设计。 
8、明确项目的亮点。(这个项目有什么亮点?) 
9、明确技术成长。(你通过这个项目有哪些技术成长?

该项目是程序员的一个交流平台,为了方便程序员间相互分享和沟通,实现的主要功能有:用户的注册登录,帖子的发布删除、点赞评论,用户间的关注取关、消息收发,全文搜索等。主要用了SpringBoot,MySQL,Mybatis,Redis,Kafka,ES等技术栈。

3. ES作用?

  ES是一个开源的分布式搜索和分析引擎,主要适用场景有:搜索引擎、日志分析、数据分析、实时监控、商业智能、安全性、应用程序开发等。
  优势有:1. 高性能:ES具有高性能的搜索和分析能力,其中涵盖了多种查询语言和数据结构。
      2. 可扩展性:ES是分布式的,可通过增加节点数来扩展搜索和分析能力。
      3. 实时分析:支持实时分析,可对数据实时查询,对快速检索数据很有用。
      4. 灵活性:支持多种数据类型、支持多种语言、支持动态映射,允许快速的调整模型以适应不同的需求。
      5. 可靠性:具有可靠性和高可用,支持数据备份和恢复。

4. ES的搜索和数据库的模糊查询有何区别?

  在实现和应用上都有区别。
  1. 数据模型和索引方式:ES是一个分布式文档型数据库,数据以JSON文档的形式存储在索引中。文档包含多个字段,每个字段可以是文本、数字、日期等不同类型。传统数据库是表格结构,数据以行和列的形式存储。列有特定的数据类型。
  2. 全文搜索 vs 字符串匹配:ES是专门用于全文搜索的数据库,通过使用全文索引、分词,支持更灵活强大的文本搜索。ES的模糊查询不仅仅是对字符串的简单匹配,还考虑了词根、同义词、分词等。传统数据库的模糊查询通常是对字符串的简单匹配,如SQL中的LIKE语句,这种方式不够灵活,尤其在处理自然文本语言时。
  3. 性能和扩展性:ES在大规模文本数据上有出色的性能和扩展性,它用倒排索引等技术让全文搜索很高效。传统数据库的模糊查询性能可能受到索引和表大小的影响,而在处理大规模文本数据时,性能可能不如专门设计用于全文搜索的数据库。
  4. 语法和查询方式:ES用Query DSL(领域特定语言)查询,支持丰富的查询语法,包括:模糊查询、通配符查询、正则表达式查询等。传统数据库用SQL查询语言,其中模糊查询通常通过LIKE语句实现。相对简单,不如ES的查询语法灵活。
  5. 分布式和实时性:ES是分布式的,支持水平扩展,可处理大量数据和查询请求,还提供了实时性,能立即返回查询结果。传统数据库可能需更多的索引和优化来处理模糊查询且可能会在大规模数据的性能上表现较差。
  总之:ES的设计目标是专注于全文搜索和大规模文本数据处理,而传统数据库的模糊查询更多的面向通用的结构化数据查询。

5. 介绍Spring的AOP、IOC

  IOC:控制反转(Inversion of Control),是一种设计思想,将应用程序的控制权从代码反转到框架(Spring容器)中,实现了松散耦合。也就是:没Spring的话,我们要使用的对象,需要我们自己创建,而有了IOC后,对象由IOC容器创建并管理,我们只用在想要使用时从容器中获取就行(@Component,@Resource)。IOC是一种思想和理念,可有不同的实现方式。
  对Spring的IOC来说,是IOC思想的一种实现方式。在容器启动时,会根据每个bean的要求将bean注入到SpringContainer中。若有其他bean需要使用,直接从容器中获取就行。
  如何实现?Spring的IOC容器是ApplicationContexet。
    ApplicationContext context= new AnnotationConfigApplicationContext("cn.wxxlamp.spring.ioc")
    Bean bean = context.getBean(Bean.class)
    
bean.use();
    1. 从配置元数据中获取要DI的业务POJO(这里的配置元数据包括:xml,注解,configuration类等)
    2. 将业务POJO形成BeanDefination注入到SpringContainer中
    3. 使用方通过ApplicationContext从SpringContainer中直接获取即可。

  AOP:面向切面编程(Aspect-Oriented Programming),面向切面编程。简单说就是:把公共的逻辑抽出来,让开发者可以更专注业务逻辑开发。也是一种思想,是对OOP(Object-Oriented Programming)的补充,OOP是面向类和对象,AOP是面向不同切面。如:一个订单的创建需4个步骤:1. 权限校验 2. 事务管理 3. 创建订单 4. 日志打印。若用AOP思想,我们可把这4步当成4个切面,让业务人员专注开发第3切面,其他三个切面则是基础的通用逻辑,统一交给AOP封装和管理。
  如何实现?代理模式。
  
有2种:JDK动态代理(默认)、基于cglib的动态代理。JDK动态代理适用于实现了接口的类,cglib代理适用于没实现接口的类。

6. SpringBoot常用注解?

  @SpringBootApplication,@Controller,@Service,@Repository,@Autowired,@RestController,@RequestMapping,@Configuration,@Value等等

7. @Autowired注解中想要其中某属性在注入时有优先权,怎么做?

  用@Qualifier注解。该注解用于指定要注入的Bean的名称,@Qualifier("xxx")。
  另,要使一个Bean具有优先权,可用@Primary注解。该注解表示优先选择具有该注解的Bean进行注入。若有多个Bean符合注入类型,但只有1个标记有@Primary,呢Spring会选择有@Primary的Bean。

8. 介绍MySQL事务?什么时候会回滚?

  是一组SQL语句的执行单元,这组语句要么全部成功执行,要么全部失败回滚,确保数据库的一致性和完整性。事务有ACID特性:原子性、一致性、隔离性、持久性。
  原子性:事务中所有操作要么全部执行成功,要么全部失败回滚,不存在部分执行的情况。
  一致性:事务的执行使数据库从一个一致性状态变为另一个一致性状态。若事务执行失败,则数据库状态会回滚到事务开始前的状态。
  隔离性:多个事务可并发执行,但一个事务的执行不能被其他事务干扰。隔离性保证了并发执行时数据的一致性。
  持久性:一旦事务提交,其对数据库的修改就是永久性的,即使系统发生故障,数据库也能恢复到事务提交后的状态。
  事务发生回滚的情况有:1. 事务主动回滚:代码中显式调用了ROLLBACK语句。这通常是在发生错误或业务规则违反时,程序通过捕获异常等方式来触发的。2. 事务的SQL语句执行失败;3. 死锁;4. 超时;5. 数据库系统故障

9. 介绍MySQL索引?索引有哪些类型?为什么要用索引?

  索引:数据库中一种用于提高检索速度的数据结构。类似于书籍的目录,通过建立索引,数据库可更快更高效的定位到包含特定值的数据行。InnoDB存储引擎支持2种常见的索引:B+树索引、hash索引。B+树索最常见最有效。
  B+树索引分为:聚簇索引、非聚簇索引。聚簇索引是按每张表的主键构造一个B+树,B+树的叶子节点中记录着表中一行数据的所有值。只要找到了叶子节点,就得到了这条记录的所有值。非聚簇索引的叶子节点不包含行记录的所有值,只包含索引值和主键值。
  根据索引的唯一性,可将索引分为:唯一索引、普通索引。唯一索引要求索引的列值必须唯一,不能重复。
  MySQL 5.6中还增加了全文索引,5.7后通过使用ngram插件开始支持中文。

  为什么要用索引?

  提高检索速度、加速排序和分组操作、加速连接(JOIN)操作、唯一性约束(唯一索引可确保表中某列或某组列的值唯一,防止出现重复数据)、加速数据修改操作。

10. 设置索引时要考虑什么因素(索引的设计原则)?

  1. 考虑查询的频率和效率:频繁查询的列可创建索引来加速查询,不经常查询或数据量较少的列,可不创建。
  2. 选择适当的索引类型:不同类型的索引适合不同查询操作,要根据实际情况选择适合的索引。
  3. 考虑区分度:尽量不选区分度不高的字段作为索引,如性别。但也不绝对,一些数据倾斜严重的字段虽区分度不高,但若有索引,查询占比少的数据时效率也有提升。
  4. 考虑联合索引:当多个列一起被频繁查询时可考虑。
  5. 考虑索引覆盖:联合索引可通过索引覆盖来避免回表查询,可大大提升效率,对于频繁的查询,可将select后的字段和where后的条件放在一起创建联合索引。
  6. 避免创建过多索引:会占用大量磁盘空间,影响写入性能。
  7. 避免使用过长索引:索引列越长,索引效率越低。
  8. 合适的索引长度:虽不要太长,但也要合理设置。若太短,如身份证号只把前6位做索引,那可能导致大量锁冲突。

11. B+树索引、hash索引区别?

  B+树索引将索引按大小排序后存储,所以B+树更适合范围查找和排序操作;而hash索引是将索引列的值通过哈希函数计算后得到一个桶的编号,然后将桶内记录保存在一个链表或树结构中。因此,hash索引适合等值查询
  B+树索引在插入、删除数据时需调整索引结构,这个过程可能涉及页分裂和页合并等操作,因此B+树维护成本较高;而hash索引在插入删除数据时只需计算哈希值并插入或删除链表中的记录,因此hash索引的维护成本相对较低。
  B+树索引在磁盘上是有序存储的,因此进行区间查询时可利用磁盘预读的优势提高查询效率;而hash索引在磁盘上是无序存储的,因此进行区间查询时可能要随机访问磁盘,导致查询效率降低。
  B+ 树索引在节点中存储多个键值对,因此可充分利用磁盘块的空间,提高空间利用率;而哈希索引由于需要存储哈希值和指针,因此空间利用率相对较低。

12. 栈和队列的区别?

  1. 顺序:栈是先进后出,队列是先进先出
  2. 操作:栈:推入(Push)、弹出(Pop);队列:入队(Enqueue)、出队(Dequeue)。
  3. 添加和移除位置:栈:新元素总是被添加到栈顶,只能从顶部移除元素。队列:新元素总是被添加到队尾,只能从队首移除元素。
  4. 应用:栈:递归,就是用栈实现的;还有JVM中方法在执行时,也会放到栈上,因为它们的执行顺序也是遵循先进后出。队列:常作为缓冲区来用,像熟知的生产者和消费者模型,生产者完成任务后,会把数据存放到队列中,等待消费者来读取。

13. Mybatis的优点?

  MyBatis是一种持久层框架,简化了Java应用程序与关系型数据库的交互,提供了一种通过XML或注解配置的方式进行SQL映射,从而使数据库操作更灵活方便。优点:
  1. 将数据库的操作逻辑和业务逻辑解耦合,使开发者更专注于业务逻辑的处理。
  2. 开发者只用写sql就可访问数据库,不用关心各种数据库连接等额外操作。各种Connection和Statement都交给了MyBatis管理。
  3. 可将数据库表的字段按业务规则直接映射到DO层,不用再像JDBC一样需要业务代码来转换。
  4. 支持多种数据源(如POOLED,UNPOOLED,JNDI),同时,还可整合其他数据库连接池如HikariCP,Druid,C3p0等。
  5. 支持动态SQL,即根据不同条件动态生成不同的SQL语句。这使得在查询条件变化时,不需手动拼接SQL字符串,而是可通过简单的配置实现动态SQL。大大减少了代码的开发量,如if/foreach等常用的动态标签。
  6. 支持事务性的一级缓存,二级缓存和自定义缓存,其中,一级缓存是以session为生命周期,默认开启;二级缓存则是根据配置的算法来计算过期时间(FIFO,LRU等),二级缓存若操作不当易产生脏数据,不建议用。

14. Redis的作用?为什么快?

  Redis是一种内存数据库管理系统,主要用作缓存、消息队列、键值存储、计数器、分布式锁等用途。

  为什么快?

  1. 基于内存:Redis是基于内存的数据库,数据存储在内存中,数据读写速度很快,因为内存访问比传统的磁盘访问快得多。
  2. 单线程模型:Redis使用单线程处理所有命令,也就是所有操作都是在一个线程内完成的,不需进行线程切换和上下文切换,避免了线程间的竞争和锁的开销。大大提高了Redis的运行速率和响应速度。
  3. 多路复用I/O模型:Redis在单线程基础上,采用I/O多路复用技术,实现了单个线程同时处理多个客户端连接的能力,从而提高了Redis的并发性能。
  4. 高效的数据结构:Redis提供了高效的数据结构,如:哈希表、有序集合、列表等,并对每种数据结构进行了优化,如:使用hash表来存储键值对,使用跳跃表来实现有序集合,等等。这些数据结构都被实现的很高效,能在O(1)的时间复杂度内完成数据读写操作。这也是Redis能快速处理数据请求的重要原因之一。
  5. 多线程的引入:Redis 6.0中为进一步提升IO性能,引入了多线程的机制。采用多线程,使得网络处理的请求并发进行,就可大大提升性能。多线程除了可减少由于网络I/O等待造成的影响,还可充分利用CPU的多核优势。

15. Kafka的作用?为什么快?

  Kafka是一个分布式流处理平台,主要用于构建实时数据流应用程序和实时数据管道。作用:
  1. 消息传递:Kafka提供了一种高可靠性、高吞吐量的消息传递系统。生产者(Producer)可将消息发送到Kafka集群,而消费者(Consumer)可从Kafka集群中订阅并接收消息。
  2. 数据管道:Kafka可作为一个可靠的数据管道,用于连接不同的数据系统和应用程序。
  3. 日志存储:Kafka的消息被存在分布式的日志结构中,这使得它成为一个高性能的分布式日志系统。
  4. 实时数据流处理:Kafka支持实时数据流处理,可用于构建实时分析、实时监控、实施决策等应用程序。
  5. 解耦生产者和消费者:Kafka的消息传递机制实现了生产者和消费者之间的解耦。生产者和消费者间不直接通信,而是通过Kafka集群作为中介,这样生产者和消费者可独立进行扩展和升级。 
  6. 可伸缩性:Kafka是一个高度可伸缩的系统,可在需要时方便地扩展以适应不断增长的数据流量。
  7. 容错性: Kafka具有高度的容错性,通过在集群中的多个节点上复制数据,可保证在节点故障时数据不会丢失。
  8. 持久性: Kafka的消息被持久化存储,即使消费者无法立即处理消息,消息仍可被保留在Kafka中供后续处理。

  为什么快?

  Kafka是一个成熟的消息队列,以性能高著称,之所以能够实现高吞吐量和低延迟,主要是:
  1. 批量发送:Kafka将多个消息打包成一个批次,减少了网络传输和磁盘写入的次数,从而提高了消息的吞吐量和传输速率。
  2. 零拷贝技术:避免了数据的拷贝操作,降低了内存和CPU使用率,提高了系统性能。
  3. 磁盘顺序写入:避免了随机读带来的性能损耗,提高了磁盘的使用效率。
  4. 页缓存:Kafka将消息存储在磁盘中,但在访问数据时,它会先将数据加载到操作系统的页缓存中,并在页缓存中保留一份副本,从而实现快速的数据访问。
  5. 分区和副本:采用分区和副本的机制,可将数据分散到多个节点上进行处理,从而实现了分布式的高可用性和负载均衡。
  6. 高效的索引和存储结构:可快速定位和检索消息,降低了消息读取和写入的延迟。

16. 为什么要用到消息队列?

  解耦:在一个复杂的系统中,不同模块或服务间可能需相互依赖,若直接用函数调用或API调用的方式,会造成模块间的耦合,当一个模块发生改变时,需同时修改调用方和被调用方的代码。而用消息队列作为中间件,不同的模块可将消息发送到消息队列中,不知道具体的接收方是谁,接收方可独立的消费消息,实现了模块间的解耦。

  异步:有些操作较耗时,如发送邮件、生成报表等,若用同步的方式处理,会阻塞主线程或进程,导致系统的性能下降。而用消息队列,可将这些操作封装成消息,放入消息队列中,异步的处理这些操作,不影响主流程的执行,提升了系统性能和响应速度。

  削峰填谷:这是一种在高并发场景下平衡系统压力的技术。通常用于平衡系统在高峰期和低谷期的资源利用率,提高系统的吞吐量和响应速度。在削峰填谷的过程中,将消息队列作为缓冲区,将请求放入消息队列中,然后再系统负载低时进行处理。这种方式可将系统的峰值压力分散到较长的时间段内,减少瞬时压力对系统的影响,从而提高系统的稳定性和可靠性。

  还有以下优点:
  1. 可靠性高:消息队列通常具有高可靠性,可以实现消息的持久化存储、消息备份和故障恢复等功能,保证消息不会丢失。
  2. 扩展性好:通过增加消息队列实例或添加消费者实例,可实现消息队列的水平扩展,提高系统的处理能力。
  3. 灵活性高:消息队列通常支持多种消息传递模式,如点对点模式和发布/订阅模式,可根据不同业务场景选择不同模式。

16. 平时如何学习提升自己?

看书籍、听课程、写博客、读开源。

17. 开源项目是否有学习?

有。e.g. ...