面试记录自用

文章目录

zjjy20251205一面

工作/实习:

  • 用kafka的好处?
  • 有考虑过用RDB和RabbitMQ吗?
  • 数量级多大?
  • 项目的难点?
  • websocket什么场景会使用到?
  • websocket跟HTTP轮询主要差别在哪,为什么性能比HTTP更好?回答的是三握四挥不知道对不对

项目:

  • 是否已经投产?
  • Redis多级缓存机制是怎么做的?
  • @Cacheable具体是怎么起作用的?
  • Redis如何保证一致性?
  • 可以先删除缓存再更新DB吗?
  • 可以先更新DB再删除缓存吗?
  • 大概介绍一下ES的原理?用的什么索引?倒排索引原理?用过哪些分词器?
  • 如果ES查询变慢了,你有什么排查思路吗?
  • Mysql慢查询讲讲?
  • 水平分库分表数据量?
  • 慢查询除了SQL本身的原因还有什么可能?
  • 事务隔离级别,MVCC,原理,readview、undolog等等。
  • redolog是什么?使用场景?
  • 间隙锁这些了解吗?(间隙锁就是锁定索引之间的间隙,防止其他事务在这个间隙插入数据,主要用来解决幻读的问题)
  • mysql会出现死锁吗?大概什么场景,什么原因?有什么解决的办法吗?
  • mysql量级多少?几千条还涉及到分库分表和慢查询吗?

八股

  • 前端到服务端整个流程大概讲一下?域名,ip,传输层,安全层这个流程是怎么运转的?
  • TCP讲一下三握手的过程?为什么要三次握手?
  • 讲一下kafka的架构和消息存储机制?zookeeper主要存什么信息或者说为什么要用zookeeper?新版本好像老早不用zookeeper了?

手撕代码

最大不重复子串-滑动窗口

wx20251205一面

** 八股**

  • TCP为什么要三次握手?四次挥手的过程是什么?能不能三次挥手就行?Time wait的作用?TCP的拥塞控制是什么?

  • 从浏览器输入一个URL到页面加载完成这个过程中会发生什么?

  • DNS寻址过程是怎样的?如果中间有服务器断联了怎么办?DNS劫持是什么?

  • HTTPS加密过程?

  • 状态码之间比如说有500 501 502?400开头和500开头的状态码一般会用在什么场景?

  • TCP三次握手过程?如果TCP给服务端发送大量的SYN报文不给最后一次握手怎么办?

  • linux指令:如何查看当前系统的内存和CPU的使用?load average知道吗?linux如何查到目标进程然后kill?top指令可以grep吗?linux里面的文件权限有rwx分别代表什么意思?权限分成哪几种用户权限?怎么看一个端口是否被占用(lsof)?怎么在linux设定一个定时任务?软连接和硬连接的区别?

  • String StringBuild StringBuffer区别?

  • 介绍threadlocal和可能的问题?

  • MYSQL索引结构?B+树特点?

手撕代码

匹配括号是否一致-栈

xykj20251203go三面

  • go和java区别?
  • 用过什么AI工具?

xykj20251202go二面

工作/实习

  • kafka有做幂等性吗?如何防止数据丢失?
  • 线程池参数怎么设置的?最大线程数,核心线程数,线程工厂,阻塞队列都怎么设置的?为什么这么设置?
  • 虚拟机栈调优

八股

  • mysql索引失效?索引创建原则?

手撕代码

  • 查询11~15条数据
  • 查询有相同生日的人
sql 复制代码
-- 适用于 ID 无断层的情况,直接通过 LIMIT 偏移量+条数实现
SELECT * FROM users 
ORDER BY id ASC 
LIMIT 10, 5; -- LIMIT 偏移量(从0开始), 查询条数 → 偏移10条后取5条(即11-15条)
sql 复制代码
SELECT * FROM users 
WHERE birthday IN (
    SELECT birthday FROM users GROUP BY birthday HAVING COUNT(id) > 1
) 

xykj20251127go一面

  • undolog redolog binlog?→MVCC隔离、主从同步mysql?
  • go map是否线程安全→sync.map原理→java concurrent hashmap
  • 慢查询
  • 水平分库分表
  • channel如何限制次数使用?(waitgroup)
  • channel关掉还能写吗,会怎样?

2025.11.12 ah二面

工作经历:

Mysql大批量插入。

所有接口都卡住怎么办?

八股:

Reentrentlock synchronize aqs

jvm 内存结构

jstack

Arthas 、慢查询

索引失效

多线程处理慢

2025.11.07实习 ah-Java-一面

八股:

Spring如何装配?答:@ComponentScan注解扫描 + Bean生命周期

Kafka如何保证消息不丢失?

Hashmap和ConcurrentHashMap 哪个线程安全?数据结构有何不同?

Redis穿透、雪崩、击穿? 但回答击穿加锁,面试官说就是为了缓存干嘛加锁。。。

docker如何优化镜像,如何加速部署,容器间如何通信? 这个挺冷门的

项目&场景:

Websocket和HTTP中和的半双工通信方式??

websocket如何保证可靠?

如何统计在线人数?答websocket/消息队列/定时任务扫描都不行

langchain4j、langchain、springai区别?如何开发?

mybatis批量插入是怎么做优化的。

2025.11.07实习 yjhz Java 一面

String StirngBuilder StringBuffer?

Springboot装配流程?

SpringbootApplication启动注解可以加什么参数?

List Set区别?Set特性?

线程的几种创建方式?

2025.10.31实习 xskj Java 一面

八股:

b+树索引

回表查询,二级索引

redis基本数据类型,项目中用了哪些

项目:

一主多从架构

功能介绍。

2025.09字节一面挂

八股:

索引最左前缀原则

举例说下死锁情景

分布式锁举例一种实现

redis基本数据类型

手撕代码:力扣 重排序

2025.07 高德一面挂

八股:

事务何时失效?

springboot为何比spring好?为何选springboot

其他忘了。

回答汇总

为什么要三次握手

一、三次握手核心目的:双向确认双方收发能力正常,同步初始序列号(ISN)

TCP是可靠传输,需确保「客户端能发、服务器能收;服务器能发、客户端能收」,三次握手刚好完成双向校验,且能避免历史无效连接干扰。

二、三次握手完整逻辑(极简版)

  1. 客户端→服务器(SYN=1,Seq=x):客户端说"我能发,我的初始序号是x"(请求建立连接);
  2. 服务器→客户端(SYN=1,ACK=1,Seq=y,Ack=x+1):服务器说"我能收(确认收到x),我也能发(我的序号是y)"(同意建立连接);
  3. 客户端→服务器(ACK=1,Seq=x+1,Ack=y+1):客户端说"我能收(确认收到y)"(连接正式建立)。

三、为什么必须三次?两次会有两个致命问题

问题1:无法确认「客户端的接收能力」,服务器资源被浪费

若只两次握手,流程是:客户端发SYN→服务器发SYN+ACK(连接建立),但客户端收不到服务器的SYN+ACK(如网络丢包),服务器会误以为连接已建立,一直占用端口、内存等资源,直到超时释放------大量此类无效连接会耗尽服务器资源,导致正常连接无法建立。

问题2:无法避免「历史无效连接请求」,导致数据错乱

TCP连接的SYN包可能因网络延迟滞留(比如客户端发的SYN卡了10分钟),客户端超时后会重发SYN建立新连接。若两次握手:

  • 滞留的旧SYN 10分钟后到达服务器,服务器直接建立连接,向客户端发数据;
  • 但客户端此时的新连接已正常通信,旧连接的无效数据会干扰新连接,导致数据错乱;
  • 三次握手时,客户端收到旧SYN对应的SYN+ACK后,会发ACK拒绝(因为序号不匹配),服务器会释放连接,避免无效连接生效。

四、面试简洁回答模板

Q:TCP三次握手为什么要三次?两次会怎么样?

三次握手核心是双向确认双方收发能力,同步初始序列号,保证可靠连接。两次握手会有两个问题:①无法确认客户端接收能力,服务器会因收不到客户端确认,一直占用资源,导致资源浪费;②无法过滤历史滞留的无效连接请求,可能干扰正常连接,导致数据错乱。三次握手刚好完成双向校验,还能规避这些问题,确保连接可靠。

为什么要四次握手

Q:TCP四次挥手为什么要四次?不能三次吗?

核心原因是TCP是全双工通信,双方的发送通道需要独立关闭。四次挥手的关键是:服务器收到客户端的关闭请求(FIN)时,可能还在发送剩余数据,无法同时确认关闭和自己关闭,因此需要分两步:先回复ACK确认客户端关闭(让客户端等待),等自己数据发完后,再发FIN关闭自己的发送通道。

若强行三次挥手,服务器会被迫同时关闭发送通道,导致未发完的数据丢失;四次挥手通过"确认→发完数据→再关闭"的流程,保证双方数据都能完整传输,优雅释放连接。

先删缓存还是先修改数据库?

可以先删除缓存再更新DB吗?

正常情况

异常情况

可以先更新DB再删除缓存吗?

正常情况

异常情况

加锁能否完全避免?

加锁能通过串行化操作消除并发竞争,缓解大部分一致性问题,但无法完全避免:一是锁可能失效 / 超时,二是删缓存失败仍会导致脏数据,三是加锁会牺牲性能且无法约束外部系统写入。

前端到服务端全链路流程(含域名、IP、传输层、安全层)

Q:请讲一下前端到服务端的整个流程,以及域名、IP、传输层、安全层是怎么运转的?

整个流程核心是"地址解析→连接建立→数据传输→连接释放":

  1. 前端构造请求后,先通过DNS将域名解析为IP(解决"域名易记但网络认IP"的问题);
  2. 基于IP,通过TCP三次握手建立可靠连接,若为HTTPS则额外通过TLS四次握手协商加密(保证数据安全);
  3. 连接建立后,前端通过HTTP/HTTPS协议将请求数据发送到服务端,服务端处理后返回响应(传输层保证可靠,安全层保证加密);
  4. 响应返回后,通过TCP四次挥手释放连接,前端渲染结果。
    其中:域名是易记标识,IP是网络设备唯一标识,传输层(TCP)保证数据可靠传输,安全层(TLS)通过加密和证书验证保证传输安全,四层配合完成从请求到响应的全链路。

DNS 域名解析的核心

DNS域名解析的核心是"先查本地缓存→再由本地DNS递归代理→通过根/顶级/权威服务器迭代指引→最终拿到IP并缓存",全程遵循"递归查结果、迭代指方向"的分工原则,确保高效与可靠。

整个流程分两步:

  1. 客户端先查浏览器/OS缓存,未命中则请求本地DNS递归查询;
  2. 本地DNS先查自身缓存,无则向根服务器问TLD地址,再向TLD问权威地址,最后向权威拿到IP并缓存返回;
    核心是"递归查结果、迭代指方向",根/TLD/权威各司其职,缓存加速查询。

DNS寻址过程是怎样的?如果中间有服务器断联了怎么办?DNS劫持是什么?

DNS寻址、断联处理与DNS劫持全解

一、DNS寻址完整流程(递归+迭代)

DNS寻址核心是"先查本地缓存→本地DNS递归代理→根/TLD/权威迭代指引→最终拿IP并缓存",分工明确、高效可靠。

1. 核心角色分工

角色 定位 核心职责
客户端 发起方 查浏览器/OS缓存→向本地DNS发递归查询→接收IP并缓存
本地DNS 递归代理 代客户端查到底,先查自身缓存,无则逐级迭代查询
根服务器 顶层指引 全球13组(A‑M),只返回顶级域(TLD)地址,不存具体IP
TLD服务器 二级指引 如.com/.cn,返回权威服务器地址
权威服务器 数据源 存储域名与IP的权威映射,返回最终IP(A/AAAA/CNAME等)

2. 详细寻址步骤(以www.example.com为例)

  1. 本地快速命中
    客户端先查浏览器缓存OS缓存 (含hosts文件)→本地DNS缓存,命中则直接返回IP,流程终止。
  2. 本地DNS递归查询
    未命中时,本地DNS向根服务器 发起迭代查询:"www.example.com的IP?"
  3. 根→TLD指引
    根服务器回复:"去问.com TLD服务器,地址是X.X.X.X"。
  4. TLD→权威指引
    本地DNS向.com TLD查询,TLD回复:"example.com的权威服务器是ns1.example.com,地址Y.Y.Y.Y"。
  5. 权威返回IP
    本地DNS向权威服务器查询,权威返回最终IP(如192.0.2.1)。
  6. 结果缓存与返回
    本地DNS缓存结果(按TTL)并返回给客户端,客户端缓存后用于TCP连接。

3. 核心原则

  • 递归+迭代:客户端对本地DNS是递归(要结果),本地DNS对根/TLD/权威是迭代(要指引)。
  • 缓存链:浏览器→OS→本地DNS,缓存由TTL控制,命中可大幅降低解析耗时。

二、中间服务器断联的处理机制

DNS通过冗余设计超时重试保证高可用,某一环节断联时自动切换,具体如下:

1. 不同服务器断联的应对

断联节点 影响范围 系统应对机制 用户/运维处理
本地DNS 单网络/用户 客户端切换备用DNS(如8.8.8.8/114.114.114.114);本地DNS重试其他上游 更换公共DNS,刷新缓存(ipconfig /flushdns
根服务器 全局(极少) 本地DNS自动重试其他根节点(Anycast技术,多节点共享同一IP) 无需操作,依赖DNS软件内置根列表
TLD服务器 某顶级域 本地DNS重试同TLD的其他节点(如.com有多个镜像) 等待TLD恢复,或使用备用DNS
权威服务器 单域名 本地DNS返回缓存结果(若未过期);过期则返回解析失败 域名持有者切换权威服务器,或启用多权威节点冗余

2. 关键保障技术

  • Anycast:多服务器共享同一IP,路由自动引导至最近可用节点,提升冗余与性能。
  • 超时与重试:DNS查询默认超时约5秒,超时后自动重试其他节点或备用DNS。
  • 缓存兜底:各级缓存(尤其本地DNS)在服务器断联时可返回过期但仍可用的结果(视TTL策略)。

三、DNS劫持是什么(原理、类型与危害)

1. 定义

DNS劫持(又称域名劫持)是攻击者通过篡改DNS解析结果,将域名指向恶意IP,导致用户访问被重定向至假冒网站,以窃取信息、植入广告或破坏服务的攻击手段。

2. 常见劫持类型

劫持类型 攻击方式 典型场景
本地劫持 恶意软件篡改OS DNS设置或hosts文件 单设备跳转到广告页,修改DNS为恶意服务器
路由器劫持 入侵路由器修改DNS配置 同一局域网内多设备受影响
中间人劫持 拦截DNS查询并返回伪造响应 公共Wi‑Fi下用户被诱导至钓鱼网站
服务器劫持 攻击本地DNS或权威服务器,篡改缓存/记录 大范围用户解析异常

3. 主要危害

  • 信息窃取:诱导用户输入账号密码、银行卡信息等。
  • 恶意植入:强制访问含病毒、木马的网站。
  • 服务中断:合法网站被劫持导致无法访问。
  • 广告导流:强制推送广告,影响用户体验。

4. 防范措施

  • 使用安全DNS:如Cloudflare(1.1.1.1)、Google DNS(8.8.8.8),避免ISP DNS劫持。
  • 启用加密DNS:DNS over HTTPS(DoH)、DNS over TLS(DoT),防止中间人篡改。
  • 加固本地与路由:定期杀毒,修改路由器默认密码,禁用远程管理。
  • 验证网站证书:访问HTTPS网站时,检查证书是否合法(如域名匹配、颁发机构可信)。

四、面试简洁回答模板

DNS寻址流程

客户端先查本地缓存(浏览器/OS/本地DNS),未命中则由本地DNS递归代理,通过根服务器→TLD服务器→权威服务器的迭代指引拿到最终IP,缓存后返回客户端;核心是"递归查结果、迭代指方向"。

服务器断联处理

DNS通过Anycast冗余、超时重试和缓存兜底应对断联:本地DNS会自动切换备用节点或备用DNS,缓存未过期时可返回旧结果,保障解析可用性。

DNS劫持

攻击者篡改DNS解析结果,将域名指向恶意IP,导致用户访问被重定向至假冒网站;常见类型有本地劫持、路由器劫持、中间人劫持,可通过安全DNS、加密DNS(DoH/DoT)和证书验证防范。

如果客户端发大量 SYN 却不发第三次握手,会发生什么?

这是 SYN 洪水攻击,会耗尽服务端的半连接队列资源:服务端收到 SYN 后会分配资源并进入半连接状态,等待 ACK 超时;大量虚假 SYN 会占满队列,导致正常请求无法建立连接。防御手段包括启用 SYN Cookie、增大半连接队列、防火墙限流等。

应对 SYN 洪水攻击有三种核心手段:① 增大半连接队列,通过调整内核参数扩容队列,容纳更多半连接请求,适合小规模攻击;② SYN Cookie,内核不预先分配资源,通过哈希算法验证合法请求,是大规模攻击的兜底方案;③ 防火墙限流,在前端拦截高频 SYN 报文,从源头减少恶意流量。生产环境通常组合使用这三种方式,层层防护。

linux指令

一、Linux 核心指令与概念详解

1. 查看内存和 CPU 使用情况
(1)查看内存使用
  • free:最常用,展示物理内存/交换分区使用情况

    bash 复制代码
    free -h  # -h 人性化显示单位(KB/MB/GB)

    输出说明:

    • total:总内存;used:已使用;free:空闲;available:可用(含缓存/缓冲区)
    • Swap:交换分区(虚拟内存)使用情况
  • top:实时监控(内存+CPU),默认按 CPU 使用率排序

    • 第一行:系统负载;第二行:进程统计;第三行:CPU 使用率;第四/五行:内存/交换分区使用
(2)查看 CPU 使用
  • top:实时查看 CPU 核心使用率、进程 CPU 占用

    • %Cpu(s) 行:us(用户态)、sy(内核态)、id(空闲)、wa(IO 等待)等
  • mpstat:查看多核 CPU 详细使用率

    bash 复制代码
    mpstat -P ALL  # 展示所有 CPU 核心的使用率
  • pidstat:按进程查看 CPU 使用率

    bash 复制代码
    pidstat -u 1  # 每秒刷新一次进程 CPU 使用
2. load average(系统负载)
  • 含义load average 是 top/uptime 中展示的 3 个数值(1 分钟、5 分钟、15 分钟),表示系统平均负载,即单位时间内处于可运行(R)和不可中断(D)状态的进程数。

  • 解读

    • 对于 N 核 CPU,load average ≤ N 表示负载正常;load average > N 表示系统过载(需结合 1/5/15 分钟趋势,若 15 分钟值持续高,说明负载长期偏高)。
    • 示例:4 核 CPU,load average: 3.2, 4.5, 5.1 → 15 分钟负载 5.1 > 4,系统过载。
  • 查看方式

    bash 复制代码
    uptime  # 直接展示 load average
    top     # 第一行开头也会显示
3. 查找目标进程并 kill
(1)查找进程
  • ps :列出进程(常用组合:ps -ef

    bash 复制代码
    ps -ef | grep java  # 查找包含 java 的进程(grep 过滤)
    # 输出:UID(用户) PID(进程ID) PPID(父进程ID) CMD(命令)
  • pgrep:直接按进程名查 PID(更简洁)

    bash 复制代码
    pgrep java  # 输出所有 java 进程的 PID
(2)终止进程
  • kill:发送信号终止进程(默认 SIGTERM 15,优雅退出;SIGKILL 9 强制杀死)

    bash 复制代码
    kill 12345  # 优雅终止 PID=12345 的进程
    kill -9 12345  # 强制杀死(无法被进程捕获,慎用)
  • killall:按进程名批量终止

    bash 复制代码
    killall -9 java  # 强制杀死所有 java 进程
4. top 指令可以 grep 吗?
  • 直接 grep 不行 :top 是交互式实时界面,stdout 输出特殊,直接 top | grep java 会无正常输出。
  • 替代方案
    1. top 内置过滤 :进入 top 后,按 o 输入 COMMAND=java(按进程名过滤),或按 u 输入用户名(按用户过滤)。

    2. 批处理模式 :top 加 -b(批处理)、-n 1(只输出一次),再 grep:

      bash 复制代码
      top -b -n 1 | grep java  # 非交互式输出一次,再过滤
5. 文件权限:rwx 含义 & 用户权限分类
(1)rwx 含义(读/写/执行)
符号 权限 数字标识 文件含义 目录含义
r 4 可读取文件内容 可列出目录下文件(ls)
w 2 可修改/删除文件 可创建/删除/重命名目录内文件
x 执行 1 可执行文件(如脚本/二进制) 可进入目录(cd)
  • 示例:-rwxr-xr-- 解析:
    • 第一位 -:文件类型(- 普通文件,d 目录,l 软链接);
    • 第2-4位 rwx:文件所有者(user)权限;
    • 第5-7位 r-x:所属组(group)权限;
    • 第8-10位 r--:其他用户(other)权限。
(2)用户权限分类

Linux 文件权限分为三类用户:

  1. 所有者(User) :文件/目录的创建者或指定用户(chown 修改);
  2. 所属组(Group) :用户组(chgrp 修改);
  3. 其他用户(Other):既非所有者,也不在所属组的所有用户。
  • 查看权限:ls -l 文件名
  • 修改权限:chmod 755 文件名(7=4+2+1,即 rwx;5=4+1,即 r-x)
6. 查看端口是否被占用(lsof / netstat)
(1)lsof(列出打开的文件,Linux 万物皆文件,端口也属于文件)
bash 复制代码
lsof -i:8080  # 查看 8080 端口被哪个进程占用
# 输出:COMMAND(进程名) PID(进程ID) USER(用户) FD(文件描述符) TYPE DEVICE SIZE/OFF NODE NAME
  • 参数:-i 表示网络连接,:端口号 指定端口;-i tcp 可过滤 TCP 端口。
(2)netstat(备选,部分系统默认未安装)
bash 复制代码
netstat -tulpn | grep 8080
# -t:TCP;-u:UDP;-l:监听中;-p:显示进程;-n:数字显示端口/IP
7. 设定定时任务(crontab)
(1)crontab 基本语法
bash 复制代码
crontab -e  # 编辑当前用户的定时任务(首次编辑需选择编辑器,推荐 vim)
  • 任务格式:* * * * * 命令/脚本路径
    五个 * 分别代表:分(0-59)、时(0-23)、日(1-31)、月(1-12)、周(0-7,0/7 均为周日)。
  • 特殊符号:
    • *:每单位时间;*/5:每 5 个单位(如 */5 * * * * 每 5 分钟);
    • ,:枚举(如 1,30 * * * * 每分钟 1 和 30 分);
    • -:范围(如 1-5 * * * * 每小时 1-5 分)。
(2)示例
bash 复制代码
# 每天凌晨 2 点执行备份脚本
0 2 * * * /usr/local/backup.sh

# 每周一到周五 18:00 清理日志
0 18 * * 1-5 rm -rf /var/log/app/*.log

# 每 10 分钟检查一次服务状态
*/10 * * * * /usr/local/check_service.sh
(3)其他常用命令
bash 复制代码
crontab -l  # 列出当前用户的定时任务
crontab -r  # 删除当前用户的所有定时任务
  • 注意:定时任务的输出默认会发邮件给用户,可在命令后加 > /dev/null 2>&1 屏蔽输出(/dev/null 是黑洞,2>&1 重定向错误输出到标准输出)。
8. 软链接 vs 硬链接(核心区别)
维度 硬链接(Hard Link) 软链接(Symbolic Link,符号链接)
本质 给文件 inode 新增文件名映射(共享 inode) 独立文件,存储原文件的路径(类似快捷方式)
inode 与原文件相同 独立 inode
跨文件系统 不支持(仅同一分区) 支持(可跨分区/远程)
链接对象 仅支持文件(不可链接目录) 支持文件/目录
原文件删除 硬链接仍有效(inode 引用计数 > 0) 软链接失效(红色闪烁)
文件大小 与原文件一致 极小(仅存储路径字符串)
创建命令 ln 原文件 硬链接文件 ln -s 原文件 软链接文件
  • 示例:

    bash 复制代码
    # 硬链接
    ln /test/file.txt /test/file_hard
    # 软链接
    ln -s /test/file.txt /test/file_soft

二、面试简洁回答模板(关键问题)

1. 查看内存/CPU 使用

查看内存用 free -h 人性化展示,top 实时监控;查看 CPU 用 top 看核心使用率,mpstat 看多核详情,pidstat 按进程统计。

2. load average 含义

系统平均负载,代表单位时间内可运行和不可中断的进程数,N 核 CPU 下,值 ≤ N 正常,> N 表示过载,需结合 1/5/15 分钟趋势判断。

3. 查找并 kill 进程

ps -ef | grep 进程名pgrep 进程名 查 PID,再用 kill PID 优雅终止,kill -9 PID 强制杀死。

4. 文件权限 rwx & 用户分类

r 读、w 写、x 执行,对应数字 4、2、1;权限分所有者(User)、所属组(Group)、其他用户(Other)三类,用 ls -l 查看。

5. 查看端口占用

lsof -i:端口号netstat -tulpn | grep 端口号lsof 更常用,能直接显示占用进程。

6. 定时任务

crontab -e 编辑,格式为 分 时 日 月 周 命令crontab -l 查看,crontab -r 删除。

7. 软/硬链接区别

硬链接共享 inode,删原文件仍有效,不支持目录和跨分区;软链接是独立文件,存原路径,删原文件失效,支持目录和跨分区,日常用软链接更多。

三、总结

以上是 Linux 运维/开发高频指令和概念,核心需掌握:

  • 资源监控(top/free/mpstat)、进程/端口管理(ps/lsof/netstat/kill);
  • 权限与链接(rwx/用户分类/软硬链接);
  • 定时任务(crontab 语法);
  • 负载解读(load average)。

ES 慢查询优化

ES 查询变慢的排查思路分四步:① 先通过慢查询日志和 Profile 分析定位慢查询的语句和耗时步骤;② 优化查询语句,避免 wildcard 前缀、深度分页、复杂脚本等低效写法;③ 检查索引设计,合理设置 Mapping、分词器和分片;④ 排查集群资源瓶颈,包括 CPU、内存、磁盘 IO、网络,针对性扩容或优化配置。核心原则是 "先优化软件,再扩容硬件"。

mysql会出现死锁吗?大概什么场景,什么原因?有什么解决的办法吗?

一、MySQL 会出现死锁吗?

,且死锁是 MySQL(尤其是 InnoDB 存储引擎)在并发场景下的常见问题。

InnoDB 是行级锁引擎,并发事务对不同行/间隙加锁时,若出现循环等待锁资源的情况,就会触发死锁。MyISAM 因是表级锁,锁冲突时只会出现阻塞而非死锁,因此死锁主要发生在 InnoDB 中。

二、死锁的核心原因与典型场景

1. 死锁的核心条件(必须同时满足)

根据经典的"死锁四大条件",MySQL 死锁需满足:

  • 互斥条件:锁资源只能被一个事务持有(如行锁排他);
  • 请求与保持条件:事务持有部分锁,又请求新的锁;
  • 不可剥夺条件:锁不能被强制剥夺,只能由持有事务主动释放;
  • 循环等待条件:多个事务形成锁资源的循环等待链(核心条件,打破即可避免死锁)。
2. 典型死锁场景
场景1:事务加锁顺序不一致(最常见)

两个事务对同一批记录的加锁顺序相反,形成循环等待。

sql 复制代码
-- 表结构:user(id INT PRIMARY KEY, name VARCHAR(20))
-- 数据:id=1, id=2

-- 事务 A
BEGIN;
UPDATE user SET name='A1' WHERE id=1; -- 持有 id=1 的行锁
UPDATE user SET name='A2' WHERE id=2; -- 请求 id=2 的行锁,被事务 B 阻塞

-- 事务 B
BEGIN;
UPDATE user SET name='B2' WHERE id=2; -- 持有 id=2 的行锁
UPDATE user SET name='B1' WHERE id=1; -- 请求 id=1 的行锁,被事务 A 阻塞

结果:事务 A 等事务 B 释放 id=2,事务 B 等事务 A 释放 id=1,形成循环等待,触发死锁。

场景2:间隙锁导致的循环等待

InnoDB 可重复读隔离级别下,间隙锁与行锁结合(临键锁),扩大了锁范围,易引发死锁。

sql 复制代码
-- 表结构:user(id INT, age INT, INDEX idx_age(age))
-- 数据:age=10, age=20

-- 事务 A
BEGIN;
SELECT * FROM user WHERE age > 10 AND age < 20 FOR UPDATE; -- 锁定间隙 (10,20)
INSERT INTO user(age) VALUES(15); -- 若事务 B 已锁定部分间隙,会阻塞

-- 事务 B
BEGIN;
SELECT * FROM user WHERE age > 5 AND age < 15 FOR UPDATE; -- 锁定间隙 (5,10)
INSERT INTO user(age) VALUES(12); -- 被事务 A 的间隙锁阻塞,同时事务 A 也等待事务 B,形成死锁
场景3:跨表加锁顺序不一致

多个事务操作多张表,加表锁/行锁的顺序相反。

sql 复制代码
-- 事务 A:先锁 user 表,再锁 order 表
BEGIN;
UPDATE user SET name='A' WHERE id=1;
UPDATE `order` SET status=1 WHERE user_id=1;

-- 事务 B:先锁 order 表,再锁 user 表
BEGIN;
UPDATE `order` SET status=2 WHERE user_id=1;
UPDATE user SET name='B' WHERE id=1;

结果:事务 A 持有 user 锁、等 order 锁;事务 B 持有 order 锁、等 user 锁,触发死锁。

场景4:长事务持有锁过久

长事务长时间占用锁资源,其他事务排队等待锁时,易形成复杂的锁等待链,最终触发死锁。

  • 例如:事务 A 执行后未及时提交(如忘记 COMMIT),持有 id=1 的锁;事务 B 持有 id=2 的锁并等待 id=1;事务 C 持有 id=3 的锁并等待 id=2;事务 A 此时请求 id=3 的锁,形成循环等待。

三、死锁的排查方法

1. 查看死锁日志

MySQL 会记录死锁信息到日志,可通过以下方式查看:

sql 复制代码
-- 方式1:查看最新死锁详情(InnoDB 内置)
SHOW ENGINE INNODB STATUS;

输出中 LATEST DETECTED DEADLOCK 部分会包含:

  • 死锁涉及的事务 ID、加锁语句;
  • 锁等待的资源、循环等待链;
  • 最终被回滚的事务(InnoDB 会自动回滚其中一个事务,打破死锁)。
2. 开启死锁监控
sql 复制代码
-- 开启死锁监控(MySQL 8.0+ 推荐)
SET GLOBAL innodb_print_all_deadlocks = ON;

该参数会将所有死锁信息写入 MySQL 错误日志(默认路径:/var/log/mysqld.log),方便长期排查。

四、死锁的解决与预防方案

1. 核心原则:打破"循环等待条件"(最有效)
  • 统一加锁顺序 :所有事务对记录/表的加锁顺序保持一致(如按 ID 升序、表名字典序加锁)。
    示例:无论哪个事务,都先更新 id=1 再更新 id=2,避免顺序相反。
  • 缩小锁范围
    • 尽量使用唯一索引(避免间隙锁,临键锁降级为行锁);
    • 避免大范围 UPDATE/DELETE(如 WHERE age > 0 会锁定全表间隙);
    • 非必要时,将隔离级别从 REPEATABLE READ 降为 READ COMMITTED(关闭间隙锁,仅用行锁)。
2. 优化事务设计
  • 缩短事务时长:事务仅包含必要的 SQL 语句,避免在事务中执行耗时操作(如 RPC 调用、用户交互),减少锁持有时间。
  • 批量操作拆分:大批量更新拆分为多个小事务(如每次更新 100 条记录),降低锁冲突概率。
  • 主动释放锁 :及时 COMMIT/ROLLBACK,避免长事务占用锁资源。
3. 代码层面的防护
  • 添加重试机制 :捕获死锁错误(MySQL 错误码:1213),自动重试事务(注意重试次数,避免无限循环)。
    示例(Java):

    java 复制代码
    int retryCount = 3;
    while (retryCount > 0) {
        try (Connection conn = getConnection()) {
            // 执行事务逻辑
            conn.setAutoCommit(false);
            updateUser(conn, 1);
            updateUser(conn, 2);
            conn.commit();
            break;
        } catch (SQLTransactionRollbackException e) {
            // 捕获死锁异常,重试
            retryCount--;
            Thread.sleep(100); // 短暂等待后重试
        }
    }
  • 使用乐观锁替代悲观锁 :对并发更新的场景,用版本号(version)实现乐观锁,避免加行锁。

    sql 复制代码
    -- 乐观锁更新:仅当版本号匹配时更新,无锁冲突
    UPDATE user SET name='new', version=version+1 WHERE id=1 AND version=5;
4. 数据库配置优化
  • 设置锁等待超时 :避免事务无限期等待锁,超时后主动回滚。

    sql 复制代码
    SET GLOBAL innodb_lock_wait_timeout = 5; -- 单位:秒,默认 50 秒,可根据业务调整
  • 关闭不必要的间隙锁 :将隔离级别设为 READ COMMITTED(需业务接受不可重复读)。

    sql 复制代码
    SET GLOBAL transaction_isolation = 'READ-COMMITTED';
5. 事后处理:分析死锁日志并优化
  • 从死锁日志中定位冲突的 SQL 和锁资源;
  • 调整 SQL 语句(如添加索引、缩小查询范围),避免不必要的锁;
  • 优化事务逻辑,消除循环等待的可能。

五、面试简洁回答模板

Q:MySQL 会出现死锁吗?什么场景、原因?如何解决?

MySQL(InnoDB)会出现死锁,核心原因是并发事务形成循环等待锁资源的闭环(满足死锁四大条件)。

典型场景:① 事务加锁顺序不一致;② 间隙锁导致锁范围扩大;③ 跨表加锁顺序相反;④ 长事务持有锁过久。

解决与预防方案:① 统一加锁顺序,打破循环等待;② 缩小锁范围(用唯一索引、降低隔离级别);③ 缩短事务时长,避免长事务;④ 代码层添加死锁重试机制,或用乐观锁替代悲观锁;⑤ 配置锁等待超时,及时排查死锁日志并优化 SQL。

六、总结

死锁的本质是"循环等待锁资源",因此预防的核心是打破循环等待 (统一加锁顺序),辅以缩小锁范围、优化事务设计等手段;排查的关键是利用 SHOW ENGINE INNODB STATUS 分析死锁日志,定位根因后针对性优化。

锁的级别有哪些?

锁的级别主要从粒度、读写属性、场景三个维度划分:

按粒度:表级锁(粒度大、并发低)、行级锁(粒度小、并发高,InnoDB 核心)、页级锁(介于两者之间,极少用),InnoDB 还特有间隙锁 / 临键锁(解决幻读);

按读写属性:共享锁(读锁,不互斥)、排他锁(写锁,互斥),以及 InnoDB 意向锁(协调表锁与行锁);

按场景:乐观锁(版本号机制,无锁)、悲观锁(传统加锁,阻塞),还有分布式锁(跨节点资源协调)。

其中,InnoDB 以行级锁为核心,结合间隙锁 / 临键锁实现高并发与数据一致性,是生产环境的主流选择。

从锁的角度分析慢查询的原因及解决方法?

从锁的角度,慢查询的核心原因是查询等待锁资源的时间过长:① 行锁竞争(高并发更新同一行、非索引查询导致行锁升级为表锁);② 间隙锁 / 临键锁扩大锁范围,增加冲突;③ 表锁(MyISAM 或显式表锁)导致读写阻塞;④ 长事务持有锁过久,阻塞后续操作。解决方法:① 确保 SQL 命中索引,缩小锁范围,统一加锁顺序;② 缩短事务时长,拆分长事务,及时提交;③ 改用 InnoDB 引擎,降低隔离级别关闭间隙锁;④ 高并发场景用乐观锁替代悲观锁,或分库分表分散锁竞争;⑤ 设置锁等待超时,监控并处理长事务。

websocket

一、WebSocket 的典型应用场景

WebSocket 是全双工、长连接 的通信协议,核心解决了 HTTP 无法主动推送数据的痛点,适用于需要实时双向交互的场景,具体包括:

  1. 实时消息与通信类
    • 即时聊天:网页版聊天工具、在线客服系统(如网页微信、钉钉客服)。客户端发送消息后,服务器可实时推送给接收方,无需客户端频繁查询。
    • 协同办公:多人在线文档(腾讯文档、飞书文档)、共享白板。用户的编辑操作可实时同步给其他协作者,实现无延迟协作。
  2. 实时数据推送类
    • 金融行情:股票、期货、加密货币的实时价格推送。服务器数据更新后立即推送给客户端,延迟可低至毫秒级,远优于轮询。
    • 物联网(IoT)监控:智能设备状态上报(如电表读数、工业传感器数据)、远程设备控制。设备可主动上报数据,服务器也可下发控制指令,双向实时通信。
    • 系统监控告警:运维监控面板(如服务器 CPU/内存使用率)、故障告警。服务器发现异常后立即推送告警信息,无需客户端定时拉取。
  3. 实时互动类
    • 在线游戏:网页版多人游戏(棋牌、休闲竞技)。玩家操作需实时同步到服务器,并推送给其他玩家,低延迟是关键。
    • 直播互动:直播弹幕、礼物打赏通知。弹幕消息可实时推送给所有观众,提升互动体验。
  4. 高频数据交互类
    • 实时表单验证:注册时实时检查用户名是否已被占用,无需用户点击"验证"按钮。
    • 投票/抽奖实时结果:活动投票数据实时更新,中奖信息即时推送。

二、WebSocket 与 HTTP 轮询的核心差异

HTTP 轮询是基于"请求-响应"模型的伪实时 方案,分为 短轮询长轮询(Long Polling),与 WebSocket 的差异主要体现在以下维度:

特性 WebSocket HTTP 短轮询 HTTP 长轮询(Long Polling)
连接模式 一次握手建立长连接,连接持续至主动关闭 每次请求建立新 HTTP 连接,响应后立即断开 建立连接后服务器挂起请求,有数据/超时后断开,再重连
通信方向 全双工(客户端/服务器可同时收发) 半双工(客户端主动请求,服务器被动响应) 半双工(仍需客户端先发起请求)
数据推送方式 服务器可主动推送,无需客户端触发 客户端定时发起请求拉取数据 服务器有数据时响应,无数据则挂起请求
协议开销 握手用 HTTP,后续传输轻量级帧(头部仅 2~10 字节) 每次请求携带完整 HTTP 头部(Cookie、User-Agent 等),冗余数据多 仍需携带完整 HTTP 头部,仅减少请求频率
延迟 极低(毫秒级,实时推送) 高(延迟等于轮询间隔,如 5 秒轮询则最大延迟 5 秒) 较低(有数据时立即响应,无数据则超时延迟)
服务器资源消耗 单连接处理双向通信,连接数少,资源消耗低 频繁建立/断开 TCP 连接,握手/挥手开销大 连接挂起时占用服务器线程,高并发下线程易耗尽

三、WebSocket 性能优于 HTTP 轮询的核心原因

WebSocket 性能更优的本质是减少了底层网络开销和协议冗余,具体可拆解为 4 点:

  1. 减少 TCP 三次握手/四次挥手的开销(核心)

    • HTTP 轮询(短/长):每次请求都要经历 TCP 三次握手建立连接 → 传输数据 → TCP 四次挥手断开连接。高频轮询下,服务器需要频繁处理连接的建立与销毁,CPU 和端口资源消耗巨大。
    • WebSocket:仅在初始化时进行一次 HTTP 握手(底层是 TCP 三次握手),之后复用该 TCP 长连接进行双向通信,直到主动关闭才触发四次挥手,彻底避免了频繁连接的开销。
  2. 降低协议头部的冗余数据

    • HTTP 协议:每次请求/响应都携带完整的头部信息(如 Host、Cookie、Content-Type 等),头部大小通常远大于实际传输的数据(例如 1 字节的"心跳"数据,HTTP 头部可能占几百字节),带宽利用率极低。
    • WebSocket:握手完成后,数据传输采用轻量级的帧协议,头部仅 2~10 字节,还支持数据压缩,大幅减少了冗余数据,提升了传输效率。
  3. 消除轮询延迟,实现真正实时

    • HTTP 短轮询:客户端需定时发起请求(如每 1 秒/5 秒),若服务器数据在两次轮询之间更新,客户端无法立即获取,存在"轮询间隔延迟",且频繁请求会浪费带宽。
    • HTTP 长轮询:虽减少了请求频率,但服务器挂起请求时会占用线程资源,高并发下易导致线程池耗尽;且请求超时后仍需重连,存在一定延迟。
    • WebSocket:服务器数据更新时可立即推送,无需客户端触发,延迟几乎为零,完美适配实时场景。
  4. 全双工通信提升交互效率

    HTTP 轮询(包括长轮询)本质是半双工 ,客户端和服务器无法同时收发数据;而 WebSocket 是全双工,客户端发送消息的同时,服务器可推送其他数据,例如聊天时,你发送消息的同时,能实时收到其他人的消息,无需等待当前请求完成。

总结

  • WebSocket 适用于高实时性、双向交互的场景,核心优势是服务器可主动推送、低延迟、低开销;
  • 与 HTTP 轮询的核心差异在于连接模式(长连接 vs 短连接)、通信方向(全双工 vs 半双工)、协议开销
  • 性能更优的根本原因是减少了 TCP 连接的建立/销毁开销、降低了协议冗余、消除了轮询延迟

要不要我帮你整理一份 WebSocket 与 HTTP 轮询的选型对比表,方便你在项目中快速决策?

相关推荐
前端布鲁伊10 小时前
聊聊前端容易翻车的“环境管理”
前端·面试
用户120391129472612 小时前
彻底搞定大模型流式输出:从二进制碎块到“嘚嘚嘚”打字机效果,让底层逻辑飞起来
前端·javascript·面试
Swift社区13 小时前
LeetCode 443. 压缩字符串
leetcode·职场和发展·蓝桥杯
ada7_13 小时前
LeetCode(python)——543.二叉树的直径
数据结构·python·算法·leetcode·职场和发展
sprintzer13 小时前
11.26-12.05力扣栈刷题
算法·leetcode·职场和发展
kingmax5421200813 小时前
高中数学试讲稿:《对数与指数之间的相互转化》
面试·教师资格
over69714 小时前
深入解析:基于 Vue 3 与 DeepSeek API 构建流式大模型聊天应用的完整实现
前端·javascript·面试
前端小白在前进14 小时前
力扣刷题:无重复字符的最长子串
算法·leetcode·职场和发展
NPE~14 小时前
面试高频——分布式事务详解
分布式·面试·职场和发展·程序员·事务·分布式事务