问了十五分钟 撕了10分钟

TIME_WAIT状态发生阶段

TIME_WAIT状态过多连接会有什么问题

TCP的连接构成(四元组五元组是什么)

比如说这种连接过多的话、会导致除了内存和CPU还有什么样的资源问题

Linux里面的端口数有没有限制 是否可以无上限

怎么看在历史里面怎么去看网络连接呢

网络连接查看指令

怎么去看他那种TIME_WAIT的那种网络连接

怎么去用指令去查看这台机器上面它的连接的个数、用什么样的指令

Redis的基本数据类型

缓存三兄弟

MySQL建立索引的原则(我回答的是什么字段适合加索引

如何定位慢查询

像CPU使用率跟CPU负载这两个有什么区别

你对CPU的使用率怎么看的呢

算法:

最长有效括号(hard

1.TIME_WAIT状态发生阶段

发生在TCP四次挥手的四次挥手的时候

分析:

第四次挥手: 客户端收到服务端的FIN报文后、回一个ACK应答报文、确认收到了服务端的关闭请求。 客户端进入TIME_WAIT状态。

参考回答:

当TCP连接的主动关闭方关闭连接、与被动关闭方进行了四次挥手的时候、在主动关闭方发送完第四次挥手后、也就是最后一个 ACK 报文后、主动关闭方的 TCP 连接就会进入到 TIME_WAIT 状态

这个状态会持续 2MSL的时长、以确保对方已经收到了最后一个 ACK 报文

2.为什么 TIME_WAIT 状态要等待 2MSL

解析:

1.可靠地终止 TCP 连接:

  1. 在主动关闭连接的一方(通常是客户端)发送最后一个 ACK 报文后、进入 TIME_WAIT 状态。

  2. 这个 ACK 报文可能因为网络原因丢失。如果 ACK 丢失、被动关闭的一方(服务器)会重传 FIN 报文。

  3. TIME_WAIT 状态的存在、使得主动关闭方可以重新发送 ACK 报文、确保被动关闭方能够收到 FIN 报文的确认,从而可靠地关闭连接。

  4. 如果主动关闭方不等待 TIME_WAIT、直接关闭连接、那么它就无法重传 ACK 报文、导致被动关闭方无法正常关闭连接、可能会出现连接半开的状态。

2.避免新连接收到旧连接的数据:

  1. TCP 报文在网络中可能因为各种原因延迟到达,甚至在连接关闭后才到达。

  2. MSL 表示 TCP 报文在网络中最大的存活时长。等待 2MSL 确保了:

    • 两个方向的报文都消失: 一个 MSL 保证了从主动关闭方发出的最后一个 ACK 报文在网络中消失,另一个 MSL 保证了从被动关闭方重传的 FIN 报文在网络中消失。

    • 避免旧连接的报文干扰新连接: 如果新的连接使用相同的 IP 地址和端口号,那么旧连接的延迟到达的报文可能会被新连接错误地接收,导致数据混乱。等待 2MSL 可以确保旧连接的所有报文都从网络中消失,从而避免这种情况发生。

解析:

  • 主动关闭方发送的最后一个 ACK 报文: 这个报文需要一个 MSL 的时间在网络中消失。

  • 被动关闭方可能重传的 FIN 报文: 如果主动关闭方发送的 ACK 报文丢失、被动关闭方会重传 FIN 报文、这个重传的 FIN 报文也需要一个 MSL 的时间在网络中消失。

防止历史连接的重复数据包干扰新的连接

  • 网络环境的复杂性: 网络环境是复杂的、数据包可能会因为各种原因(路由变化、拥塞等)延迟到达、甚至被复制。

  • 连接复用: TCP 协议允许在短时间内复用相同的端口号对(源 IP 地址、源端口、目的 IP 地址、目的端口)建立新的连接。

  • 问题: 如果一个连接关闭后立即使用相同的端口号对建立新的连接、那么之前连接中延迟到达的数据包可能会被新的连接接收、导致数据混乱或错误。

  • 2MSL 的作用: 2MSL (Maximum Segment Lifetime) 是 TCP 报文在网络中存活的最长时间。 等待 2MSL 确保了:

    • 所有来自旧连接的数据包都已过期并从网络中消失。 即使有延迟的数据包、也肯定会在 2MSL 时间内到达或被丢弃。

    • 新的连接不会接收到旧连接的数据包

    • 来自旧连接的数据包会被丢弃。 这是 TIME_WAIT 状态的主要目的之一、防止旧连接的数据包干扰新连接。 判断是否是旧连接的数据包、主要是通过序列号和确认号来判断。 如果数据包的序列号在旧连接的范围内、或者确认号是旧连接期望的、那么就会被认为是旧连接的数据包而被丢弃。

参考回答:

我的理解主要有两个原因:

  • 2MSL 的作用: 2MSL (Maximum Segment Lifetime) 是 TCP 报文在网络中存活的最长时间。 等待 2MSL 确保了:

  • 第一个原因、主要是为了避免本次连接的历史报文、被新的连接接收到这些历史报文、从而导致出错。MSL 表示 TCP 报文在网络中最大的存活时长、等待 2MSL 就可以让两个方向的报文可以在网络中自然消失、 一个 MSL 保证了从主动关闭方发出的最后一个 ACK 报文在网络中消失、另一个 MSL 保证了从被动关闭方重传的 FIN 报文在网络中消失、这样新的连接就不会接收到历史报文了。

  • 第二个原因、是为了确保第四次挥手 ACK 报文能被接收、从而帮助被动关闭方正常关闭连接。如果主动关闭方的第四次挥手的 ACK 报文丢失了、由于被动关闭方没有收到这个 ACK 报文、被动关闭方它会超时重传 FIN 包、主动关闭方 TIME_WAIT 状态等待期间会重新发送 ACK 报文、如果没有 TIME_WAIT 状态、那么就没办法重新发送 ACK 报文、也就没办法帮助被动关闭方正常关闭连接了。

以上就是我对 TIME_WAIT 状态的理解。

3.TIME_WAIT状态过多连接会有什么问题

分析

过多的 TIME-WAIT 状态主要的危害有两种:

  • 第一是占用系统资源、比如文件描述符、内存资源、CPU 资源、线程资源等;

  • 第二是占用端口资源、端口资源也是有限的、一般可以开启的端口为 32768~61000、也可以通过 net.ipv4.ip_local_port_range 参数指定范围。

客户端和服务端 TIME_WAIT 过多、造成的影响是不同的

所以要从客户端过多 TIME_WAIT 状态和服务端过多 TIME_WAIT 状态来回答。

深度解析:

如果客户端(主动发起关闭连接方)的 TIME_WAIT 状态过多:

客户端的 TIME_WAIT 状态过多、占用了端口、端口是有数据限制的、最大的是 65535

连接四元组: TCP连接由四元组唯一确定:(源IP, 源端口, 目的IP, 目的端口)。

血的教训我当时不记得了😭😭😭😭😭😭 💪 💪 💪 💪 💪 💪

只要连接的是不同的服务器端、端口是可以重复使用的、所以客户端还是可以向其他服务器端发起连接的、这是因为内核在定位一个连接的时候、是通过四元组(源IP、源端口、目的IP、目的端口)信息来定位的、并不会因为客户端的端口一样、而导致连接冲突。

也就是说

  • 连接目标相同: 只有当客户端需要连接到相同的服务器(相同的IP地址和端口号)时、TIME_WAIT过多才会成为问题。

  • 连接目标不同: 如果客户端连接到不同的服务器(例如、10.0.0.1:80、10.0.0.2:80、10.0.0.3:80)即使客户端端口号相同、也不会发生冲突。因为连接四元组是不同的。

参考回答

客户端和服务端 TIME_WAIT 过多、造成的影响是不同的。

如果客户端(主动发起关闭连接方)的 TIME_WAIT 状态过多:

就会占满了所有端口资源、端口是有数据限制的、那么就无法对「目的 IP+目的 PORT」都一样的服务器发起连接了、但是被使用的端口还是可以继续对另外一个服务器发起连接的。在四元组确定一个TCP连接的场景下、只有客户端端口的端口号是变量、其他三个都是固定的、那么随着 time_wait 连接越多、占用的端口号就越多、客户端的端口号就会成为受限。

因此客户端(发起连接方)都是和「目的 IP+目的 PORT」都一样的服务器建立连接的话、当客户端的 TIME_WAIT 状态连接过多的话、就会受端口资源限制、如果占满了所有端口资源、那么就无法再跟「目的 IP+目的 PORT」都一样的服务器建立连接了

不过即使是在这种场景下、只要连接的是不同的服务器端、端口是可以重复使用的、所以客户端还是可以向其他服务器端发起连接的、这是因为内核在定位一个连接的时候、是通过四元组(源IP、源端口、目的IP、目的端口)信息来定位的、并不会因为客户端的端口一样、而导致连接冲突。

如果服务端(主动发起关闭连接方)的 TIME_WAIT 状态过多:

它并不会导致端口资源受限、因为服务端只监听一个端口、而且由于一个四元组唯一确定一个 TCP 连接、因此理论上服务端可以建立很多连接、但是 TCP 连接过多、会占用系统资源、比如文件描述符、内存资源、CPU 资源、线程资源等。

4.TCP的连接构成(四元组五元组是什么)

四元组(源IP、源端口、目的IP、目的端口) 血的教训我当时不记得了😭😭😭😭😭😭 💪 💪 💪 💪 💪 💪

五元组包括:(源IP、源端口、目的IP、目的端口、传输层协议)

5.Linux里面的端口数有没有限制 是否可以无上限

有的 端口资源也是有限的、一般可以开启的端口为 32768~61000、也可以通过 net.ipv4.ip_local_port_range 参数指定范围。

6.怎么看在历史里面怎么去看网络连接呢命令是什么

网络连接查看指令

netstat -an 显示网络连接、路由表、接口统计等信息 此命令列出所有活动的网络连接及其状态。
ss -tuln 此命令显示所有监听的 TCP 和 UDP 端口

7.怎么去看他那种TIME_WAIT的那种网络连接

netstat -ant | grep TIME_WAIT

8.怎么去用指令去查看这台机器上面它的连接的个数、用什么样的指令


netstat -an 显示网络连接、路由表、接口统计等信息 此命令列出所有活动的网络连接及其状态。

9.CPU占用过高怎么看

可以理解为:

Java线上项目CPU飙高怎么办

思路1:

首先toptop -c命令 查看哪个进程占用较高 假设进程PID 是 1677

然后查这个进程对应的一些线程

top -H -p PIDtop -hp PID找到线程占用率较高的线程PID 假设是1700

将线程PID(10进制)转换为16进制

printf "0x%x\n" 67890

然后通过

jstack PID > x.txt
vim x.txt

然后搜索 16进制的线程PID 查看相关代码

总结:

  1. top: 找到 Java 进程 PID 假设是 12345。

  2. top -H -p 12345: 找到 CPU 占用高的线程 PID 假设是 67890。

  3. printf "0x%x\n" 67890: 输出 0x10932

  4. jstack 12345 > jstack.log: 生成堆栈信息文件。

  5. vim jstack.log: 打开文件、搜索 /0x10932

  6. 分析找到的线程堆栈信息 例如:

"Thread-1" #23 prio=5 os_prio=0 tid=0x00007f2a8c001000 nid=0x10932 runnable [0x00007f2a8bfff000] java.lang.Thread.State: RUNNABLE at com.example.MyClass.myMethod(MyClass.java:20) at com.example.MyClass.run(MyClass.java:10) at java.lang.Thread.run(Thread.java:745)

思路2:

CPU占用高问题的思路;

  1. top: 找到 Java 进程 PID 假设是 12345。

  2. top -H -p 12345: 查出 CPU 占用高的线程 PID 假设是 67890。H 选项表示显示线程信息。 -p 12345 选项表示只显示PID为12345的进程的线程信息。 同样按 P 键按CPU使用率排序、找到CPU占用率最高的线程记录其PID。

  3. printf "0x%x\n" 67890: 输出 0x10932

  4. Jstack -l 进程ID 查看虚拟机当前时刻下的线程栈信息

10.Redis的基本数据类型

11.缓存三兄弟

参考上篇文章:

一文告诉你面试的时候要怎么回答缓存击穿、穿透、雪崩问题_缓存雪崩需要多少请求-CSDN博客

12.MySQL建立索引的原则

(我回答的是什么字段适合加索引)

我们一般选择什么样的字段来建立索引

分析

考察索引的使用场景。

适用索引的场景:

  • 字段有唯一性限制的、比如商品编码(索引的区分度高 可以从索引层面保证数据安全)

  • 经常用于 WHERE 查询条件的字段、这样能够提高整个表的查询速度、如果查询条件不是一个字段、可以建立联合索引;

  • 经常用于 GROUP BYORDER BY 的字段、这样在查询的时候就不需要再去做一次排序了、因为我们都已经知道了建立索引之后在 B+Tree 中的记录都是排序好的。

不适合索引的场景:

  • WHERE 条件、GROUP BY、ORDER BY 里用不到的字段、索引的价值是快速定位、如果起不到定位的字段通常是不需要创建索引的,因为索引是会占用物理空间的。

  • 字段中存在大量重复数据、不需要创建索引、比如性别字段,只有男女、如果数据库表中、男女的记录分布均匀、那么无论搜索哪个值都可能得到一半的数据。在这些情况下还不如不要索引、因为 MySQL 还有一个查询优化器、查询优化器发现某个值出现在表的数据行中的百分比很高的时候、它一般会忽略索引、进行全表扫描。(直接explan测试)

  • 经常更新的字段不用创建索引、比如不要对电商项目的用户余额建立索引、因为索引字段频繁修改、由于要维护 B+Tree 的有序性、那么就需要频繁的重建索引、这个过程是会影响数据库性能的。(因为索引的维护成本较高)

参考回答:

可以对频繁用于 WHERE 查询条件的字段建立索引、这样能够提高整张表的查询速度、如果查询条件不是一个字段、可以考虑建立联合索引。还有对于经常用于排序、分组的字段建立索引,这样在查询的时候就不需要再去做一次排序了,因为建立索引之后在 B+ 树中的数据都是排序好的。

不过对于一些区分度不高的字段、比如性别字段、只有男女、不建议建立索引、如果数据库表中、男女的记录分布均匀、那么无论搜索哪个值都可能得到一半的数据、在这种情况下、MySQL 的优化器发现某个值在表中出现的比例很高的时候、它一般会忽略索引、进行全表扫描、这时候建立的索引就没有起到作用、反而还占用了存储空间。

如何定位慢查询

像CPU使用率跟CPU负载这两个有什么区别

你对CPU的使用率怎么看的呢

算法手撕题:

最长有效括号(hard)题目链接: 32. 最长有效括号

import java.util.Stack;

class Solution {
    public int longestValidParentheses(String s) {

        int maxLen = 0;
        Stack<Integer> stack = new Stack<>();
        stack.push(-1); // 初始时,栈底放入 -1、应付s第一个是)

        for (int i = 0; i < s.length(); i++) { // 从 i = 0 开始循环
            char c = s.charAt(i);
            if (c == '(') {
                stack.push(i); // 遇到左括号入栈
            } else {
                stack.pop(); // 遇到右括号出栈
                if (!stack.isEmpty()) {
                    // 栈不为空,说明有匹配的左括号,计算长度
                    maxLen = Math.max(maxLen, i - stack.peek());
                } else {
                    // 栈为空,说明没有匹配的左括号,将当前右括号的索引入栈,作为新的起始位置
                    stack.push(i);
                }
            }
        }

        return maxLen;
    }
}

后续补充一下相关知识

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐