【2025最新面经】暑期实习常问知识点
问题集来自:暑期后端高频问题汇总_牛客网
关于各问题的详细解答
一、计算机网络
1. TCP三次握手四次挥手
三次握手:
-
客户端发送SYN=1, seq=x;(client向server发送syn,seq=x,此时client验证client发送能力正常。client置为SYN_SENT状态)
-
服务端回复SYN=1, ACK=1, seq=y, ack=x+1(server收到syn,此时server验证client发送能力正常,server接收能力正常。server向client发送ack = x + 1,seq = y,此时server验证server发送能力正常。server置为SYN_RCVD状态)
-
客户端发送ACK=1, seq=x+1, ack=y+1(client收到ack,此时client验证client接收能力正常,server接收发送能力正常。client向server发送ack = y + 1, seq = x + 1,server接收到后验证client接收能力正常。client置为ESTABLISHED状态)
为什么三次:防止已失效的连接请求报文突然到达服务器,造成资源浪费。如果是两次握手,服务端无法确定客户端是否已经接收到了自己发送的初始序列号,如果第二次握手报文丢失,那么客户端就无法知道服务端的初始序列号,那 TCP 的可靠性就无从谈起。 -
客户端由于某种原因发送了两个不同序号的 SYN 包,我们知道网络环境是复杂的,旧的数据包有可能先到达服务器。如果是两次握手,服务器收到旧的 SYN 就会立刻建立连接,那么会造成网络异常。
如果是三次握手,服务器需要回复 SYN+ACK 包,客户端会对比应答的序号,如果发现是旧的报文,就会给服务器发 RST 报文,直到正常的 SYN 到达服务器后才正常建立连接。
所以三次握手才有足够的上下文信息来判断当前连接是否是历史连接。
四次挥手:
-
主动方发送FIN=1(client向server发送fin。client置为FIN_WAIT_1)
-
被动方回复ACK(server向client发送ack。server置为CLOSE_WAIT,client置为FIN_WAIT_2)
-
被动方发送FIN=1(等server传输数据完毕后,向client发送fin。server置为LAST_ACK)
-
主动方回复ACK。(client向server发送ack。client置为TIME_WAIT。之后等待2MSL,client关闭。server接收到后置为CLOSED)
为什么四次:TCP是全双工协议,需要双方独立关闭通道。对于四次挥手,因为 TCP 是全双工通信,在主动关闭方发送 FIN 包后,接收端可能还要发送数据,不能立即关闭服务器端到客户端的数据通道,所以也就不能将服务器端的 FIN 包与对客户端的 ACK 包合并发送,只能先确认 ACK,然后服务器待无需发送数据时再发送 FIN 包,所以四次挥手时必须是四次数据包的交互。
2. TIME_WAIT状态
作用:
-
确保最后的ACK到达
-
让旧连接的报文在网络中消失
2MSL原因:足够时间确保最后一个ACK丢失后能重传(MSL=Maximum Segment Lifetime)
现代变化:Linux可通过sysctl调整net.ipv4.tcp_fin_timeout
(默认60s)
3. TCP重传机制
基本流程
-
发送数据包:发送方发送数据包并启动重传定时器(Retransmission Timer)。
-
等待 ACK:若在超时时间(RTO, Retransmission Timeout)内收到 ACK,取消定时器。
-
超时重传:若超时未收到 ACK,重传数据包并重置定时器(可能加倍 RTO)。
超时重传:基于RTT(发送数据包到收到ack的时间)动态计算重传超时时间(RTO(动态计算的超时阈值。))
SACK(选择性确认):
-
机制:接收方通过 SACK 选项告知发送方已接收的非连续数据块。
-
作用:允许发送方仅重传丢失的报文段,避免冗余重传。
-
格式
TCP Header Option: Kind=5 (SACK), Length=10, Left Edge=1001, Right Edge=2001
//表示接收方已正确接收 1001-2001 的数据。
struct tcp_sack_block {u32 start_seq;u32 end_seq; }; // 标记接收到的数据块范围
HPACK(HTTP/2头部压缩)前向确认:
-
结合 SACK 信息,计算网络中未被确认的最大序列号。
-
作用:更精确地判断丢包,优化重传决策。
-
静态字典(61个常用头部)
-
动态字典(维护在连接生命周期内)
-
Huffman编码
快速重传(Fast Retransmit)
-
触发条件:收到 3 个重复 ACK(DupACK)。
-
操作:立即重传丢失的报文段,无需等待超时。
-
优势:显著减少等待时间,提升传输效率
示例: 发送方发送 Seq=1,2,3,4,5 接收方收到 1,3,4,5 → 返回 3 个 ACK=2 发送方检测到 3 个 DupACK=2,立即重传 Seq=2
当发生超时重传时,TCP 认为网络出现严重拥塞,会触发:
-
拥塞窗口(cwnd)重置为 1 MSS。
-
进入慢启动阶段,重新探测可用带宽。
-
若使用快速恢复(如 NewReno),在快速重传后保持部分窗口。
4. 拥塞控制
慢启动:cwnd指数增长(每RTT翻倍) 在TCP刚连接好,开始发送TCP报文段时。或网络发生拥塞后,TCP会从比较小的发送速率开始。慢启动机制逐步增加拥塞窗口(Congestion Window,简称cwnd),即发送方每次可以发送的最大数据量,以避免瞬时向网络注入过多数据。●初始时,cwnd通常设为1个MSS(最大报文段大小)。 ●每收到一个ACK,cwnd增加1个MSS。 ●通过指数级增长,慢启动会迅速增加发送速率,直到达到阈值(ssthresh)或发生丢包。 拥塞避免:cwnd线性增长(每RTT +1) 当cwnd达到慢启动阈值(ssthresh)后,TCP进入拥塞避免阶段。此时,数据发送速率的增长变为线性,以更小的步伐增加,避免引发拥塞。 快速重传:收到3个重复ACK时触发 当发送方收到三个连续的相同ACK时,它会立即重传该丢失的数据包,而不必等待超时。这就是快重传 快速恢复:cwnd = ssthresh + 3,进入拥塞避免
将ssthresh设置为cwnd的一半,同时将cwnd设为ssthresh加上三个MSS(对应三次重复ACK)。
之后,TCP继续以线性增长的方式调整发送窗口,直到恢复正常的传输速率。
5. HTTP/2 vs HTTP/3
可以看我的其他文章
【2025最新面试八股常问知识点】HTTP1.0,HTTP1.1,HTTP2.0,HTTP3.0,HTTP的进化之路。-CSDN博客
HTTP/2:
-
二进制分帧
-
头部压缩(HPACK)
-
多路复用
-
服务器推送
HTTP/3:
-
基于QUIC协议(UDP实现)
-
0-RTT或1-RTT连接建立
-
改进的拥塞控制
-
无队头阻塞
二、操作系统
1. 进程通信方式
方式 | 特点 | 使用场景 |
---|---|---|
管道 | 单向字节流 | 父子进程简单通信 |
消息队列 | 结构化数据 | 跨进程结构化通信 |
共享内存 | 无需复制数据 | 高性能数据共享 |
信号量 | 计数器同步 | 资源访问控制 |
Socket | 跨网络通信 | 分布式系统 |
2. Linux页式内存管理
优点:
-
支持虚拟内存
-
内存分配灵活(4KB页)
-
支持写时复制(Copy-on-Write)
-
页表多级缓存(TLB加速)
3. I/O多路复用对比
详细可以看看这个
【2025最新Java八股】redis中io多路复用怎么回事,和多线程的关系-CSDN博客
select | poll | epoll | |
---|---|---|---|
时间复杂度 | O(n) | O(n) | O(1) |
最大连接数 | FD_SETSIZE(1024) | 无限制 | 百万级 |
工作模式 | 轮询 | 轮询 | 回调 |
内存拷贝 | 每次调用拷贝fd集合 | 同select | 内核维护红黑树 |
4. 零拷贝技术
详细可以看看这个
操作系统之零拷贝原理和实现方式_rttos中streambuffer的零拷贝怎么实现的-CSDN博客
mmap:
void *addr = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0);
sendfile:
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
应用案例:
-
Kafka:sendfile + PageCache
-
RocketMQ:mmap + 文件预热
三、MySQL
1. InnoDB存储结构
B+树特点:
-
叶子节点形成双向链表
-
非叶子节点只存键值
-
每个节点16KB(innodb_page_size)
2. B+树优势
-
范围查询高效(叶子节点链表)
-
树高更低(每个节点存储更多键)
-
适合磁盘预读(局部性原理)
3. 索引优化
覆盖索引:
-- 使用联合索引(a,b) SELECT b FROM table WHERE a = 1; -- 无需回表
索引下推:
WHERE a > 10 AND b = 5 -- 在存储引擎层过滤b=5
4. RR隔离级别防幻读
-
Next-Key Lock:锁定记录+间隙
-
ReadView:维护活跃事务ID列表
-
快照读(MVCC)+当前读(锁)配合
5. 主从复制
模式 | 数据一致性 | 性能 |
---|---|---|
异步 | 弱 | 高 |
半同步 | 较强 | 中 |
全同步 | 强 | 低 |
四、Redis
【2025面试Java常问八股之redis】zset数据结构的实现,跳表和B+树的对比-CSDN博客
1. ZSet实现
跳跃表:
struct zskiplistNode {sds ele;double score;struct zskiplistNode *backward;struct zskiplistLevel {struct zskiplistNode *forward;unsigned int span;} level[]; };
压缩列表(元素<128字节且数量<512时使用)
2. 分布式锁
-- 原子获取锁 if redis.call('setnx', KEYS[1], ARGV[1]) == 1 thenredis.call('expire', KEYS[1], ARGV[2])return 1 end
注意事项:
-
设置唯一value防误删
-
使用Redlock算法保证强一致
-
自动续期防止业务未完成锁过期
3. 持久化机制
AOF重写:
-
原理:根据内存数据重建命令
-
触发条件:auto-aof-rewrite-percentage 100%(增长100%触发)
RDB Copy-on-Write:
-
fork子进程时共享内存
-
父进程修改数据时复制内存页
五、Java
1. HashMap原理
JDK8改进:
-
数组+链表/红黑树(链表长度>8转树)
-
hash计算优化:
static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
2. ConcurrentHashMap
JDK8实现:
-
Node数组+链表+红黑树
-
CAS+synchronized锁细化
-
sizeCtl控制并发扩容
3. synchronized原理
字节码层面:
monitorenter // 代码逻辑 monitorexit
锁升级过程:
无锁 → 偏向锁 → 轻量锁 → 重量锁
4. G1 vs CMS
G1 | CMS | |
---|---|---|
算法 | 标记整理+复制 | 标记清除 |
停顿时间 | 可预测 | 不可预测 |
内存碎片 | 无 | 有 |
适用场景 | 大堆 | 中小堆 |
六、消息队列
1. 消息不丢失保障
生产者:
-
事务消息
-
同步刷盘(SYNC_MASTER)
Broker:
-
同步刷盘(flushDiskType=SYNC_FLUSH)
-
主从同步(SYNC_MASTER)
消费者:
-
手动ACK(业务处理完成后提交)
2. 顺序消费
RocketMQ方案:
-
相同sharding key的消息路由到同一队列
-
消费端单线程处理队列
3. RocketMQ事务消息
生产者->Broker: 发送半消息 Broker->生产者: 存储半消息 生产者->本地事务: 执行事务 本地事务->生产者: 返回执行结果 生产者->Broker: Commit/Rollback Broker->消费者: 投递可见消息
七、场景设计题
配置中心设计
推拉结合模式:
-
客户端长轮询(默认30s)
-
配置变更时服务端主动推送
-
降级策略:本地缓存+定期校验
双Buffer设计:
class ConfigBuffer {AtomicReference<Map<String, String>> active = new AtomicReference<>();AtomicReference<Map<String, String>> standby = new AtomicReference<>();void update() {Map<String, String> newConfig = loadFromDB();standby.set(newConfig);active.set(standby.get());} }
关键技术点:
-
版本号比对(etag机制)
-
增量更新(diff patch)
-
灰度发布(按机器分组推送)