淘天3.22面经解析:BAT的核心部门原来这么难

嗨~我是可拟雀,一个后端开发工程师,毕业于某985大学,目前供职于bat某大厂核心部门后端。每天分享最新面经答案,希望在大环境不好的当下能帮到你,让你多积累面试经验。需要内推或者面经合集请评论哦。

原文:

八股集合,汗流浃背,但是确实学到了很多内容,是以前没有仔细看过的。目前记起来一些,后续想起来别的了再补充 

操作系统
Linux平常使用吗
线程和进程的区别,还有什么类似进程和线程的吗
什么是协程
CPU满了怎么看,怎么办
Linux下rm正在写入的文件会发生什么?
那么该如何在不使用kill的情况下删除该文件
磁盘满了怎么看
进程状态以及特殊两种状态
僵尸线程和孤儿线程是什么
清空进程时什么进程还存活?

网络
tcp三次握手四次挥手
为什么不能两次握手
如何解决tcp包的粘连
udp和tcp的区别
udp如何变得安全

Java基础
hashmap的底层
hashmap.get之后会发生什么
什么时候链表转红黑树
什么时候红黑树降级
jmm
Jvm区域及作用
老年代常用垃圾处理算法

多线程
threadlocal有没有使用
threadlocal底层是什么(哈希表)
threadlocal底层哈希表的key是什么

数据库
两种引擎区别
事务的原理
数据库的四大特性
如何保证隔离性
隔离级别分别有哪些
MVCC有什么用
什么是死锁。如何解决
sql数据库如何解决死锁
sql锁

Spring基础
springboot运行原理
bean如何加载,循环依赖?
aop底层
了解什么设计模式
代理模式在spring哪里使用过
单例模式在spring哪里使用过
包装者模式在spring哪里使用过
接口类代理和非接口类代理的区别

中间件
redis基本类型
Redis缓存穿透,击穿,雪崩及解决方法,bitmap

项目相关

常见限流算法

答案概答:

操作系统:
线程和进程的主要区别体现在以下几个方面:

基本单位:进程是系统进行资源分配和调用的独立单位,它拥有独立的地址空间和系统资源。而线程是进程内的一个执行单元,它是CPU调度和分派的基本单位,多个线程共享父进程的地址空间。
数量与关系:一个进程至少包含一个线程,也可以包含多个线程。线程之间共享进程的资源,这使得线程间的通信更为方便和快捷。而进程之间则是相对独立的,需要通过显式机制如管道、消息队列等进行通信。
执行方式:由于线程共享进程资源,线程之间的切换开销相对较小,因此多线程并发执行时效率更高。而进程间的切换则涉及更多资源分配和回收的操作,开销较大。

除了进程和线程,协程是另一种轻量级的执行单元。协程不是进程或线程,其执行过程更类似于子例程或不带返回值的函数调用。协程的切换开销比线程更小,适用于高并发场景。

当CPU满载时,可以通过系统监控工具如top、htop等查看CPU使用情况。若CPU使用率过高,可能需要优化程序算法、减少不必要的计算或增加CPU资源。

在Linux下,如果尝试使用rm命令删除正在写入的文件,可能会导致数据丢失或损坏。因为rm命令会立即删除文件系统的引用,而正在写入的文件可能还有未写入磁盘的缓存数据。在不使用kill命令的情况下,可以尝试先停止写入进程(如通过发送信号或优雅地关闭程序),然后再删除文件。

磁盘空间使用情况可以通过df -h命令查看。如果磁盘空间已满,需要及时清理不必要的文件或扩展磁盘容量。

进程状态可以通过ps、top等命令查看。其中,僵尸线程是指子进程已经结束但父进程没有回收其资源,这可能导致资源浪费。而孤儿线程则是指父进程结束但子进程还在运行,这些子进程将被init进程(进程号为1)接管。

在清空进程时,通常系统进程和服务进程(如init、sshd等)会存活下来,因为它们负责维护系统的基本功能和安全性。

计算机网络:

TCP三次握手和四次挥手的设计是基于网络通信的可靠性和安全性考虑的,不能简化为两次握手。

TCP三次握手的主要目的是确认双方的发送和接收能力是否正常,以及初始化序列号,以保证后续数据传输的可靠性。在三次握手过程中,第一次握手由客户端发起SYN报文,第二次握手由服务端回应SYN+ACK报文,第三次握手由客户端回应ACK报文。这样的设计确保了双方都能发送和接收数据,并且初始化了序列号,为后续的数据传输做好了准备。

而TCP四次挥手的主要目的是在数据传输结束后,双方能够安全、有序地释放连接资源。在四次挥手过程中,第一次挥手由客户端发起FIN报文,第二次挥手由服务端回应ACK报文,第三次握手由服务端发起FIN报文,第四次握手由客户端回应ACK报文。这样的设计确保了数据传输的完整性和连接释放的安全性。

如果将TCP的握手和挥手过程简化为两次握手,可能会面临以下问题:

无法确保双方的发送和接收能力都正常,可能导致数据传输失败或丢失。
无法初始化序列号,使得后续的数据传输无法按序进行,导致数据混乱。
无法安全、有序地释放连接资源,可能导致资源泄露或连接状态不一致。

关于TCP包的粘连问题,一种常见的解决方案是采用定长发送的方式。也就是说,在发送数据时,将数据分包为固定长度的数据包进行发送。接收方在接收数据时,也按照固定的长度进行接收。这样,发送和接收就能一一对应,从而解决TCP包的粘连问题。但这种方法可能会引入一些额外的开销,比如在数据包长度不足固定长度时需要进行填充。

UDP和TCP的主要区别体现在以下几个方面:

连接性:UDP是无连接的协议,每个数据包都是独立的,发送端和接收端之间没有建立持久的连接。而TCP在数据传输前会建立一个可靠的连接,数据传输完成后再断开连接。
可靠性:TCP提供可靠的数据传输,通过序号、确认和重传机制,确保数据按顺序、完整地传输到目的地。而UDP不提供可靠性保证,数据包可能会丢失或乱序。
流量控制和拥塞控制:TCP支持流量控制和拥塞控制,以防止网络拥塞和数据丢失。而UDP不提供这些功能。

要使UDP变得安全,可以考虑以下几种方法:

实现多路径传输:通过利用多个网络路径同时进行文件传输,分散数据流量,避免单一路径的拥堵问题,提高UDP协议的传输速度和稳定性。
应用数据重传机制:当接收端收到不完整的数据时,可以请求发送端重新发送丢失的数据段,保证数据的完整性和可用性。
加入安全认证机制:通过使用加密算法和数字签名等技术,保证数据信息的机密性和完整性,防止黑客攻击和数据泄露。

java基础

1. HashMap的底层实现

HashMap的底层实现主要依赖于数组和链表(在Java 8及以后版本中,当链表长度超过一定阈值后会转为红黑树),以及一个计算哈希值的函数。每个HashMap对象内部都有一个Node数组(Node<K,V>[] table),数组的每个元素是一个链表。当向HashMap中添加元素时,首先根据key的哈希值计算出其在数组中的索引位置,然后将该元素添加到对应索引位置的链表中。

2. HashMap.get()之后会发生什么

当调用HashMap的get()方法时,首先会根据key的哈希值计算出在数组中的索引位置,然后遍历该索引位置处的链表或红黑树,查找与给定key相等的元素。如果找到了,就返回对应的value;否则返回null。

3. 什么时候链表转红黑树

在Java 8及以后的版本中,当HashMap中的某个桶(bucket)的链表长度达到一定的阈值(TREEIFY_THRESHOLD,默认为8)时,链表会转换为红黑树。这样做的目的是为了优化性能,因为在链表较长时,查找元素的时间复杂度是O(n),而红黑树的查找时间复杂度为O(log n)。

4. 什么时候红黑树降级

当HashMap中的某个桶的红黑树节点数少于一定的阈值(UNTREEIFY_THRESHOLD,默认为6)时,红黑树会退化为链表。此外,在HashMap进行resize(扩容)时,即使桶中的节点数大于UNTREEIFY_THRESHOLD,也会将红黑树退化为链表,然后再重新计算索引位置并插入。

5. JMM(Java内存模型)

Java内存模型(Java Memory Model, JMM)定义了Java虚拟机(JVM)中多线程程序并发访问共享变量时的内存可见性、原子性和有序性问题。JMM通过Happens-Before规则来定义操作的可见性,确保多线程环境下的数据一致性。

6. JVM区域及作用

JVM(Java虚拟机)的内存区域主要包括以下几个部分:

方法区:存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
堆:所有线程共享的一块内存区域,用于存放对象实例。根据对象的生命周期不同,堆内存可以细分为新生代和老年代。新生代又可以分为Eden区和两个Survivor区(S0和S1)。
栈:每个线程都有一个私有的栈,用于存储局部变量和方法的执行过程。栈中的每个元素称为栈帧,每个方法执行时都会创建一个新的栈帧。
程序计数器:一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。
本地方法栈:与Java栈类似,但它是为Native方法服务的。
7. 老年代常用垃圾处理算法

老年代中常用的垃圾处理算法主要有标记-清除和标记-整理两种。

标记-清除:首先标记出所有需要回收的对象,然后统一回收所有被标记的对象。这种方法效率较高,但会产生内存碎片。
标记-整理:首先标记出所有需要回收的对象,然后让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。这种方法不会产生内存碎片,但效率相对较低。

JVM的垃圾回收算法并不局限于这两种,还有复制算法、分代收集算法等,它们会根据不同的使用场景进行优化和选择。

多线程:

ThreadLocal 的底层实现并不直接是一个哈希表(HashTable)。ThreadLocal 的实现涉及到了每个线程内部的 ThreadLocalMap。这个 ThreadLocalMap 是一个定制化的、用于存储线程局部变量的数据结构。每个 Thread 对象都持有一个 ThreadLocalMap 的引用,用于存储该线程特有的 ThreadLocal 变量。

ThreadLocalMap 的内部实现,它确实使用了哈希表的概念,但并不是标准的 java.util.HashTable 或 java.util.HashMap。它是专门为 ThreadLocal 设计的,具有一些特定的优化和特性。

在 ThreadLocalMap 中,key 是 ThreadLocal 的弱引用(WeakReference),而 value 是与之关联的线程局部变量值。弱引用的使用是为了允许 ThreadLocal 对象在不再被强引用时能够被垃圾回收,即使它的值(即 ThreadLocalMap 中的 entry)仍然存在。这是为了避免内存泄漏,因为线程可能会长时间存活,而 ThreadLocal 可能只在某个特定的代码块或任务中使用。

ThreadLocal 底层并不是直接一个哈希表。
ThreadLocalMap 内部使用了类似哈希表的结构来存储键值对。
在这个“哈希表”中,key 是 ThreadLocal 的弱引用。

虽然 ThreadLocalMap 的实现使用了哈希表的概念,但它并不是 java.util 包下提供的标准哈希表实现。它是专门为 ThreadLocal 的需求而定制的。

数据库

以下是关于两种引擎区别、事务的原理、数据库的四大特性、隔离性的保证、隔离级别、MVCC的作用、死锁的定义与解决,以及SQL数据库中的锁和死锁解决方案的详细解释:

一、两种引擎区别

通常这两种引擎指的是InnoDB和MyISAM,它们在许多方面存在差异:

事务处理:InnoDB支持事务处理,而MyISAM不支持。事务是一种高级的处理方式,它确保了一组操作的原子性,即要么全部执行,要么全部不执行。
外键支持:InnoDB支持外键,而MyISAM不支持。
全文索引:MyISAM支持FULLTEXT类型的索引,而InnoDB不支持。
行数统计:InnoDB不保存表的行数,需要扫描整个表来计算行数,而MyISAM可以简单地读出保存好的行数。
自增长字段:在InnoDB中,自增长字段必须包含只有该字段的索引,而在MyISAM中,它可以和其他字段一起建立联合索引。

二、事务的原理

事务是并发控制的单位,是用户定义的一个操作序列。这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务通常是以BEGIN TRANSACTION开始,以COMMIT或ROLLBACK结束。COMMIT表示提交,即将事务中所有对数据库的更新写回到磁盘上的物理数据库中去,事务正常结束。ROLLBACK表示回滚,即在事务运行的过程中发生了某种故障,系统将事务中对数据库的所有已完成的操作全部撤消,滚回到事务开始的状态。

三、数据库的四大特性

数据库的四大特性是ACID,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。

原子性:整个事务是不可分割的,要么全部执行,要么全部不执行。
一致性:事务的执行结果要与业务的逻辑保持一致。
隔离性:多个事务之间隔离开来,互不影响。
持久性:一旦事务执行完毕,执行后的结果会永久的保存下来。

四、如何保证隔离性

数据库的隔离性主要通过锁机制和多版本并发控制(MVCC)技术来实现。锁机制可以防止多个事务同时修改同一数据,而MVCC则通过保存数据的多个版本来实现无锁或低锁的并发访问。

五、隔离级别分别有哪些

InnoDB支持的隔离级别有四种,从低到高分别为:读未提交、读已提交、可重复读和串行化。

六、MVCC有什么用

MVCC(Multiple Version Concurrency Control)的主要作用是解决读-写和写-写冲突,使得大多数读操作不用加锁,从而提高了并发性能。通过保存数据的多个版本来实现并发访问,避免了读操作之间的锁竞争。

七、什么是死锁

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

八、如何解决死锁

解决死锁的方法主要有以下几种:

预防死锁:通过一次性分配所有资源、按序请求资源等方式来预防死锁的发生。
避免死锁:通过银行家算法等来判断并避免系统进入不安全状态,从而避免死锁。
检测与解除死锁:定期检测系统中是否发生死锁,一旦发生死锁,则采取解除死锁的措施。解除死锁通常涉及撤销一些进程,以便回收它们的资源,从而使得其他进程能够继续执行。

九、sql数据库如何解决死锁

在SQL数据库中,解决死锁的方法通常包括:

设置合理的锁超时时间:当尝试获取锁超过设定的时间后,放弃锁请求,避免长时间等待导致死锁。
优化事务设计:尽量减小事务的大小和持续时间,减少锁的持有时间,从而降低死锁的风险。
避免在事务中执行用户输入:用户输入可能导致不可预测的行为,增加死锁的风险。
使用低隔离级别:如果可能,使用较低的隔离级别,以减少锁的需求和冲突。
定期监控和诊断:使用数据库提供的工具和日志来定期监控和诊断死锁情况,及时发现并解决潜在问题。

十、sql锁

SQL中的锁主要用于控制并发访问,保证数据的完整性和一致性。SQL锁主要分为共享锁和排他锁。共享锁允许多个事务同时读取同一资源,而排他锁则阻止其他事务对同一资源进行读取或修改。此外,根据锁定的粒度,还可以分为行级锁、页级锁和表级锁等。不同的数据库管理系统和存储引擎可能会有不同的锁实现和策略。

spring相关

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,它主要用于简化企业级应用的开发。
Spring的核心功能包括IoC容器和AOP,它们分别用于管理对象之间的依赖关系和实现横切关注点(如日志、事务等)。
Spring支持声明式事务管理,通过注解或XML配置即可轻松实现事务的控制。
Spring还提供了丰富的数据访问支持,包括JDBC、Hibernate、MyBatis等集成。

Spring Boot运行原理:
Spring Boot的设计目的是简化Spring应用的初始搭建以及开发过程。它提供了大量的默认配置,使得开发者可以快速启动和运行Spring应用。

Spring Boot的运行原理主要基于自动配置和起步依赖。自动配置会根据项目的类路径和依赖关系自动为应用提供默认的设置和功能;而起步依赖则是一组预定义的依赖关系,用于简化项目中所需库和框架的导入过程。

Bean的加载与循环依赖:
在Spring容器中,Bean的加载过程包括解析配置文件或注解、创建Bean实例、注入依赖等步骤。

循环依赖是指两个或多个Bean相互依赖对方,形成一个闭环。Spring通过三级缓存机制来解决循环依赖问题。一级缓存存储成品对象,二级缓存存储半成品对象(已实例化但未完全初始化),三级缓存存储ObjectFactory用于解决代理对象的循环依赖。

AOP底层实现:
Spring AOP的底层实现主要基于动态代理技术。对于接口代理,Spring使用JDK动态代理;对于非接口类代理,Spring使用CGLIB库来实现。动态代理允许在运行时创建代理对象,并将横切关注点织入到目标对象的方法执行过程中。
设计模式在Spring中的应用:

单例模式:在Spring中,默认情况下Bean是单例的,即在整个Spring IoC容器中只创建一个Bean实例。

工厂模式:Spring使用BeanFactory和ApplicationContext作为工厂来创建和管理Bean对象。

代理模式:在Spring AOP中,代理模式被用于实现面向切面的编程。Spring通过动态代理为目标对象创建代理对象,并在代理对象上织入横切关注点。

包装者模式(装饰器模式):在Spring中配置DataSource时,可能会使用到装饰器模式。当需要连接多个数据库时,可以根据需求切换不同的数据源。

代理模式在Spring中的使用:
在Spring AOP中,代理模式被广泛应用。Spring通过创建代理对象来增强目标对象的功能,实现横切关注点的织入。无论是JDK动态代理还是CGLIB代理,都是代理模式在Spring中的具体实现。

接口类代理和非接口类代理的区别:
接口类代理通常指的是JDK动态代理,它要求被代理的对象必须实现一个或多个接口。JDK动态代理通过反射机制在运行时创建接口的代理实例。

非接口类代理则是指CGLIB代理,它不需要被代理的对象实现接口。CGLIB通过继承被代理的类来创建子类作为代理对象,因此可以代理没有实现接口的类。

redis相关

Redis是一个开源的使用ANSI C语言编写的、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。以下是关于Redis基本类型、缓存穿透、击穿、雪崩及解决方法和bitmap的详细解释:

Redis基本类型:

Redis支持五种基本数据类型,分别是:

String:字符串类型,是Redis最基本的数据类型,可以存储任何类型的数据,包括字符串、数字和二进制数据等。

List:列表类型,是一种有序的字符串列表,可以在头部或尾部添加元素。

Set:集合类型,是一组无序、唯一的字符串集合,可以对集合进行并、交、差等集合运算。

Hash:哈希类型,类似于Map的一种结构,key-value存储。

Sorted Set:有序集合类型,与Set一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。Redis正是通过分数来为集合中的元素进行从小到大的排序。

Redis缓存穿透、击穿、雪崩及解决方法:

缓存穿透:
描述:客户端请求的数据在缓存和数据库中都不存在,导致缓存永远不会生效,请求都被打到数据库。
解决方法:
主动方案:增加id复杂度,避免被猜测到id规律;做好数据基础格式校验;加强用户权限校验;做好热点参数的限流。
被动方案:缓存空对象,并为其设置一个TTL。但这种方法可能会有额外内存消耗,并可能造成短期的不一致。

缓存击穿:
描述:缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
解决方法:设置热点数据永不过期;定时更新;使用互斥锁或布隆过滤器等方法。

缓存雪崩:
描述:缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
解决方法:保持缓存层的高可用;缓存不过期;优化缓存过期时间;使用互斥锁重建缓存等。

Redis的Bitmap:

Bitmap是一个通过最小的单位bit来进行0或1的设置,用来记录每一个元素对应的值或者状态。Redis的bitmap不是一种新的数据结构,而是基于String类型实现的位操作功能。Bitmap的常见应用场景包括日活统计、用户签到、统计独立用户数(UV)等。

限流算法:

常见的限流算法主要有以下几种:

计数器算法:

计数器算法是限流算法中最简单也最容易实现的一种。
它通过对每个请求进行计数,当计数器的值超过设定的阈值时,触发限流策略。
但这种算法存在临界问题,特别是在周期切换时,如果大量请求集中在周期末尾涌入,可能会导致限流失效。

滑动窗口算法:

滑动窗口算法是对计数器算法的一种改进,通过动态调整时间窗口来解决临界问题。
它将时间划分为多个固定大小的窗口,并分别对每个窗口内的请求进行计数。
当某个窗口内的请求数超过阈值时,触发限流策略。

漏桶算法:

漏桶算法基于时间的概念,将数据流想象成一个有固定容量的桶。
当数据流进入桶时,如果桶未满,则数据被保留在桶中;如果桶已满,则新的数据会被丢弃或延迟处理。
数据以一定的速率从桶中流出,从而控制整体的速率。

令牌桶算法:

令牌桶算法是另一种常见的限流算法,它通过模拟一个固定容量的桶和一定数量的令牌来实现。
每个令牌代表一个请求的处理权限。请求到达时,如果桶中有令牌可用,则获取令牌并处理请求;否则,请求被拒绝或延迟处理。
令牌以一定的速率添加到桶中,当桶满时,新的令牌会被丢弃。

令牌漏斗算法:

令牌漏斗算法结合了漏桶和令牌桶的概念。
它将数据流想象成一个漏斗,每个时间间隔内漏斗会积累一定数量的令牌。
请求到达时,需要获取令牌才能被处理。如果令牌不足,请求被拒绝或延迟。

分布式令牌桶算法:

在分布式环境中,多个服务器可能需要共享限流策略。
分布式令牌桶算法允许多个服务器共同维护一个令牌桶,通过共享令牌来控制整个系统的流量。


大厂校招实习最新面经解析 文章被收录于专栏

专注于最新各大厂最新面筋解析

全部评论
怎么会问这么多
点赞 回复
分享
发布于 03-25 17:22 广东

相关推荐

#软件开发2024笔面经#客户运营部门(1h50min,&nbsp;电话面,发了手撕邮件)1、通过什么途径了解Java?2、什么方式学习Java?3、为什么想去学习Java,为什么想做后端开发?4、你与科班相比有什么优势?5、介绍项目,介绍重难点。6、有没有单机部署,压测数据多少?7、你认为项目中还有哪些可以优化的点?8、Redis的架构(我答的数据结构,&nbsp;主从复制,&nbsp;哨兵,cluster)9、讲一下跳表10、redis扩容的过程?11、redis扩容有哪些问题需要解决?12、hash的优势?13、如何处理hash数量过大,&nbsp;渐进式rehash?14、rocketMQ如何做到不丢失?15、如何做幂等控制?16、订单创建成功,支付,如何保证请求可靠17、什么适合做唯一标识?18、uuid是什么时机生成的?19、项目中怎么实现的最终一致性?20、讲讲其他解决缓存一致性的方案?(我答的延迟双删和先写数据库再删缓存)21、如果是实时性要求比较高的场景,用哪种一致性方案?22、两个微服务之间如何实现缓存一致性?(分布式事务2PC,&nbsp;没了解过)23、讲讲项目中布隆过滤器的使用,底层原理,常用的场景?24、讲讲项目中订单的项目业务25、如何保证乘车人表和订单表数据的一致性?(分布式事务&nbsp;没了解过)26、讲讲项目中订单相关的流程?27、讲讲雪花算法及组成,缺点及解决方案?组成中数据中心号和机器标识码的含义,各占多少bit(我引申到了美团分布式框架Leaf)28、数据库的ACID?29、MySQL如何保证事务不丢失?二阶段提交,如果宕机了如何处理?30、MQ的事务消息有了解吗?【算法】LC&nbsp;3限流相关代码题一道总结:分布式相关内容有所欠缺
点赞 评论 收藏
转发
9 85 评论
分享
牛客网
牛客企业服务