Browse Source

新增mysql面试笔记
新增计网面试笔记

seamew 1 year ago
parent
commit
634105f93f

+ 2 - 2
面经/问答/JVM.md

@@ -27,7 +27,7 @@ CMS垃圾收集器的缺点
 
 * 产生大量空间碎片:因为老年代是标记-清楚算法,所以会产生大量的空间碎片
 * 对CPU资源敏感:应该它与用户线程并行, 所以会导致系统资源被占用
-* 空间需要预留:CMS垃圾收集器可以一边回收垃圾,一边处理用户线程,那需要在这个过程中保证有充足的内存空间供用户使用。如果CMS运行过程中预留的空间不够用,会报错
+* 内存需要预留:CMS垃圾收集器可以一边回收垃圾,一边处理用户线程,那需要在这个过程中保证有充足的内存空间供用户使用。如果CMS运行过程中预留的空间不够用,会报错
 
 ## G1垃圾收集器
 
@@ -109,7 +109,7 @@ jvm内存区域大体上可以分为线程私有和线程共有两大部分
 
 ## 强引用对象会被GC清除吗?
 
-不会被清,因为强引用对象本身就是GC ROOT,除非该方法已经从栈中弹出,或者不在使用才会被清除
+不会被清,因为强引用对象本身就是GC ROOT,除非该方法已经从栈中弹出,或者不在使用才会被清除
 
 
 

+ 81 - 0
面经/问答/Mysql.md

@@ -0,0 +1,81 @@
+## mysql内连接,外连接,左连接,右连接
+
+- left join(左连接):返回包括左表中的所有记录和右表中连接字段相等的记录。
+- right join(右连接):返回包括右表中的所有记录和左表中连接字段相等的记录。
+- inner join(内连接):只返回两个表中连接字段相等的行。
+- full join (全外连接):返回左右表中所有的记录和左右表中连接字段相等的记录。在mysql中不存在全连接,但是他可以等同于左连接合并右连接
+
+## mysql如何提升查询性能
+
+1. 合理使用索引:索引是提升查询性能的重要手段,可以通过在常用查询字段上创建索引来加速查询速度。需要注意的是,索引的创建和使用需要谨慎,过多或不合理的索引可能会降低性能。在使用索引时,可以通过 EXPLAIN 分析查询计划,避免全表扫描和不必要的索引使用。
+2. 优化 SQL 语句:优化 SQL 语句可以通过多种方式实现,例如避免使用通配符查询,优化复杂查询语句,避免不必要的连接查询和子查询,合理使用聚合函数和 GROUP BY 子句等。可以通过使用数据库性能分析工具(如 MySQL 自带的慢查询日志)来定位慢查询,并对其进行优化。
+3. 缓存和缓冲技术:通过使用缓存和缓冲技术可以减轻数据库的负载,提高查询性能。可以使用数据库自带的查询缓存功能,或者使用外部缓存技术如 Redis、Memcached 等进行数据缓存,减少对数据库的频繁查询。
+4. 合理配置数据库参数:MySQL 有丰富的配置参数可以进行调优,例如调整缓冲池大小、设置合理的连接数、开启合适的日志等,可以根据实际需求和硬件资源来配置数据库参数,以达到最佳性能。
+5. 定期维护数据库:数据库的性能和稳定性需要定期进行维护,包括定期清理无用的数据和索引,进行数据库备份和日志管理,定期更新统计信息等。定期维护可以保持数据库的健康状态,提升查询性能。
+6. 可以考虑使用分库分表技术,例如对于用户中奖详情单我选择了分库分表,因为有多个用户和不同活动同时竞争这个表,数据库访问压力比较大,所以就要选择分库分表
+
+## mysql低层数据结构
+
+1. B+ 树索引:MySQL 使用 B+ 树作为默认的索引结构。索引数据最好能按顺序排列,这样可以使用「二分查找法」高效定位数据,而且还要支持排序操作。这就天然要求我们使用平衡二叉树作为默认的数据结构,而平衡二叉树本身是一个B树,每个节点只能有两个子节点那么当节点个数越多的时候,树的高度也会相应变高,这样就会增加磁盘的 I/O 次数,从而影响数据查询的效率。B 树的每一个节点最多可以包括 M 个子节点,M 称为 B 树的阶,所以 B 树就是一个多叉树。B+ 树就是对 B 树做了一个升级,他和B树相比有如下几个优点
+   1. B+ 树的非叶子节点不存放实际的记录数据,仅存放索引,因此数据量相同的情况下,相比存储即存索引又存记录的 B 树查询效率更高,因为IO次数更少
+   2. B+ 树在删除根节点的时候,由于存在冗余的节点,所以不会发生复杂的树的变形,B 树则不同,B 树没有冗余节点,删除节点的时候非常复杂
+   3. B+ 树所有叶子节点间还有一个链表进行连接,这种设计对范围查找非常有帮助
+2. 数据文件:MySQL 数据库将数据存储在磁盘上的数据文件中,低层由表空间构成,表空间由段(segment)、区(extent)、页(page)、行(row)组成
+3. InnoDB 存储引擎:InnoDB 是 MySQL 的一种常用存储引擎,它使用了多版本并发控制(MVCC)和行级锁来实现高并发性和事务支持。InnoDB 存储引擎的核心数据结构包括页(page)、记录(record)、索引(index)和事务日志(transaction log)等。
+
+## 联合索引定义要注意哪些点
+
+在 MySQL 中定义联合索引时,需要注意以下几点:
+
+1. 列顺序:联合索引中的列顺序非常重要,它会影响索引的效果。通常情况下,应该将被频繁用于查询的列放在联合索引的前面,这样可以使索引在查询时更加有效。例如,如果查询中经常同时使用列 A 和列 B 进行查询,那么联合索引应该按照 (A, B) 的顺序定义,而不是 (B, A)。
+2. 列选择:不要将过多的列包含在联合索引中,因为索引的大小对数据库性能有影响。过大的索引可能会导致磁盘 I/O 操作增加,并且会占用额外的存储空间,导致性能下降
+3. 索引选择:不是所有的列都适合联合索引。联合索引在使用时会按照索引列的顺序进行匹配,因此只有查询中包含了索引的前缀列时,索引才能被充分利用。因此,应该选择那些在查询中经常一起使用的列进行联合索引定义。
+4. 更新性能:联合索引在更新操作时可能会导致性能下降。因为联合索引涉及多个列,更新其中的一个列可能需要更新整个索引。因此,在定义联合索引时应该考虑更新性能的影响,避免频繁的更新操作导致性能下降。
+
+## 数据库ACID
+
+- **原子性(Atomicity)**:一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节,而且事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样,就好比买一件商品,购买成功时,则给商家付了钱,商品到手;购买失败时,则商品在商家手中,消费者的钱也没花出去。
+- **一致性(Consistency)**:是指事务操作前和操作后,数据满足完整性约束,数据库保持一致性状态。比如,用户 A 和用户 B 在银行分别有 800 元和 600 元,总共 1400 元,用户 A 给用户 B 转账 200 元,分为两个步骤,从 A 的账户扣除 200 元和对 B 的账户增加 200 元。一致性就是要求上述步骤操作后,最后的结果是用户 A 还有 600 元,用户 B 有 800 元,总共 1400 元,而不会出现用户 A 扣除了 200 元,但用户 B 未增加的情况(该情况,用户 A 和 B 均为 600 元,总共 1200 元)。
+- **隔离性(Isolation)**:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致,因为多个事务同时使用相同的数据时,不会相互干扰,每个事务都有一个完整的数据空间,对其他并发事务是隔离的。也就是说,消费者购买商品这个事务,是不影响其他消费者购买的。
+- **持久性(Durability)**:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
+
+InnoDB 引擎通过什么技术来保证事务的这四个特性的呢?
+
+- 持久性是通过 redo log (重做日志)来保证的;
+- 原子性是通过 undo log(回滚日志) 来保证的;
+- 隔离性是通过 MVCC(多版本并发控制) 或锁机制来保证的;
+- 一致性则是通过持久性+原子性+隔离性来保证;
+
+## 数据库隔离级别
+
+数据库隔离级别是指在多用户并发访问数据库时,数据库管理系统 (DBMS) 为了保护数据的一致性、隔离性和并发性,采取的一系列措施和规定。MySQL 支持以下四种隔离级别:
+
+1. 读未提交 (Read Uncommitted):最低的隔离级别,事务可以读取到其他事务未提交的数据。这种隔离级别可能导致脏读(Dirty Read),即读取到其他事务未提交的数据,可能会引起数据的不一致性。
+2. 读提交 (Read Committed):事务只能读取到其他事务已经提交的数据,保证了数据的一致性。但在该隔离级别下,可能会出现不可重复读(Non-repeatable Read)问题,即在同一事务内多次读取同一行数据时,可能会得到不同的结果。
+3. 可重复读 (Repeatable Read):事务在执行期间对同一行数据进行读取时,会保持一致的结果。其他事务对该行数据的修改只有在当前事务提交后才能生效。这种隔离级别可以避免不可重复读问题,但仍然可能出现幻读(Phantom Read)问题,即在同一事务内多次执行相同的查询时,可能会得到不同的结果。
+4. 串行化 (Serializable):最高的隔离级别,事务会对数据库中的数据加锁,防止其他事务对数据的并发访问。这种隔离级别可以避免幻读问题,但可能会导致性能下降,因为事务需要等待其他事务释放锁。
+
+## 数据库MVCC
+
+MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种数据库管理系统(DBMS)中的并发控制机制,用于在多用户并发访问数据库时保障事务的隔离性和一致性。MVCC通过在数据库中为每个事务创建多个版本的数据副本,使多个事务可以同时读取和修改数据库中的数据,而不会相互干扰。
+
+在MVCC模型中,每个事务在读取和修改数据时,都会看到数据库中的一个一致性的快照(snapshot),而不是实际的物理数据。每个事务都有自己的事务ID(Transaction ID),数据库中的每条记录也会保存多个版本,每个版本都包含了一个事务ID和一个时间戳(Timestamp)。当事务执行读取操作时,只会看到在其事务开始之前提交的数据版本,而不会看到在其事务开始之后提交的数据版本。这样可以避免脏读、不可重复读和幻读等并发访问问题。
+
+## 加入索引有什么讲究
+
+1. 精选索引列:选择适合索引的列是关键。频繁在查询条件中出现,或者是查询条件的所有列。这样可以防止回表
+2. 注意索引的顺序:索引的顺序对查询性能有影响。对于联合索引,索引列的顺序应该根据查询的实际情况来选择。通常,将基数(Distinct count)较高的列放在前面,可以减少索引的选择性,提高查询性能。
+3. 考虑索引的类型:MySQL支持多种类型的索引,如普通索引、唯一索引、主键索引、全文索引等。根据查询的需求和数据的特点选择合适的索引类型。例如,对于需要唯一性约束的列,可以使用唯一索引或主键索引;对于文本字段的模糊查询,可以考虑使用全文索引。
+4. 避免过度索引:过度索引可能导致性能下降和维护成本增加。因此,避免在相同的列上创建多个重复的索引,避免对低基数列(Distinct count较低的列)添加索引,避免创建不必要的索引。
+
+## B树的特点
+
+1. 平衡二叉树节点最多有两个子树,而 B 树每个节点可以有多个子树,**M 阶 B 树表示该树每个节点最多有 M 个子树**
+2. 平衡二叉树每个节点只有一个数据和两个指向孩子的指针,而 B 树每个中间节点有 k-1 个关键字(可以理解为数据)和 k 个子树( k介于阶数 M 和 M/2 之间,M/2 ⬆️向上取整)
+3. B 树的所有叶子节点都在同一层,并且叶子节点只有关键字,指向孩子的指针为 null
+
+## 索引的分类
+
+- 按「物理存储」分类:**聚簇索引(主键索引)、二级索引(辅助索引)(非聚簇索引)**。
+- 按「字段特性」分类:**主键索引、唯一索引、普通索引、前缀索引**。
+- 按「字段个数」分类:**单列索引、联合索引**。

BIN
面经/问答/assets/format,png-20230309230424714.png


BIN
面经/问答/assets/format,png-20230309230614791.png


BIN
面经/问答/assets/image-20230416213611588.png


BIN
面经/问答/assets/image-20230416213623643.png


+ 230 - 0
面经/问答/计网.md

@@ -0,0 +1,230 @@
+## 什么是TCP
+
+TCP 是**面向连接的、可靠的、基于字节流**的传输层通信协议。
+
+![img](assets/format,png-20230309230424714.png)
+
+- **面向连接**:一定是「一对一」才能连接,不能像 UDP 协议可以一个主机同时向多个主机发送消息,也就是一对多是无法做到的;
+- **可靠的**:无论的网络链路中出现了怎样的链路变化,TCP 都可以保证一个报文一定能够到达接收端;
+- **字节流**:用户消息通过 TCP 协议传输时,消息可能会被操作系统「分组」成多个的 TCP 报文,如果接收方的程序如果不知道「消息的边界」,是无法读出一个有效的用户消息的。并且 TCP 报文是「有序的」,当「前一个」TCP 报文没有收到的时候,即使它先收到了后面的 TCP 报文,那么也不能扔给应用层去处理,同时对「重复」的 TCP 报文会自动丢弃。
+
+## tcp拥塞控制的几个策略
+
+1. 慢启动:在连接刚建立时,TCP发送方会以较小的拥塞窗口(cwnd)开始发送数据,并根据每次接收到的确认(ACK)增加cwnd的大小,从而逐渐增加发送速率,达到网络带宽的最佳利用。
+2. 拥塞避免:当 `cwnd` >= `ssthresh` 时,就会使用「拥塞避免算法」,TCP发送方会切换到拥塞避免模式,此时每次接收到一个ACK时,cwnd的大小只会增加一个MSS(最大报文段长度),而不是每次都加倍。这样可以避免发送过多的数据导致网络拥塞。
+3. 拥塞发生:当网络出现拥塞,也就是会发生数据包重传,重传机制主要有两种:
+   1. 快速重传:当TCP发送方连续收到3个重复的ACK时,TCP 认为这种情况不严重,因为大部分没丢,只丢了一小部分,则 `ssthresh` 和 `cwnd` 变化如下:
+      - `cwnd = cwnd/2` ,也就是设置为原来的一半;
+      - `ssthresh = cwnd`;
+      - 进入快速恢复算法
+   2. 超时重传:如果在发送数据时未能及时接收到ACK,`ssthresh` 设为 `cwnd/2`,`cwnd` 重置为 `1`
+4. 快速恢复:进入快速恢复之前,`cwnd` 和 `ssthresh` 已被更新了,然后,进入快速恢复算法如下:
+   1. 拥塞窗口 `cwnd = ssthresh + 3` ( 3 的意思是确认有 3 个数据包被收到了);
+   2. 重传丢失的数据包;
+   3. 如果再收到重复的 ACK,那么 cwnd 增加 1;
+   4. 如果收到新数据的 ACK 后,把 cwnd 设置为第一步中的 ssthresh 的值,原因是该 ACK 确认了新的数据,说明从 duplicated ACK 时的数据都已收到,该恢复过程已经结束,可以回到恢复之前的状态了,也即再次进入拥塞避免状态;
+
+## TCP如何保证可靠
+
+* 重传机制
+  * 超时重传
+  * 快速重传
+  * SACK-- **可以将已收到的数据的信息发送给「发送方」**
+  * D-SACK -- **使用了 SACK 来告诉「发送方」有哪些数据被重复接收了**
+* 滑动窗口
+* 流量控制 -- **TCP 提供一种机制可以让「发送方」根据「接收方」的实际接收能力控制发送的数据量,这就是所谓的流量控制。**
+* 拥塞控制
+
+## TCP和UDP区别
+
+*1. 连接*
+
+- TCP 是面向连接的传输层协议,传输数据前先要建立连接。
+- UDP 是不需要连接,即刻传输数据。
+
+*2. 服务对象*
+
+- TCP 是一对一的两点服务,即一条连接只有两个端点。
+- UDP 支持一对一、一对多、多对多的交互通信
+
+*3. 可靠性*
+
+- TCP 是可靠交付数据的,数据可以无差错、不丢失、不重复、按序到达。
+- UDP 是尽最大努力交付,不保证可靠交付数据。
+
+*4. 拥塞控制、流量控制*
+
+- TCP 有拥塞控制和流量控制机制,保证数据传输的安全性。
+- UDP 则没有,即使网络非常拥堵了,也不会影响 UDP 的发送速率。
+
+*5. 头部长度不同*
+
+- TCP 首部长度较长,会有一定的开销,首部在没有使用「选项」字段时是 `20` 个字节,如果使用了「选项」字段则会变长的。
+- UDP 首部只有 8 个字节,并且是固定不变的,开销较小。
+
+*6. 传输方式*
+
+- TCP 是流式传输,没有边界,但保证顺序和可靠。
+- UDP 是一个包一个包的发送,是有边界的,但可能会丢包和乱序。
+
+*7. 分片不同*
+
+- TCP 的数据大小如果大于 MSS 大小,则会在传输层进行分片,目标主机收到后,也同样在传输层组装 TCP 数据包,如果中途丢失了一个分片,只需要传输丢失的这个分片。
+- UDP 的数据大小如果大于 MTU 大小,则会在 IP 层进行分片,目标主机收到后,在 IP 层组装完数据,接着再传给传输层。
+
+## 两个队列
+
+在 TCP 三次握手的时候,Linux 内核会维护两个队列,分别是:
+
+- 半连接队列,也称 SYN 队列;服务端收到**第一次握手**后,会将`sock`加入到这个队列中,队列内的`sock`都处于`SYN_RECV` 状态。
+- 全连接队列,也称 accept 队列;在服务端收到**第三次握手**后,会将半连接队列的`sock`取出,放到全连接队列中。队列里的`sock`都处于 `ESTABLISHED`状态。这里面的连接,就**等着服务端执行accept()后被取出了。**
+
+## socket函数常见方法
+
+![image-20230416213623643](assets/image-20230416213623643.png)
+
+### 服务端方法:
+
+* `bind`,将 socket 绑定在指定的 IP 地址和端口;
+  * **服务端如果只 bind 了 IP 地址和端口,而没有调用 listen 的话,然后客户端对服务端发起了连接建立,服务端会回 RST 报文。**
+* `listen`,进行监听,服务器端处于listen状态
+  * **每一个**`socket`执行`listen`时,内核都会自动创建一个半连接队列和全连接队列。
+* `accept`,等待客户端连接;**accept 成功返回是在三次握手成功之后**
+  * `accept方法`只是为了从全连接队列中拿出一条连接,本身跟三次握手几乎**毫无关系**。
+
+### 客户端
+
+* `connect`,向服务端的地址和端口发起连接请求;**connect 成功返回是在第二次握手**
+  * 客户端调用connect函数主动构建连接
+
+## TCP三次握手
+
+这个问题可以理解为为什么TCP不是两次握手,因为主要原因是两次握手只能确定一方的状态
+
+- 三次握手才可以阻止重复历史连接的初始化(主要原因)
+- 三次握手才可以同步双方的初始序列号
+- 三次握手才可以避免资源浪费
+
+需要注意的是**第三次握手是可以携带数据的,前两次握手是不可以携带数据的**
+
+### 第一次握手丢失了,会发生什么?
+
+* 客户端会重传 SYN 报文,也就是第一次握手就会触发「超时重传」机制,重传 SYN 报文
+
+### 第二次握手丢失了,会发生什么?
+
+- 客户端会重传 SYN 报文,也就是第一次握手,最大重传次数由 `tcp_syn_retries`内核参数决定;
+- 服务端会重传 SYN-ACK 报文,也就是第二次握手,最大重传次数由 `tcp_synack_retries` 内核参数决定。
+
+### 第三次握手丢失了,会发生什么?
+
+* 服务端会重传 SYN-ACK 报文,**ACK 报文是不会有重传的,当 ACK 丢失了,就由对方重传对应的报文**。
+
+## 既然 IP 层会分片,为什么 TCP 层还需要 MSS 呢?
+
+**那么当如果一个 IP 分片丢失,整个 IP 报文的所有分片都得重传**,经过 TCP 层分片后,如果一个 TCP 分片丢失后,**进行重发时也是以 MSS 为单位**,而不用重传所有的分片,大大增加了重传的效率。
+
+## TCP的ACK报文会重传吗
+
+TCP协议中的ACK(Acknowledgment)报文通常不会重传。
+
+ACK报文是TCP用于确认接收到数据的报文,用于确认对方发送的数据已经成功接收。在TCP的可靠传输机制中,发送方发送数据后,会等待接收方发送ACK报文进行确认。如果发送方在一定的超时时间内没有接收到ACK报文,则会认为数据没有成功送达,并进行重传(这里是对应报文不是ACK报文)。
+
+在TCP协议中,数据的重传是由发送方负责的,而ACK报文的重传通常不会由接收方触发。一般情况下,接收方只需要发送ACK报文来确认已接收到数据,而不会因为没有接收到ACK报文而进行重传。接收方只有在需要通知发送方数据丢失或者需要进行流量控制等特殊情况下,才会发送特定的控制报文,如SACK(Selective Acknowledgment)报文或者窗口更新报文。
+
+## 什么是 SYN 攻击?如何避免 SYN 攻击?
+
+我们都知道 TCP 连接建立是需要三次握手,假设攻击者短时间伪造不同 IP 地址的 `SYN` 报文,服务端每接收到一个 `SYN` 报文,就进入`SYN_RCVD` 状态,但服务端发送出去的 `ACK + SYN` 报文,无法得到未知 IP 主机的 `ACK` 应答,久而久之就会**占满服务端的半连接队列**,使得服务端不能为正常用户服务。
+
+避免 SYN 攻击方式,可以有以下四种方法:
+
+- 调大 内核处理速度
+- 增大 TCP 半连接队列;
+- 开启 tcp_syncookies;可以将全连接队列利用起来
+- 减少 SYN+ACK 重传次数
+
+## TCP四次挥手
+
+![客户端主动关闭连接 —— TCP 四次挥手](assets/format,png-20230309230614791.png)
+
+- 客户端打算关闭连接,此时会发送一个 TCP 首部 `FIN` 标志位被置为 `1` 的报文,也即 `FIN` 报文,之后客户端进入 `FIN_WAIT_1` 状态。
+- 服务端收到该报文后,就向客户端发送 `ACK` 应答报文,接着服务端进入 `CLOSE_WAIT` 状态。
+- 客户端收到服务端的 `ACK` 应答报文后,之后进入 `FIN_WAIT_2` 状态。
+- 等待服务端处理完数据后,也向客户端发送 `FIN` 报文,之后服务端进入 `LAST_ACK` 状态。
+- 客户端收到服务端的 `FIN` 报文后,回一个 `ACK` 应答报文,之后进入 `TIME_WAIT` 状态
+- 服务端收到了 `ACK` 应答报文后,就进入了 `CLOSE` 状态,至此服务端已经完成连接的关闭。
+- 客户端在经过 `2MSL` 一段时间后,自动进入 `CLOSE` 状态,至此客户端也完成连接的关闭。
+
+你可以看到,每个方向都需要**一个 FIN 和一个 ACK**,因此通常被称为**四次挥手**。
+
+这里一点需要注意是:**主动关闭连接的,才有 TIME_WAIT 状态。**
+
+### 第一次挥手丢失了,会发生什么?
+
+* 客户端:如果第一次挥手丢失了,那么客户端迟迟收不到被动方的 ACK 的话,也就会触发超时重传机制,重传 FIN 报文,重发次数由 `tcp_orphan_retries` 参数控制。
+* 服务端:后续会通过keepalive机制结束连接
+
+### 第二次挥手丢失了,会发生什么?
+
+* 客户端:ACK 报文是不会重传的,所以如果服务端的第二次挥手丢失了,客户端就会触发超时重传机制
+* 服务端:服务端会主动调用close函数
+
+### 第三次挥手丢失了,会发生什么?
+
+* 服务端:如果迟迟收不到这个 ACK,服务端就会重发 FIN 报文
+
+### 第四次挥手丢失了,会发生什么?
+
+* 服务端:如果第四次挥手的 ACK 报文没有到达服务端,服务端就会重发 FIN 报文
+
+## 为什么 TIME_WAIT 等待的时间是 2MSL?
+
+`2MSL` 的时间是从**客户端接收到 FIN 后发送 ACK 开始计时的**。如果在 TIME-WAIT 时间内,因为客户端的 ACK 没有传输到服务端,客户端又接收到了服务端重发的 FIN 报文,那么 **2MSL 时间将重新计时**。
+
+TIME_WAIT 等待 2 倍的 MSL,比较合理的解释是: 网络中可能存在来自发送方的数据包,当这些发送方的数据包被接收方处理后又会向对方发送响应,所以**一来一回需要等待 2 倍的时间**。
+
+## 为什么需要 TIME_WAIT 状态?
+
+- 防止历史连接中的数据,被后面相同四元组的连接错误的接收;
+- 保证「被动关闭连接」的一方,能被正确的关闭;
+
+## TIME_WAIT 过多有什么危害?
+
+- 第一是占用系统资源,比如文件描述符、内存资源、CPU 资源、线程资源等;
+- 第二是占用端口资源,端口资源也是有限的,一般可以开启的端口为 `32768~61000`,也可以通过 `net.ipv4.ip_local_port_range`参数指定范围。
+
+## 服务器出现大量 TIME_WAIT 状态的原因有哪些?
+
+- 第一个场景:HTTP 没有使用长连接
+- 第二个场景:HTTP 长连接超时
+- 第三个场景:HTTP 长连接的请求数量达到上限
+
+## 四次挥手可以变成三次吗?
+
+答案是可以
+
+> 什么是 TCP 延迟确认机制?
+
+当发送没有携带数据的 ACK,它的网络效率也是很低的,因为它也有 40 个字节的 IP 头 和 TCP 头,但却没有携带数据报文。 为了解决 ACK 传输效率低问题,所以就衍生出了 **TCP 延迟确认**。 TCP 延迟确认的策略:
+
+- 当有响应数据要发送时,ACK 会随着响应数据一起立刻发送给对方
+- 当没有响应数据要发送时,ACK 将会延迟一段时间,以等待是否有响应数据可以一起发送
+- 如果在延迟等待发送 ACK 期间,对方的第二个数据报文又到达了,这时就会立刻发送 ACK
+
+**当被动关闭方在 TCP 挥手过程中,如果「没有数据要发送」,同时「没有开启 TCP_QUICKACK(默认情况就是没有开启,没有开启 TCP_QUICKACK,等于就是在使用 TCP 延迟确认机制)」,那么第二和第三次挥手就会合并传输,这样就出现了三次挥手。**
+
+## close和shutdown的区别
+
+- close 函数,同时 socket 关闭发送方向和读取方向,也就是 socket 不再有发送和接收数据的能力。如果有多进程/多线程共享同一个 socket,如果有一个进程调用了 close 关闭只是让 socket 引用计数 -1,并不会导致 socket 不可用,同时也不会发出 FIN 报文,其他进程还是可以正常读写该 socket,直到引用计数变为 0,才会发出 FIN 报文。
+- shutdown 函数,可以指定 socket 只关闭发送方向而不关闭读取方向,也就是 socket 不再有发送数据的能力,但是还是具有接收数据的能力。如果有多进程/多线程共享同一个 socket,shutdown 则不管引用计数,直接使得该 socket 不可用,然后发出 FIN 报文,如果有别的进程企图使用该 socket,将会受到影响。
+
+## TCP 的 Keepalive
+
+TCP 的 Keepalive 这东西其实就是 **TCP 的保活机制**
+
+>  如果两端的 TCP 连接一直没有数据交互,达到了触发 TCP 保活机制的条件,那么内核里的 TCP 协议栈就会发送探测报文。
+
+如果两端的 TCP 连接一直没有数据交互,达到了触发 TCP 保活机制的条件(默认是两个小时),那么内核里的 TCP 协议栈就会发送探测报文。
+
+- 如果对端程序是正常工作的。当 TCP 保活的探测报文发送给对端, 对端会正常响应,这样 **TCP 保活时间会被重置**,等待下一个 TCP 保活时间的到来。
+- 如果对端主机崩溃,或对端由于其他原因导致报文不可达。当 TCP 保活的探测报文发送给对端后,石沉大海,没有响应,连续几次,达到保活探测次数后,**TCP 会报告该 TCP 连接已经死亡**。

+ 21 - 3
面经/项目/中煤项目.md

@@ -1,5 +1,17 @@
 # kafka模块
 
+煤矿大数据平台作为智能矿山基础服务平台的一部分,承担智能矿山服务平台中煤矿数据的采集、传输、存储、分发、计算等任务,致力于达到打通煤矿数据壁垒、整合数据资源、规范煤矿数据等目标。我主要负责数据采集和该模块监控这个两部分的功能。主要应用的组件是kafka,为了与下层数据传感器或者叫收集器解耦,也为了缓解系统IO压力,我们引入了kafka模块做数据采集的主要组件,为了保证顺序消费,因为采集的数据将按照时间顺序存入到hbase中。在生产者那一段主要是使用对象池技术进行缓存kafka producer。在消费者那一端则采用线程池对消费的数据进行处理,主要采取策略模式,按照选择的不同策略进行计算,例如区间或者压强的简单计算,或者是数值替换,也支持三方jar包,然后通过futuer收集数据。最后存储到hbase中。为了保证消息的等幂性,消费者端我们采取redis进行缓存数据,缓存超时时间默认为3分钟,将ACK设置为1保证消息顺序消费,如果消息发送失败,则默认重试一次,因为这个系统更多的是在意吞吐量,对于消息是否丢失不是很在意。
+
+我完成的第二个模块就是kafka监控模块,主要监控kafka集群的状态,与kafka-egale类似。主要操作就是调用kafka提供的kafka-admin-client接口和JMX进行操作,这里进行了相应的优化,主要包括复用同一个连接,多个用户同时调用接口,都会通过工厂模式,单例的产生一个admin-client,这里主要加了两段锁和volatile关键字保证线程安全,利用redis缓存topic的速率。最后对于该模块,采用热启动的方式优化,例如自动建表,提前获取相关admin-client链接等
+
+
+
+我参与了一个煤矿大数据平台的开发项目,旨在为智能矿山服务平台提供支持并优化业务流程。在项目中,我负责设计和实现了数据采集和处理模块。我使用了Kafka作为数据采集工具,通过Kafka监控模块对数据进行实时监控和处理,利用Redis进行缓存以提高数据查询效率。
+
+为了保证项目的性能和稳定性,我针对Kafka监控模块进行了优化,包括对消费者组进行调优、调整分区和副本数量、设置合理的消息大小和缓冲区大小等。这些优化措施显著提升了系统的数据处理速度和稳定性。
+
+通过我在数据采集和处理模块的设计和实现,项目成功地实现了高效、可靠的数据采集和处理流程,为智能矿山服务平台提供了稳定的数据支持,并在业务流程优化方面取得了显著的成果。项目上线后,数据处理速度提升了30%,用户体验得到了明显的改善。此外,通过合理的资源管理和团队协作,项目按计划完成,并且得到了用户和业务部门的高度认可。
+
 ## kafka监控
 
 redis缓存
@@ -16,18 +28,24 @@ jmx -- 多个端口
 
 ## kafka消费
 
-线程池多线程消费   --- future
+线程池多线程消费   --- future  CPU -N +1  IO 2N
 
 幂等处理 -- redis缓存
 
-hash计算多个分区
+hash计算多个分区????
 
 ack = 1
 
 顺序消费
 
+采集任务合并
+
+策略模式选择策略
+
 # 流量分析项目
 
 * SPI
 * 策略模式
-* 责任链模式
+* 责任链模式
+
+流量分析项目是六所网络安全部门的一个子项目,它主要功能是识别工控设备异常流量,达到防范攻击和攻击溯源的功能,我主要负责的是工控协议流量解析部分,负责12种工控协议的解析。协议解析主要参照各个协议的官网进行翻译,主要通过策略模式进行协议选择,和通过责任链模式进行协议判断,然后将该jar包通过SPI注入到服务方的服务中去