综合性能与故障场景题

共 18 题
📑 题目列表 18 题
#
★★★

1. 线上 CPU 100% 的排查路径,从 top 到火焰图的完整工具链如何使用?

线上服务器 CPU 使用率达到 100% 时,如何从 top 开始逐层定位到具体线程和代码路径,并利用火焰图等工具完成完整的排查?

  • 熟悉 top、pidstat、perf、jstack 等工具的使用与定位思路
  • 能够区分用户态 CPU、内核态 CPU、上下文切换与 IO 等待
  • 掌握火焰图(Flame Graph)的生成与解读方法

排查路径通常分四步:第一步用 top 确认总 CPU 占用高的进程,记录 PID 并观察 %us、%sy、%wa 等指标,判断是用户态计算密集还是内核态/IO 等待。第二步用 top -Hp 或 pidstat -t 定位到具体线程。第三步用 jstack 抓取 Java 线程栈,或用 perf record -p -g 采样生成调用栈,再用 perf script 配合 FlameGraph 工具(stackcollapse-perf.pl + flamegraph.pl)生成火焰图,直观看到哪个函数占用的 CPU 栈面积最大。第四步结合业务代码定位热点,如循环、正则、序列化、锁竞争或 GC 频繁。

火焰图的宽度代表函数累计 CPU 时间占比,最宽的平台即为热点,能快速从"现象"收敛到"代码行"。关键是先分层(进程→线程→代码),避免盲目优化。若 %sy 高则关注系统调用与锁,若 %wa 高则转向 IO 而非 CPU。

#
★★★

2. 接口延迟突增但 CPU/内存正常时,如何从网络、锁、GC、IO 分层定位?

接口响应延迟突然升高,但进程 CPU 与内存使用率都正常时,应如何从网络、锁、GC、IO 等多个维度分层排查定位根因?

  • 理解延迟与资源利用率脱节的常见原因
  • 掌握网络、锁、GC、IO 四类瓶颈的排查手段
  • 学会用 trace、日志、监控指标交叉验证

CPU/内存正常而延迟高,说明瓶颈不在计算资源本身,而在"等待"。按层排查:一层看网络,用 ping/ss 检查丢包、重传、RTT,确认是否网络拥塞或对端耗时。二层看锁,用 jstack 看是否有线程长时间 BLOCKED/WAITING,判断锁竞争与死锁。三层看 GC,分析 GC 停顿(STW)是否频繁、是否过长。四层看 IO,用 iostat 看磁盘等待、用数据库慢查询看 SQL 是否变慢。最后用 Trace 工具定位到底哪一段耗时占比最大。

延迟 = 计算时间 + 等待时间,资源空闲时延迟高几乎必然是等待类问题(锁竞争、GC、网络、IO、下游慢)。用链路追踪把总耗时拆解到各调用段,能快速锁定"等待发生在哪一段"。

#
★★★

3. 进程处于 D 状态(不可中断睡眠)无法 kill 的排查,如何定位阻塞在哪个内核路径(IO 等待或锁),如何处理?

进程处于 D 状态(不可中断睡眠)且无法 kill 时,应如何定位其阻塞在内核的哪个路径(IO 等待还是内核锁),以及如何处理?

  • 理解 D 状态(不可中断睡眠)与 S 状态(可中断睡眠)的区别
  • 掌握 /proc、ps 等定位 D 状态进程的方法
  • 了解 IO 等待与内核锁阻塞的区分与处理手段

D 状态是进程在内核中不可中断地等待某个条件(多为磁盘 IO 或内核锁),此时信号无法送达,kill 无效。排查时先用 ps -eo pid,stat,wchan:30,comm 查看 wchan(等待的内核函数),wchan 指向类似 io_schedule、lock_sock 等,可判断是 IO 等待还是内核锁。再通过 /proc/ /stack 和 /proc/ /wchan 查看内核栈,用 /proc//io 看读写字节变化判断 IO 是否卡住。若为磁盘 IO 等待,检查磁盘是否异常、是否拔盘或网络盘(NFS/iSCSI)失联;若为内核锁,检查内核 Bug 或死锁。处理上:等待 IO 恢复后进程自然退出,无法 kill 时只能等待或重启系统。

D 状态与 S(可中断睡眠)的本质区别是:D 状态不响应信号,只能等待内核让条件成立;S 状态可被信号唤醒。定位关键是看 wchan/内核栈,把"阻塞在哪"从黑盒变成可观测。D 状态长期大量存在往往意味着底层存储故障。

#
★★★

4. 网络丢包/重传导致接口延迟变高的定位,如何用 ss -s 重传统计与抓包确认,丢包与重传对延迟分位的影响如何?

网络丢包与重传导致接口延迟变高时,如何用 ss -s 重传统计与抓包确认,以及丢包和重传对延迟分位(P99)的影响?

  • 掌握 ss -s 与 ss -ti 的协议统计解读
  • 会用 tcpdump/Wireshark 抓包确认重传与丢包
  • 理解重传对延迟分位(尤其是 P99)的放大效应

先用 ss -s 查看 TCP 全局统计,关注 retrans(重传数);用 ss -ti 查看每条连接的 rtt、retrans 与队列长度。若发现重传计数快速上升,用 tcpdump -i eth0 tcp and port 抓包,在 Wireshark 中通过 TCP Retransmission、Dup ACK、Out-of-Order 等标记确认丢包与重传。丢包触发重传后,RTO 超时(指数退避)或快速重传会显著拉长尾延迟:少量丢包对平均延迟影响有限,但会让 P99 剧烈抬升,因为重传把少数请求的耗时放大到 RTO 级别(几百毫秒到秒级)。

重传是尾延迟的放大器。平均延迟看常见路径,P99 看最坏情形,一次 RTO 重传就可能把 P99 从几毫秒拉到几百毫秒。定位上先用 ss 看统计,再抓包确认,最后配合监控曲线看 P99 是否与重传时间点吻合。

#
★★

5. 内存持续增长的进程如何区分"泄漏"与"正常缓存增长",如何取证?

进程内存持续增长时,如何区分是真正的内存泄漏还是正常的缓存/内存池增长,并如何进行取证?

  • 理解内存泄漏与缓存增长的判别标准
  • 掌握堆 dump、内存监控与 GC 日志的取证方法
  • 学会用"长期稳态"与"趋势"判断是否泄漏

关键在于观察增长后是否收敛。正常缓存或连接池增长会达到一个稳态上界(水位),随后趋于平稳;真正的泄漏则持续单调上升,直至 OOM。取证方法:一是用监控工具记录 RSS/堆内存随时间曲线,看是否收敛;二是用 jmap -dump 导出堆 dump,用 MAT 分析 dominator tree,找出占用最大且持续增长的类;三是看 GC 日志中 GC 后堆是否回不到基线,若每次 GC 后残留量不断抬高即泄漏。对非 JVM 进程用 pmap/gdb 或 valgrind 分析分配。

泄漏的本质是"无法回收的对象/内存持续累积",而缓存是"增长到上限后保持"。判别核心是"是否收敛到稳态",配合 GC 日志观察 GC 后存活对象基线是否逐次抬升,是最可靠的取证手段。

#
★★

6. 分布式调用超时的排查,如何结合 Trace 与依赖关系图缩小范围?

分布式系统中某个调用持续超时,如何结合链路追踪(Trace)与依赖关系图缩小根因范围?

  • 理解 TraceID、Span、调用链的粒度
  • 会用依赖图与调用方/被调方视角缩小范围
  • 掌握超时与异常、抖动、依赖故障的区分

先用 Trace 系统拉取该 TraceID 的完整调用链,逐 span 对比各段耗时,找出耗时最长的 span。若某段耗时接近整体超时,说明根因在该服务或下游;再结合依赖关系图(服务拓扑)看该服务调用了哪些下游。区分三种情况:上游等待(本服务排队)、自身处理慢(CPU/GC/锁)、下游慢(DB/Redis/第三方)。通过 Trace 的 span 时间戳与埋点(如 DB 查询、HTTP 调用)进一步定位到具体资源。若超时是偶发,配合错误率与延迟分位曲线判断是抖动还是持续性故障。

分布式定位的核心是"沿着调用链把总耗时逐段拆解",Trace 的每个 span 就是一段可量化的耗时,依赖图则展示调用关系,两者结合能把问题从"整个系统"收敛到"某个服务、某个资源"。避免盲目重试放大故障。

#
★★

7. 磁盘 IO 成为瓶颈时,如何用 iostat/iotop/pidstat 定位到具体进程与文件?

当磁盘 IO 成为系统瓶颈时,如何用 iostat、iotop、pidstat 等工具定位到具体进程与文件?

  • 掌握 iostat 读磁盘整体利用率与 await/util
  • 会用 iotop/pidstat 定位高 IO 进程
  • 会用 lsof 定位具体文件

先用 iostat -x 1 查看磁盘 util% 与 await、svctm,判断磁盘是否达瓶颈(util% 接近 100%);再用 iotop -o 实时查看哪些进程的 IO 读写速率最高,或用 pidstat -d 1 查看各进程的 KB_rd/s、KB_wr/s。锁定高 IO 进程后,用 lsof -p 或 /proc//fd 查看该进程打开的文件,结合业务日志判断是哪个文件在频繁读写。若无法定位到进程,可用 iostat -x 看磁盘 io 队列,配合 blktrace 做更细粒度的 IO 跟踪。

定位遵循"磁盘→进程→文件"逐层收敛:iostat 确认磁盘级别瓶颈,iotop/pidstat 定位到进程,lsof/文件路径再定位到具体文件。util% 高说明磁盘饱和,但需结合 await 判断是请求排队还是设备本身慢。

#
★★

8. CPU 使用率 100% 但系统响应慢的排查路径,如何区分计算密集、上下文切换、锁竞争与 IO 等待?

CPU 使用率达到 100% 但系统响应变慢时,如何区分是计算密集、上下文切换过多、锁竞争还是 IO 等待导致的?

  • 理解 %us、%sy、%wa、%si 等 CPU 指标含义
  • 掌握 vmstat/sar 观察上下文切换与运行队列
  • 区分忙等待与真正计算的定位方法

先用 top 或 sar 看 CPU 各项拆分:%us 高说明用户态计算密集;%sy 高说明系统调用/内核态开销大;%wa 高说明 IO 等待;%si 高说明软中断多。用 vmstat 1 观察 run queue(r 列)与上下文切换(cs 列),若 r 大于核数说明 CPU 被打满,若 cs 极高说明切换频繁。遇到锁竞争,可用 jstack 转储看线程 BLOCKED 状态,或 perf 看 spinlock 热点。若 %us 高但业务无实际吞吐,可能是在忙循环(自旋)空转。综合时间线交叉判断是哪一类占主导。

关键是把"CPU 100%"这一总指标拆成 us/sy/wa/si 细分,再结合运行队列与上下文切换判断。计算密集是"真正在工作",上下文切换是"在切换中浪费",锁竞争是"忙等或阻塞",IO 等待是"在排队"——不同根因的治理手段完全不同。

#
★★

9. 内存持续增长的定位,堆内/堆外、JVM/非 JVM 进程、缓存与连接池泄漏如何逐层排查?

进程内存持续增长时,如何从堆内/堆外、JVM/非 JVM 进程、缓存与连接池泄漏等维度逐层排查?

  • 区分堆内存、堆外内存(DirectBuffer、元空间)与 Native 内存
  • 掌握 JVM 内存监控与 Native 内存分析工具
  • 识别缓存与连接池泄漏的常见模式

先判断是 JVM 还是非 JVM 进程。若是 JVM,监控堆内存(jstat -gc)、GC 日志与堆 dump 定位堆内泄漏;若堆内存正常但 RSS 持续增长,则怀疑堆外/Native 内存,检查 DirectBuffer(-XX:MaxDirectMemorySize)、元空间(Metaspace)、线程栈、JNI 与第三方库(如 netty 的堆外缓存)。非 JVM 进程用 pmap/valgrind。缓存泄漏常见于静态集合、ThreadLocal 未清理、缓存 key 未设过期;连接池泄漏见于未归还连接导致连接数持续增长。逐层用"堆内→堆外→native→业务资源"的漏斗排查,每层用对应工具取证。

内存增长不等于堆泄漏,堆外与 Native 内存很容易被忽略。排查要按"堆内 vs 堆外 vs Native"分层,配合 RSS 与堆指标的对比:RSS 持续涨而堆稳定,说明问题在堆外。缓存与连接池这类"有界资源"泄漏的特点是无界增长且无法回收。

#
★★

10. 连接与文件描述符泄漏的排查,如何用 ss/lsof 发现 fd 增长,TIME_WAIT 与 CLOSE_WAIT 分别对应什么问题?

连接与文件描述符泄漏如何排查?如何用 ss/lsof 发现 fd 增长,以及 TIME_WAIT 与 CLOSE_WAIT 各对应什么问题?

  • 掌握 ss/lsof 查看连接与 fd 数量的方法
  • 理解 TIME_WAIT 与 CLOSE_WAIT 的成因与语义差异
  • 掌握 fd 泄漏的定位与处理

用 ss -s 查看系统连接总数,用 ss -tn state 统计各状态数量;用 lsof -p | wc -l 或 /proc//fd 统计 fd 数量,观察是否随时间单调增长。TIME_WAIT 是由主动关闭方在收到 FIN 后进入的等待状态,用于确保旧报文在网络中消失,大量 TIME_WAIT 通常来自高并发短连接(如频繁创建连接),可通过连接复用(keep-alive)缓解。CLOSE_WAIT 是被动关闭方收到 FIN 后未调用 close 关闭套接字导致的状态,说明应用层没有释放连接,属于典型的 fd 泄漏:CLOSE_WAIT 持续增长多半是代码没正确关闭连接。

TIME_WAIT 是主动关闭方的正常状态,数量大说明连接被频繁建立/关闭;CLOSE_WAIT 是被动关闭方的异常残留,代表应用未 close,是 fd 泄漏的直接信号。fd 增长定位用 lsof 找未关闭的 fd 及其来源,配合代码审查修复。

#
★★

11. GC 频繁与 Full GC 的排查,如何结合 GC 日志、堆 dump 与对象分配速率定位大对象或内存泄漏?

GC 频繁与 Full GC 时,如何结合 GC 日志、堆 dump 与对象分配速率定位大对象或内存泄漏?

  • 掌握 GC 日志解读(Young GC/Full GC 频次与耗时)
  • 会用堆 dump 与 MAT 分析对象引用
  • 理解分配速率与存活对象的关系

先开启并分析 GC 日志,看 Young GC 频次、Full GC 频次与单次停顿时间,判断是否频繁元空间不足、大对象直接进老年代或老年代持续增长。用 jstat -gcutil 看各代使用率变化。若每次 GC 后老年代占用都不降,说明有无法回收的对象(存活对象泄漏),用 jmap -dump 导出堆,用 MAT 分析 Dominator Tree 找到 GC root 引用链上占内存最大的对象。同时观察对象分配速率,若分配速率极高但有大量大对象(如大的 byte[])直接进老年代,会导致 Full GC 频繁。

定位思路是"频率看 GC 日志、对象看堆 dump、趋势看分配速率"三者结合。Full GC 频繁的两大主因是"老年代被大对象灌满"或"老年代有泄漏存活对象",分别对应分配速率问题与存活对象问题,治理手段不同。

#
★★

12. 数据库连接池被打满与线程池被打满的关联排查思路?

数据库连接池被打满与线程池被打满通常相互关联,如何系统性地排查这两类"池满"问题,理清它们之间的因果关系?

  • 理解连接池与线程池的容量、等待与超时语义
  • 掌握 HikariCP/ThreadPoolExecutor 的监控指标与日志
  • 学会区分"连接池满是因"还是"线程池满是因"的因果链

两类池满常互为因果:若数据库慢查询或连接泄漏导致连接池耗尽,线程会长时间等待获取连接,线程被占用继而拖垮线程池;反之,若业务并发过高导致线程池打满,线程排队等待执行,其中的任务可能因未及时释放而占用连接,反将连接池打满。排查时先看线程池状态(核心/最大线程数、queue 大小、rejected 次数、活跃线程),再查连接池状态(active/idle/等待获取连接数、连接获取超时、SQL 执行耗时)。用监控文本把"池满发生的时间点"与"慢查询/SQL 耗时曲线"对齐,判断谁先被打满。若连接池先满且等待获取连接超时,说明连接池是瓶颈源头;若线程池先满且队列堆积,说明线程池是瓶颈。追溯根因可能是慢 SQL、连接泄漏、热 key 或下游缓慢。

关键是把两个池"谁先满"找出来,因为它们会互相放大。连接池满源于"连接获取/释放不均衡",线程池满源于"任务速率高于处理速率"。用时间线对齐监控,先定位先被打满的一方,再沿调用链找真正的根因(SQL、锁、下游),避免只扩容其中一个池而反复复发。

#
★★

13. 磁盘 IO 打满的应急与根治,如何快速定位高 IO 进程、评估是否需要扩容或优化查询?

磁盘 IO 被打满时,如何快速应急定位高 IO 进程,并评估应采取扩容还是优化查询等根治方案?

  • 掌握磁盘 IO 打满的应急定位流程
  • 理解 IOPS 与吞吐量、随机 IO 与顺序 IO 的差异
  • 学会判断扩容与优化查询的取舍

应急时先用 iostat -x 1 确认磁盘 util% 是否接近 100%,区分是 IOPS 饱和还是带宽饱和(随机 IO 看 IOPS,顺序 IO 看带宽)。用 iotop -o / pidstat -d 1 定位高 IO 进程,再结合业务判断是批量任务、日志刷盘还是数据库查询。若为数据库,用慢查询日志与执行计划分析是否存在全表扫描、索引缺失或大范围扫描。根治上:能优化查询优先优化(加索引、减少扫描、分批、缓存),避免盲目扩容;若确实业务量增长导致 IO 需求超容量,才评估扩容(本地盘/云盘/降级读写)。应急期可先限流、降级非核心任务、关闭无谓日志,缓解压力。

定位是"磁盘→进程→SQL/文件",根治要回到"请求是否可优化"。扩容是物理手段,治标;优化查询是逻辑手段,治本。先判断是"真的需要这么多 IO"(扩容)还是"产生过多无效 IO"(优化),是决策的核心。

#
★★

14. 内存溢出的排查,堆栈分析、dump 与 GC 日志如何结合?

出现内存溢出(OOM)时,如何通过堆栈分析、堆 dump 与 GC 日志进行系统性排查定位根因?

  • 掌握 OOM 的常见类型与触发条件
  • 会用 GC 日志与堆 dump 分析存活对象
  • 理解堆分析工具(MAT/JProfiler)的用法

先看 OOM 异常类型:Java heap space 表示堆内存不足,Metaspace 表示元空间不足,Direct buffer memory 表示堆外内存不足,Unable to create native thread 表示线程/本地内存耗尽。根据类型选择分析重点。开启 -XX:+HeapDumpOnOutOfMemoryError 在 OOM 时自动导出堆,用 jmap 补 dump。分析 GC 日志看 OOM 前堆是否持续增长、GC 是否已无法回收。用 MAT 打开堆 dump,分析 Leak Suspects 与 Dominator Tree,找到 GC root 到最大对象的最短引用链,定位是大对象、集合无限增长、缓存未清理还是 ThreadLocal 泄漏。对 Metaspace 看类加载器是否泄漏,对 native 内存用 pmap/jcmd 分析。

OOM 是"堆无法分配新对象"的结果,根因是"存活对象基数过大"或"分配速率过快"。堆 dump 揭示"谁占着内存、被谁引用",GC 日志揭示"空间如何耗尽",两者结合才能定位到具体代码路径。开启自动 dump 是排查的前提。

#
★★

15. 磁盘 IO 高的定位,iostat 与进程 IO 分析如何实施?

磁盘 IO 偏高时,如何利用 iostat 查看磁盘级别指标,并结合进程 IO 分析定位到具体进程?

  • 掌握 iostat 关键指标(util、await、svctm、r/s、w/s)
  • 会用 pidstat/iotop 定位进程级 IO
  • 理解随机 IO 与顺序 IO 的区别

先用 iostat -x 1 观察 util%(磁盘繁忙度)、await(平均 IO 等待)、r/s 与 w/s(读写次数)、rkB/s 与 wkB/s(吞吐量)。util% 接近 100% 说明磁盘饱和;await 高而 util 不高时,可能是请求排队或设备本身慢。高 r/s/w/s 且请求小块,多为随机 IO,瓶颈在 IOPS;高吞吐量大块,多为顺序 IO,瓶颈在带宽。进程级用 pidstat -d 1 看各进程 KB_rd/s、KB_wr/s,或用 iotop -o 实时过滤高 IO 进程,再结合 lsof 看具体文件。若 IO 由数据库产生,进一步用 SQL 分析与执行计划定位。

iostat 回答"磁盘多忙、什么类型 IO",进程 IO 工具回答"谁在产生 IO"。先判断磁盘是否真饱和,再判断是 IOPS 型还是带宽型,最后定位到进程与文件,为优化(加索引、缓存、调整 IO 调度)提供依据。

#
★★

16. 缓存大面积失效(击穿/雪崩)导致 DB 压力突增,如何区分击穿、雪崩与穿透并逐层治理?

缓存大面积失效导致数据库压力突增时,如何区分缓存击穿、雪崩与穿透三种情况,并分别进行治理?

  • 理解缓存穿透、击穿、雪崩的语义差异
  • 掌握互斥锁、热点永不过期、随机过期等治理手段
  • 学会结合缓存与 DB 指标判断故障类型

三种情况成因不同:穿透是查询的 key 在缓存和 DB 都不存在,导致每次请求都打到 DB,治理用布隆过滤器拦截或缓存空值;击穿是某个热点 key 过期瞬间,大量并发请求同时打到 DB,治理用互斥锁(只允许一个请求回源)、逻辑过期或热点 key 永不过期;雪崩是大量 key 在同一时间过期,或缓存实例宕机,导致流量整体冲垮 DB,治理用过期时间加随机抖动、缓存集群高可用、限流熔断、DB 兜底。排查时结合缓存命中率、DB 请求量、key 过期策略判断属于哪一类。

三者共同点是"缓存没兜住,流量打到 DB",但触发点不同:穿透打在没有的 key,击穿打在单个热点 key,雪崩打在大批 key。定位要区分"单个 key 还是大批量""key 是否存在",再选对应治理手段,避免一刀切。

#

17. OOM 的排查,cgroup 限制、堆内存与 swap 如何分析?

在容器化环境中出现 OOM 时,如何结合 cgroup 内存限制、Java 堆内存与 swap 进行排查?

  • 理解 cgroup 内存限制与 OOM Killer 的触发机制
  • 掌握容器内 JVM 堆与容器内存的关系
  • 了解 swap 对 OOM 判断的影响

容器内 OOM 常见于 cgroup 内存限制(memory.limit)小于应用实际使用。cgroup 会在使用的内存超过限制时触发 OOM Killer,把占用最高的进程杀掉。排查时用 /sys/fs/cgroup/memory/memory.limit_in_bytes 与 memory.usage_in_bytes 对比,确认是否触顶。JVM 在容器中需设置 -XX:+UseContainerSupport 和 -XX:MaxRAMPercentage,让堆大小自适应容器内存,避免堆超配导致 native 内存挤占 cgroup 限制。swap 的存在会掩盖内存压力,使 cgroup 统计与物理内存不一致,应关注 memory.swappiness 与 swap 使用情况。若 OOM 发生在 cgroup 层而非 JVM 层,说明是容器整体内存不足,而非 Java 堆问题。

容器内 OOM 要区分"是 JVM 堆 OOM 还是 cgroup OOM"。前者是 JVM 内部堆满,后者是容器整体内存(堆+堆外+元空间+线程栈+网络)超限被内核杀。关键看堆内存与容器限制的匹配,以及 swap 是否掩盖了真实内存水位。

#

18. 磁盘空间满或 inode 耗尽导致写入失败,如何用 df、df -i 定位并做日志清理与容量规划?

磁盘空间满或 inode 耗尽导致写入失败时,如何用 df、df -i 定位问题,并做日志清理与容量规划?

  • 掌握 df 与 df -i 的区别与用法
  • 理解 inode 耗尽与空间满的差异
  • 学会日志清理与容量规划的常用策略

写入失败先区分是空间不足还是 inode 不足:用 df -h 看磁盘可用空间,df -i 看 inode 使用率。若空间满,用 du -sh * 从大到小定位大目录,检查日志、临时文件、上传目录、docker 镜像等,清理过期日志、无用的临时文件与旧备份。若 inode 耗尽(df -i 显示 100% 但空间仍有剩余),说明小文件数量过多,用 find / -xdev -type f | wc -l 统计文件数,定位到临时文件/缓存目录或大量小文件,删除或合并。规划上:配置日志轮转(logrotate)、设置文件大小上限、定期清理归档、监控磁盘与 inode 使用率并设置告警,预留扩容空间。

空间满与 inode 满是两种不同资源耗尽,可能同时存在。空间看"容量",inode 看"文件数量"。定位策略一致:先确认哪个耗尽,再用 du/find 逐层收敛到具体目录,最后靠日志轮转与监控规划根治。