J
Java技术栈复习JVM / Spring / MQ / 分布式 / 大数据 · v6.2
JAVA ENGINEERING · KNOWLEDGE MAP v6.2

Java技术栈复习

从语言与 JVM 的机制级原理,到分布式架构、生产治理、安全工程和 AI 企业应用。用清晰层级、可检索目录与可横向滚动的数据表,支撑系统复习与面试准备。

HTML v6.2 · 正文目录默认折叠主体 11 章 + 附录 A–G正文保留 · 目录统一 · 技术勘误已补
HTML AUDIT · 2026-10-28

页面标题简化与正文目录默认折叠(HTML v6.2)

本轮以 v6.1 实际 HTML 文件为基准,将页面主标题简化为“Java技术栈复习”,移除封面、品牌栏和相关章节标题中的年限标签;正文内嵌目录默认收起,仍可手动展开,左侧智能导航与全文搜索保持独立工作。

正文保全说明:已检查 v5.9 文件实际结构,3.4.7 之后第 4–11 章及附录 A–G 均有正文;未发现本次使用文件在该处物理截断。本轮在原正文上增量补充和校订,不以目录条目替代正文。

本轮保留旧版本审校历史,并将历史说明置于下方折叠记录;当前版本的标题、元数据与正文目录默认状态以 v6.2 为准。侧边栏与正文目录仍对应同一套实际标题树。

v6.2 本轮重点:页面主标题统一为“Java技术栈复习”;正文内嵌目录默认收起,点击可展开;经验年限标签改为通用资深岗位表述;左侧智能导航、正文标题层级、技术正文、表格和代码示例均予以保留。

查看本轮详细复核记录与官方核验入口
页面交互修复

补上实际可用的目录筛选;修正全文搜索第一次按 Enter 会跳过第一个结果的行为;保留目录展开/收起、深色模式、进度条、复制代码和打印功能。

Java 版本纠错

将结构化并发标为 JDK 27 第七次预览,而不是 JDK 25 稳定功能;补充 JDK 26/27 的 HTTP/3、G1 默认选择、紧凑对象头和最终字段反射警告等变化。

JVM/GC 表述校准

校正紧凑对象头的位数与默认版本、ZGC 分代模式的屏障描述、Epsilon 分配模型、晋升年龄和 safepoint 诊断参数;把过度绝对化的性能收益改成需要验证的条件性结论。

目录与表格索引

附录 A 现区分“正文表格数量”和“索引编号”:索引 65、66 是此前未单列的既有专题表,67 是本次新增的 JDK 26/27 特性表。因此索引编号到 67,不代表正文有 67 张表。

第二轮技术勘误

修正 ZGC 染色位“高 4 位”的过度简化、Serial Old 作为 G1 兜底的错误说法、G1 RSet 固定占比和 IHOP 固定阈值的表述;统一 JDK 26 最终字段反射警告版本,补充 JDK 27 Vector API 与 PEM 预览状态。

第三轮内容与交互复核

收敛 HashMap 并发安全、虚拟线程 ThreadLocal/ScopedValue、长事务、消息重复投递、Netty TLS、语义缓存收益和技术债预算中的绝对化结论;修正 sendfile/kTLS 对 CPU、拷贝和性能百分比的泛化;补充 JDK 27 重要移除项,并修复目录筛选时的折叠边界。

第四轮技术边界校正

修正 C2 可数循环的绝对化描述;删除“64MB Arena 空洞”这一错误固定值;补全 MCP 的 Resources / Prompts / Tools 原语;将重试预算 10%、ArrayDeque 性能、HikariCP 连接获取、Canal 缓存删除及跨地域 RPC 改为有前提的工程判断;列明 JDK 27 关键启动参数移除及替代项。

v5.2 目录、知识点与页面 Bug 终审

检查 190 个正文标题与两套目录、重复 ID、内部锚点、表格/代码块和 4 组复习清单;将集合框架移回 Java 语言/标准库章节,并把并发编号恢复连续;MQ 顺序调整为通用语义→可靠性原则→Kafka 概览→各产品深入;补足微服务治理、RPC 选型和官方发行版本快照。Node 对全部内嵌 JavaScript 执行语法检查通过,静态锚点检查无失效目标。自动化 Chromium 导航被当前运行环境策略拦截,因此不把这一轮描述为已通过完整浏览器视觉回归。

版本更新截至日期

截至 2026-10-27,Oracle 官方发布说明列出 JDK 27.0.1.0.3 GA(2026-10-24);JDK 27 是非 LTS 功能版本,JDK 25 仍为最新 LTS。Oracle GA/BPR 构建号与其他 OpenJDK 发行版支持节奏需分别核对,不能把某一厂商版本表述当成所有发行版的共同事实。

经典知识图谱交叉核验(v5.3 历史批次)

以 PDai 题库的问题域和《Java 工程师成神之路》的分层目录为基准,补入 Java 语义、并发 API、设计模式、Servlet/Tomcat、I/O/Reactor、Redis HA、ORM、工具链、Linux/OS 和算法题型;新增附录 C 源主题映射与使用边界。没有整段复制来源文章,具体表述由本报告归纳,旧资料中的版本状态不作为当前事实依据。

招聘平台岗位要求提炼的 Java 技术栈全量清单与复习路线

项目 内容
面向人群 Java 后端工程师 · 资深工程师/Staff·Principal Engineer/系统架构师/技术专家/后端与研发负责人
版本 v6.2(基于 v6.1:页面主标题简化为“Java技术栈复习”;正文目录默认收起;将封面、导航及岗位定位中的年限标签改为通用资深岗位表述;保留原有技术正文与交互功能)
报告日期 2026 年 10 月 28 日
规模主体章节 + 附录 A–G · 145 个逻辑编号图表/专题 · 建议复习周期 6 周
版本事实口径 技术版本事实截至 2026-10-27;快速演进项以对应官方版本说明与实际生产发行版为准。

📊 速览

技术域 P0 核心清单 P1 进阶清单 建议复习周期
12 大类 26 项 24 项 6 周
  • 口径 A:技术域复习优先级(表 2)——按“面试中被追问的深度”排序,决定先读哪一章。
  • 口径 B:面试必备清单(第 10 章 10.1/10.2)——按“资深岗位候选人投递前必须准备”排序,决定哪些必须带案例。

两者不一致是有意设计:MySQL/Redis/MQ 在技术域层面归 P1(意味着不必像 JVM 那样追到 C++ 源码级),但在面试必备清单中归 P0(意味着必须准备真实故障案例与量化数据)。下表“26 项 / 24 项”指表 24/25 的打勾项数量,不含第 10 章核心必备清单中的 MySQL/Redis/MQ。


🧭 阅读导航

如果你的目标是 建议优先读 可略读
资深/核心研发(主攻 P0 深度) 第 0、1、2、3 章 + 第 4 章 按 P0 深度准备 MySQL/Redis 高频追问 + 第 9 章 P0 清单 第 8 章、P2 清单
系统架构师/技术专家 第 0(0.4/0.5)、1、5 章 + 2.1.8–2.1.19、2.4.1、2.2.7~2.2.8、3.4.5、4.1.5、5.2.8、5.4、6.4 6.3 大数据栈
后端/研发负责人 第 0、8 章 + 1.3、5.4、6.5、7.1、7.3、10.5、10.6 2.1.1、2.2.1 等参数细节
时间紧(约 2 周突击) 第 0.4 模板 + 第 1 章全景表 + 第 9 章清单 + 10.6 自检 其余按薄弱项回查
技术专家/SRE/平台工程 第 2、6 章 + 6.1(eBPF + OOMKilled + ActiveProcessorCount)+ 6.5 + 7.1 + 7.4 8 章

📑 目录

正文快速目录 正文目录默认已收起;可展开查看全部章节

摘要

本报告面向 Java 后端工程师及资深技术岗位候选人,目标岗位包括资深 Java 工程师、Staff/Principal Engineer、系统架构师、技术专家、后端负责人及研发负责人。资深岗位不只是要求掌握更多初中级知识点;招聘方通常会进一步验证候选人是否具备复杂系统设计、线上疑难问题闭环、技术决策与权衡、核心模块交付、跨团队推动和团队技术影响力。

公开职位样本反复出现的基础组合是 Java/JVM/并发、Spring Boot/Spring Cloud、MySQL、Redis、MQ、分布式系统、生产排障和架构设计;Docker/Kubernetes、CI/CD、测试与代码质量也经常出现。岗位行业、公司规模和职位级别差异很大,因此下文的 P0/P1/P2 是备考优先级建议,不是对整个招聘市场的统计比例,不能把个别职位样本外推成“所有岗位都要求”或精确占比。

两套分层口径:

口径 用途 典型差异
口径 A:技术域复习优先级(表 2) 决定“先读哪一章、追到多深” MySQL/Redis/MQ 归 P1(不必追底层 C++ 源码),JVM/并发/Spring/网络/微服务/架构设计归 P0
口径 B:面试必备清单(第 10.1/10.2) 决定“投递前哪些必须带案例” MySQL/Redis/MQ 归 P0(必须有真实故障案例与量化数据),安全/测试在通用岗位归 P1、金融/政企归 P0 否决项

对资深岗位候选人,面试准备必须从“会使用技术”升级为“能解释机制、说明边界、给出数据、讲清取舍、证明结果”。建议每个 P0 主题至少准备:原理图、典型追问、生产案例、量化结果、方案替代项及其代价。

招聘信息来源与使用边界

本次检索到的公开职位样本包括智联招聘上的高级 Java/架构类职位,以及猎聘上的 Java 架构师、资深 Java 岗位列表。样本中明确出现 Java 核心与 JVM、Spring Boot/Cloud、MySQL、Redis、MQ、分布式与高并发、SQL 调优、容器化、CI/CD、代码质量、系统架构和团队协作等要求。


0. 资深 Java 岗位定位与能力标准

0.1 资深岗位候选人的面试目标

表 1:五类目标岗位与其考察重点

目标岗位 招聘方更关注什么 需要重点证明的能力
资深 Java 后端/核心研发 能否独立负责复杂模块并稳定交付 Java/JVM/JUC、Spring、SQL/缓存/MQ、线上排障、代码质量
Staff/Principal Engineer 能否解决跨服务、跨团队的系统性问题 系统设计、技术标准、容量与可靠性、复杂技术决策、技术影响力
系统架构师 能否从业务约束推导出合理架构 领域建模、服务边界、数据架构、分布式一致性、可演进性和成本
技术专家/中间件方向 是否具备机制级理解与性能诊断能力 JVM、并发、网络、存储、消息系统、性能测试和源码分析
后端负责人/研发负责人 能否兼顾交付、质量、人员和业务目标 技术规划、风险控制、架构治理、人才培养、跨部门沟通、ROI

0.2 技术掌握深度的四级标准

级别 名称 定义
L1 使用级 能在项目中正确配置和使用,知道常见 API 与基本概念
L2 原理级 能解释核心机制、关键数据结构、线程模型、事务边界和故障模式
L3 实战级 能展示真实项目案例、监控数据、排查步骤、优化前后指标及失败教训
L4 设计与决策级 能在约束条件下比较多种方案,解释为什么选择、何时失效、如何迁移、如何回滚及其成本

0.3 资深岗位需要额外补齐的“责任型能力”

序号 能力维度 具体说明
1 从功能开发到系统结果 不只说“完成了某模块”,还要说明业务规模、SLA、吞吐、延迟、数据规模、故障率和业务收益
2 从单点优化到全链路治理 能沿请求链路定位线程池、数据库、缓存、MQ、网络和下游依赖的瓶颈,兼顾线程池与连接池协同
3 从方案罗列到权衡决策 讲清一致性、可用性、延迟、成本、复杂度、团队能力和迁移风险之间的取舍
4 从个人排障到机制建设 沉淀告警、Runbook、压测基线、故障复盘、发布门禁和预防性架构测试(如 ArchUnit)
5 从技术执行到影响力 推动架构决策记录(ADR)、指导团队、治理技术债,并用结果而非头衔证明影响力

0.4 面试回答黄金九步法模板(架构/选型/故障通用)

遇到架构设计、技术选型和生产故障类问题时,可按此结构组织回答:

1. 背景(Context)     :业务目标、规模(QPS/TPS/存储量)、当前架构与核心业务约束。
2. 问题(Problem)     :系统的主要瓶颈、高可用风险、一致性隐患或突发故障现象。
3. 原因(Root Cause)  :从系统证据链(日志/Metrics/堆栈/内核)推理出的深层机制,绝不凭空猜测。
4. 方案(Options)     :列举 2~3 个候选方案,说明最终的技术选型。
5. 取舍(Trade-offs)  :为什么不选替代方案?说明延迟、一致性、改造成本、复杂度与运维的权衡。
6. 落地(Execution)   :配置改动、代码重构、数据迁移、发布顺序与灰度步骤。
7. 验证(Verification):压测对比数据、P99/QPS 改善比例、线上监控看板变化证明方案有效。
8. 兜底(Fallback)    :降级开关、熔断阈值、数据对账补偿机制与一键回滚方案。
9. 结果(Impact)      :量化业务收益(如:P99 从 300ms 降至 45ms,服务器成本降低 30%)。

0.5 资深岗位候选人必备 11 个生产实战案例库

复习时必须结合自身经历整理出以下 11 个真实案例,做到“有背景、有证据、有参数、有取舍、有数字”:

  1. JVM / 堆外内存泄漏 / 线程池打满故障排查(结合 NMT、pmap、Glibc Arena、jstack、Arthas、MAT)。
  2. 生产慢 SQL 深入调优与锁争用解除(结合 optimizer_trace、死锁日志分析、索引优化)。
  3. 缓存击穿 / 穿透 / 雪崩 / 大 Key 治理与双写一致性保障。
  4. 消息积压、消息重复消费与死信补偿闭环。
  5. 分布式事务 / 跨系统资金级业务幂等与对账补偿设计。
  6. 线上 P0 故障应急响应、止血策略与全链路事后复盘(RCA)。
  7. 遗留单体系统重构或技术债清理(绞杀者模式落地与双写双读切换)。
  8. 亿级大表不停机迁移、在线 DDL 或平滑分库分表(结合 CDC 与对账校验)。
  9. 一次重大发布故障回滚与新旧版本数据兼容性防护(Expand-Contract 模式)。
  10. 软件供应链漏洞修复与系统安全性加固(如 Log4j/SpringShell/SSRF/权限垂直越权治理)。
  11. AI 大模型 API 企业级接入工程化或 RAG 系统落地的召回调优与降级兜底。

1. 技术栈总览与优先级分层

表 2:Java 技术栈全景(按优先级分层)

优先级 技术域 栈内技术项 对应岗位要求
P0 JVM 与底层性能 内存模型与 JMM、全量十款回收器(Serial/ParNew/Parallel/CMS/G1/ZGC/Shenandoah/Epsilon)、三色标记机制、TTSP 与可数循环安全点陷阱、Glibc ptmalloc Arena 膨胀与 jemalloc 替代、JIT 编译(C1/C2/内联/去优化)、类加载器体系与双亲委派、排障工具链(Arthas/MAT/JFR)、类卸载与 Metaspace 泄漏 资深研发/架构核心考察项
P0 并发与 JUC AQS 三组件、ThreadPoolExecutor 与 ForkJoinPool、CPU 缓存行伪共享(False Sharing)与 LMAX Disruptor、ConcurrentHashMap 扩容迁移、中断/取消/超时传播、死锁活锁排查、虚拟线程与 ScopedValue 高性能并发系统基石
P0 Java 语言与集合源码 核心集合框架底层实现(HashMap 扰动函数/高低位扩容/红黑树泊松分布、LinkedHashMap LRU、TreeMap、ConcurrentSkipListMap 跳表无锁并发、WeakHashMap 引用清理、IdentityHashMap 探测、ArrayList 内存迁移与 subList、LinkedList 节点开销与遍历成本、CopyOnWriteArrayList 弱一致迭代、ArrayDeque 位运算循环、PriorityQueue 二叉小顶堆)、泛型/擦除/桥接方法、equals/hashCode 对象契约、集合只读视图与 fail-fast 边界、异常设计与 AutoCloseable、时间时区、金额 BigDecimal 规范、安全序列化 架构级代码规范与严谨性体现
P0 Spring 生态与协同 Bean 生命周期与 BFPP/BPP 扩展点、三级缓存与代理暴露时机、@Transactional 传播与自调用失效、长事务与连接池耗尽、启动配置校验与探针就绪 后端开发工程底座
P0 网络、IO 与协议 TCP/HTTP/HTTPS、HTTP/2 二进制分帧与 HTTP/3 QUIC、HTTPS 下传统 sendfile 零拷贝失效悖论与 Linux kTLS、分阶段排查链路、HikariCP 并发与泄漏检测、超时预算传递、Netty Reactor 模型、响应式编程(Reactor/WebFlux) 线上疑难故障高发地
P0 微服务与服务治理 Nacos(Distro/Raft)、Sentinel 流控与 SlotChain、Seata 分布式事务、Gateway、Dubbo SPI 与 @Adaptive、Sidecar Mesh vs Proxyless Mesh(Sermant) 架构师/技术负责人核心
P0 架构设计方法论 DDD 战略/战术建模、CQRS、Event Sourcing、业务幂等性设计、分布式状态机与补偿、ADR 决策记录与技术债治理、系统设计题框架 架构师准入分水岭
P1 关系型数据库 B+ 树索引、覆盖索引、索引下推、MVCC、Next-Key Lock、EXPLAIN、optimizer_trace、ShardingSphere、数据备份恢复(RPO/RTO/PITR)、冷热分离、分区表、大表 DDL(gh-ost/pt-osc)、业务不变量条件更新 高可用数据架构必备
P1 缓存与 NoSQL Redis 底层编码、RDB/AOF 混合持久化、Cluster/哨兵、Lua 原子操作、Redisson 锁续期与 fencing token、多级缓存(Caffeine+Redis)、String big key 异步边界、Elasticsearch、MongoDB 高性能数据访问必备
P1 ORM 与 SQL 执行层 MyBatis 执行链路、#{} vs ${} 注入边界、Executor 执行器、一二级缓存脏读风险、MyBatis-Plus 增强、JPA 实体生命周期与 N+1 治理 业务开发与 SQL 治理必考
P1 消息队列 Kafka(ISR/HW-LEO/幂等/事务/零拷贝)、RocketMQ(顺序/延迟/事务消息)、RabbitMQ(Quorum Queue)、Pulsar(存算分离/分层存储)、重试风暴与退避算法 分布式解耦与流处理核心
P1 分布式高可用与容灾 异地多活单元化(Cell-based / 单元化架构)、跨机房流量路由闭环、Binlog 来源标签防回环同步、跨地域冲突裁决(LWW/向量时钟/CRDT) 架构师/技术专家核心进阶
P1 云原生与 DevOps Docker 多阶段构建、Distroless、Kubernetes 高级编排(NetworkPolicy/HPA/PDB/探针)、ArgoCD GitOps、Prometheus+Grafana、SkyWalking/OTel、eBPF 内核态观测、Linux 性能诊断 现代化云上生产架构标配
P2 AI 与新技术 Spring AI 三层抽象、Advisor 链执行顺序、LangChain4j、模型上下文协议(MCP 架构:Host/Client/Server;服务端 Resources/Prompts/Tools 三类原语)、企业级向量语义缓存(Semantic Cache 降本架构)、大模型 API 接入治理、RAG 检索增强系统(切分/召回/重排/权限预过滤)、Agent 工具安全调用、Prompt Injection 防御、AI 评测集与回归 2025-2026 年差异化竞争力
P2 大数据与前沿 Flink on K8s、RocksDB 状态后端、Spark、Kafka 流管道、HBase、Panama FFM API、GraalVM AOT 数据密集型业务加分项
P2(通用)/ P0(金融政企) 安全合规与测试工程 OWASP Top10、SSRF 深度防御、对象级鉴权与多租户隔离、软件供应链与 SBOM、国密 SM2/SM3/SM4、Vault、测试金字塔与契约测试(Pact)、混沌工程(Chaos Mesh) 金融/政企具备否决权,平时为质量保障线

1.1 P0 栈的深度标准

表 3:P0 主题的三层追问落点(自检用)

主题 第一层 第二层 第三层(最容易失守)
G1 G1 怎么回收 Region 与 Mixed GC 怎么选 为什么把 MaxGCPauseMillis 调得更小反而吞吐崩溃且停顿变长
ZGC ZGC 怎么做到低停顿 染色指针与读屏障是什么 经典 ZGC 的读屏障与 G1 的 SATB 写前屏障有何区别;分代 ZGC 为跟踪跨代引用为何还需要写侧屏障/记忆集维护,分代模式解决了什么痛点
三级缓存 有哪三个 Map 为什么需要三级 为什么二级缓存拿到的可能是原始对象而不是代理;ObjectFactory 在哪步执行
BFPP/BPP 分别操作什么 执行时机差在哪 AOP 代理在哪一步创建;为什么不能在 BFPP 中直接调用 getBean()
MVCC ReadView 是什么 RR 下怎么实现可重复读 RR 到底能不能防幻读;为什么当前读和快照读防御机制不同
Kafka ISR 是什么 HW 与 LEO 的关系 为什么消费者只能消费到 HW;生产端 PID+Sequence 是如何做到幂等的
Dubbo SPI 是什么 和 JDK SPI 有什么不同 @Adaptive 是怎么在运行时根据 URL 动态生成字节码选到具体实现的
TTSP 什么是安全点 为什么 GC 停顿很短但 STW 很长 可数循环为什么没有安全点检查,JIT 循环条带化是如何解决的
零拷贝 sendfile 怎么做到零拷贝 为什么开启 HTTPS 传统 sendfile 会失效 Linux 内核 kTLS 是如何将对称加密下沉以重新恢复零拷贝的
集合扩容 HashMap 怎么扩容 JDK 8 高低位指针判断原理 为什么判定式是 (e.hash & oldCap) == 0,以及泊松分布如何推导树化阈值 8

1.2 P1 栈的组织方式

P1 的目标是“能解释机制、能诊断常见故障、能给出工程取舍”,而不是把每个中间件都追到 C/C++ 源码级。对 MySQL、Redis、消息队列、微服务治理等主题,应能说明关键数据结构或协议路径、配置项语义、常见故障、观测指标、容量边界和替代方案。

  • 深度标准:能讲清核心原理与失败模式;能结合执行计划、监控指标、日志或压测数据定位问题。
  • 项目证明:至少准备一个真实案例,说明当时规模、症状、证据链、备选方案、上线验证、回滚条件和最终收益。
  • 学习边界:以目标岗位 JD、实际使用技术和个人短板决定优先顺序,不以“清单越长”作为学习完成标准。

1.3 P2 栈的取舍规则

P2 用于形成岗位差异化,不要求所有人同时深挖 AI、大数据、金融安全、平台工程和云原生。先选定行业与岗位方向,再选择 1–2 个可形成竞争力的专题,建立“概念与边界—可运行 Demo—生产化风险—项目案例—可量化结果”的证据链。

  • AI 企业应用:侧重模型 API 治理、RAG 数据与权限、工具调用安全、评测回归、成本与延迟。
  • 平台/SRE/云原生:侧重容量规划、可观测性、自动化发布、故障隔离、恢复演练与成本治理。
  • 金融/交易/数据平台:侧重一致性、幂等、审计、数据对账、恢复目标、合规与跨版本迁移。

2. Java 语言核心与 JVM 栈

2.1 JVM 与性能诊断栈

表 4:JVM 栈复习条目

技术项 需掌握到的深度
内存模型 手绘堆(Young/Old)、栈、方法区/元空间、直接内存交互;JMM happens-before 原则、volatile 内存屏障语义
垃圾回收 掌握主流与历史 GC 的机制、版本可用性与选型边界(Serial/ParNew/Parallel/CMS/G1/ZGC/Shenandoah/Epsilon 等);理解三色标记、CMS 增量更新、G1 SATB 与 ZGC 屏障机制的关键差异
安全点与停顿 TTSP(Time-To-Safepoint)诊断、可数循环(Counted Loop)陷阱与条带化优化(Loop Striping)
内存分配黑洞 Glibc ptmalloc Arena 碎片与虚高机制、MALLOC_ARENA_MAX 参数限制、jemalloc 替换路径
类加载机制 双亲委派模型及其被打破的场景(SPI、Tomcat、热部署);用自定义类加载器解决 jar 包冲突原理
诊断工具 jstat、jmap、jstack、jcmd;Arthas 的 thread/watch/trace/tt;MAT 分析 OOM 堆转储;JFR 录制生产快照
类的一生 类的加载、连接、初始化;类卸载的三大严苛条件;Metaspace OOM 根因与排查路径
JIT 编译 C1/C2、分层编译流程、方法内联条件与失败原因、去优化(Deoptimization)触发与 CPU 毛刺

2.1.1 三个收集器的停顿目标与适用边界

🔹 G1

  • G1 的 -XX:MaxGCPauseMillis 默认目标值为 200ms(目标而非硬上限);10–200ms 常用于建立调优直觉,但实际停顿取决于对象存活率、分配速率、堆布局、CPU 配额等。目标值设得过严可能使单次回收工作量下降、回收频率上升或吞吐降低,需用 GC 日志和压测验证,不应断言必然发生“断崖式下跌”。
  • -XX:InitiatingHeapOccupancyPercent(IHOP)的初始/静态阈值默认为 45%;默认启用的自适应 IHOP 会根据历史标记周期与分配情况动态调整触发点,不能把 45% 当成运行时永远固定的阈值。
  • -XX:ConcGCThreads 默认约为并行 GC 线程数的 1/4。
  • 大对象处理:对象大小 \(\ge\) Region/2 进 Humongous Region(逻辑属老年代),不走 PretenureSizeThreshold。

🔹 ZGC

  • 停顿时间亚毫秒级且不随堆大小增长;代价是读屏障开销与较多 CPU 核数。
  • 染色指针(Colored Pointers):在 64 位引用的可用虚拟地址位中编码 GC 元数据;经典布局使用 Marked0、Marked1、Remapped、Finalizable 四个颜色位,但它们不应笼统描述为原始指针的“最高 4 位”,具体位布局取决于平台与 JDK 实现。
  • 读屏障(Load Barrier):ZGC 通过读屏障(Load Barrier)在读取引用时检测状态,并在需要时借助转发表自愈指针;但不要把它概括成“所有版本绝无写侧屏障”:分代 ZGC 还需跟踪跨代引用并维护记忆集,会引入相关写侧屏障成本。屏障细节应按目标 JDK 的分代模式与实现版本核对。
  • G1 vs ZGC 屏障哲学:G1 用写屏障+SATB 解决并发标记漏标;ZGC 用读屏障+染色指针解决并发转移的指针修正。
  • SATB vs 增量更新:SATB(G1)记录删除的引用,保证标记开始时存活的快照;增量更新(CMS)记录新增的引用。

🔹 Shenandoah

  • 目标是降低停顿,但实际暂停时间、CPU 开销与吞吐损失取决于堆规模、分配速率、负载与构建版本,不应把“低停顿目标(非 SLA;需实测验证)”当作保证。JDK 25 的 JEP 521 引入分代 Shenandoah;具体发行版是否包含、默认状态与启动参数以供应商构建说明为准。

2.1.2 线上故障的排查证据链与诊断流程

排查 CPU 100%、频繁 Full GC 或线程死锁必须遵循可复现的证据链:

1. 监控确认:确认故障发生时间点,比对请求量、P99 延迟、CPU、内存、GC 与连接池监控。
2. 进程诊断:
   - CPU 100%:top -> top -Hp <pid> -> printf "%x\n" <tid> -> jstack <pid> | grep -A 30 <nid_hex>
   - 区分业务线程与 GC task thread(若 GC 线程打满说明内存告急触发连续回收)。
3. 内存与转储:
   - jstat -gcutil <pid> 1000 查看分代使用率与 GC 频率。
   - jcmd <pid> VM.native_memory summary 排查堆外内存(需提前开启 NMT)。
   - 必要时通过 jcmd <pid> GC.heap_dump 生成堆转储,严禁在高峰期对超大堆做 jmap -dump。
4. 应急止血:先通过切流、降级或扩容恢复服务,妥善保留 core dump 与 heap dump 供线下复盘。

2.1.3 对象的一生:从分配到晋升

类加载检查 → 分配内存(指针碰撞 / 空闲列表 + TLAB) → 零值初始化 → 设置对象头 → 执行 <init>
  • 分配路径与标量替换:JVM 逃逸分析判断对象是否逃逸出方法。若不逃逸,JIT 会进行标量替换(Scalar Replacement),把聚合对象拆成可单独优化的标量值,由 JIT 放入寄存器或适当的栈槽等位置;这不代表对象一定被分配到 Java 栈,也不保证每次都能消除堆分配。
  • 直接进老年代的情况:
    • Serial/ParNew:超过 -XX:PretenureSizeThreshold 直接进老年代。
    • G1:对象大小 \(\ge\) Region/2 进 Humongous Region。
    • 达到晋升年龄阈值(受 -XX:MaxTenuringThreshold、收集器实现、Survivor 占用与动态年龄判定影响);不要把“默认 15”或历史 CMS 的某个默认值视为所有 JDK/收集器的固定行为,应查看目标运行时参数与 GC/年龄分布日志。
    • 动态对象年龄判定:Survivor 空间中相同年龄所有对象大小总和大于 Survivor 空间的一半,大于或等于该年龄的对象直接进老年代。
  • 紧凑对象头:JEP 519 在 JDK 25 将该功能从实验性状态转为产品功能;JDK 27 通过 JEP 534 默认启用。官方描述的 64 位 HotSpot 对象头布局从 96 bit 缩减至 64 bit,但应用整体堆占用的改善幅度取决于对象数量与内存布局,不能直接承诺固定比例。

2.1.4 类的一生:加载、使用与卸载

  • 类卸载的关键条件与边界:类通常随其定义类加载器一起卸载;需要类加载器在 GC 根可达性分析中变为不可达,并且没有其他强引用链继续保活该加载器/其类元数据。单纯“某个类的实例都已回收”并不足以保证卸载;同一加载器定义的类通常以加载器为生命周期边界一起处理。卸载时机还受收集器与运行时策略影响,不承诺在某次 GC 立即发生。
  • Metaspace OOM 典型场景:CGLIB/Javassist/Groovy 动态生成大量类且不断创建新 ClassLoader;Tomcat 热部署后旧 WebappClassLoader 泄漏(常因 ThreadLocal 未清理或静态字段引用);排查使用 jstat -gcmetacapacity 与 jmap -clstats。

2.1.5 GC 选型决策表(表 36)

表 36:GC 选型决策表

维度 G1 ZGC Shenandoah Parallel GC
目标停顿 10–200ms(可调) 亚毫秒~毫秒级目标;暂停不随堆容量线性增长(非 SLA) 低停顿目标(非 SLA;需实测验证) 秒级(关注吞吐量)
适用堆大小 1GB–32GB 几 GB–数 TB(大堆优势明显) 几 GB–数 TB 小堆(< 1GB)或离线批处理
吞吐损失 5%–15% 10%–25%(读屏障与转移开销) 10%–30% 0%(基准最高)
CPU 核数建议 2+ 核 建议 4+ 核以上 建议 4+ 核以上 1~2 核即可
关键参数 -XX:MaxGCPauseMillis、IHOP -XX:+UseZGC -XX:+UseShenandoahGC -XX:+UseParallelGC

2.1.6 JIT 编译器深入:C1/C2/分层编译/方法内联/去优化

  • 分层编译:Level 0 解释执行 \(\to\) Level 1~3 C1 编译(带 profiling) \(\to\) Level 4 C2 激进优化。
  • 方法内联(Inline):消除调用压栈弹栈开销,铺平逃逸分析与死代码消除。内联失败的常见原因包括字节码体积超过当前内联阈值、调用点类型信息不足导致动态分派难以去虚拟化,以及递归/编译预算等限制。不要把 325 字节当作统一的固定上限;需区分 MaxInlineSize、FreqInlineSize 等参数,并结合目标 JDK、方法热度、调用点类型信息和编译日志判断。
  • 去优化(Deoptimization):基于推测优化的机器码在假设破灭(如类加载出现新子类)时,必须通过 Safepoint 撤销优化回退到解释器,频繁去优化会导致 P99 毛刺与 CPU 瞬时飙高。

2.1.7 JVM 类加载器体系详解

  • 层级架构:Bootstrap ClassLoader(HotSpot 传统实现中由 VM 负责) \(\to\) JDK 8 及以前的 Extension ClassLoader/JDK 9+ 的 Platform ClassLoader \(\to\) Application ClassLoader \(\to\) 自定义 ClassLoader。
  • 打破双亲委派三大经典:
    1. SPI:利用线程上下文类加载器(Thread.currentThread().getContextClassLoader())实现父加载器委派子加载器加载实现类。
    2. Tomcat WebappClassLoader:打破常规顺序,优先加载 /WEB-INF/classes 和 /WEB-INF/lib,实现各应用依赖隔离。
    3. OSGi / 热部署:网状类加载器拓扑,根据模块 bundle 动态加载并随时销毁 ClassLoader 实现热替换。

2.1.8 JVM 隐藏长停顿:TTSP 与 Counted Loop 安全点陷阱

生产上常出现“GC 日志记录单次 GC 仅停顿 15ms,但 APM 监控显示该请求 STW 停顿了超过 2000ms”的怪异现象。根因往往不在 GC 本身,而在 TTSP(Time-To-Safepoint,到达安全点等待时间)。

机制维度 原理说明与生产实战
Safepoint 与 STW 构成 真正的应用暂停耗时 = TTSP(等待所有线程挂起的时间) + GC 工作时间。JVM 必须等所有线程都运行到安全点(Safepoint)并插桩轮询挂起后,才能正式开始 STW。如果有一个线程迟迟进不了安全点,其他已经挂起的几百个线程都会干等,造成全局瘫痪
可数循环(Counted Loop)陷阱 在特定 HotSpot 版本、编译层级、循环形态与机器码路径下,C2 可能将 for (int i = 0; i < limit; i++) 优化为可数循环;某些循环路径的安全点轮询可能被省略、稀疏化或延后,长时间运行时会增加 TTSP。这不是所有 int 循环的通用行为,也不能仅凭循环代码断定根因。应结合目标 JDK 版本、编译日志/反汇编、Safepoint 统计、JFR 与可复现测试确认,再评估循环拆分、目标版本支持的 safepoint 选项或升级修复。
诊断手段 在 JDK 9+ 优先使用统一日志:-Xlog:safepoint=debug:file=safepoint.log:time,uptime,level,tags,并结合 JFR、GC 日志和线程栈识别请求延迟与安全点到达延迟;旧版 PrintSafepointStatistics 参数仅适用于相应旧 JDK。单一日志字段不能独立“实锤”根因,需把时间线与线程行为交叉验证
工程解决方案 不要把 int 改成 long 当成通用修复:具体循环仍可能被 JIT 优化为可数循环,是否插入轮询取决于 JDK 构建、循环形态和优化路径。优先在目标 JDK 上用安全点日志/JFR 复现,再验证有界分块处理、循环条带化行为以及 -XX:+UseCountedLoopSafepoints 等诊断选项的实际效果;后者应先在预发压测,不要未经验证直接作为生产参数

2.1.9 操作系统内存分配黑洞:Glibc ptmalloc Arena 膨胀与 jemalloc 治理

容器化生产中经常出现经典故障:“JVM 堆监控完全正常,NMT 统计的堆外内存(DirectMemory、Metaspace、线程栈)加起来也就 2GB,但容器的物理内存 RSS 已经飙到了 6GB,最终触发 Linux 内核 cgroup OOMKilled”。Glibc 内存分配器的碎片与 Arena 行为是候选原因之一,但 RSS 与 NMT 不是一一对应关系。还应排查 JNI/本地库分配、直接映射、线程栈、代码缓存、共享映射以及 NMT 未覆盖或未开启的内存;结合 /proc/<pid>/smaps、pmap、NMT 和原生分配剖析交叉验证。

表 62:内存分配器 ptmalloc vs jemalloc 对比

对比维度 Glibc 原生 ptmalloc jemalloc (FreeBSD / Meta 默认)
内存池架构 采用 Arena 机制。64 位 glibc 的默认 Arena 上限通常按在线 CPU 数量的约 8 倍计算(可由 MALLOC_ARENA_MAX/glibc.malloc.arena_max 调整);并非每次分配或每个线程都会新建 Arena,“每个 Arena 固定 64MB”也不是通用常量,具体取决于 glibc 版本、分配行为和运行参数。 采用多阶分层分配(Small / Large / Huge),基于 Run 和 Slab 细粒度管理物理内存页
内存释放行为 对由 brk 管理的堆区,通常只有堆顶连续空闲空间才能通过收缩 break 归还 OS;较大的 mmap 分配则可能单独解除映射。多 Arena、缓存和碎片可能造成 RSS 不随业务对象释放而立即回落,但具体表现应结合 glibc 版本、分配大小和映射类型分析。 针对空闲物理页采用主动探测并积极调用 madvise(MADV_DONTNEED) 将物理页归还内核
高并发并发度 依靠线程加锁或轮询争用有限数量的 Arena,高并发多线程下锁争用明显 Thread-Cache(T-Cache)设计,每个线程拥有专属微型无锁缓存,极致高并发性能
容器内存表现 多线程异步解压、JNI 调用、Netty 堆外操作频繁时,RSS 持续单调增长不回落,引发 OOMKilled 可能改善特定负载下的碎片与 RSS 回落表现;改善幅度取决于分配大小、线程数、原生库和 allocator 版本,必须以同负载压测和 RSS/映射统计验证,不能泛化固定下降比例。

生产落地动作:

  1. 临时应急规避:在容器启动脚本中设置环境变量 export MALLOC_ARENA_MAX=2 或 4,将 Arena 数量强行压制,减少虚高内存池。
  2. 候选治理方案(需验证):在镜像中安装与发行版、架构匹配的 jemalloc,并在受控环境评估通过 LD_PRELOAD 预加载的可行性。它可能改善部分 glibc 分配器碎片问题,但无法保证消除所有 RSS 虚高或 OOM;需验证 JNI/本地依赖兼容性、崩溃风险、RSS、吞吐与尾延迟,再分阶段发布并准备回滚。

2.1.10 全量十款垃圾收集器深度解析与机制对比

HotSpot JVM 经历多年架构演化,针对吞吐量、低延迟及特殊场景构建了全量十款垃圾收集器:

表 63:十大垃圾回收器特性与选型对比总表

收集器名称 所属分代 核心算法 线程工作模型 STW 停顿水平 内存占用 (Footprint) 内存屏障机制 引入/移除版本 典型瓶颈与缺陷 适用核心场景
Serial 新生代 复制算法 单线程 STW 秒级 / 百毫秒级 极低(零额外开销) 无 早期存在 无法利用多核,单次卡顿明显 单核 CPU、内存小于 200MB 的小型客户端
Serial Old 老年代 标记-整理 单线程 STW 秒级 极低 无 早期存在 内存大时卡顿极长 主要用于历史客户端/小堆场景,以及旧版 CMS 发生 Concurrent Mode Failure 等情况下的老年代回退路径;G1 的 Full GC 不能笼统描述为退化到 Serial Old。
ParNew 新生代 复制算法 多线程并行 STW 百毫秒级 较低 无 JDK 1.4~14 移除 必须绑定 CMS,无法独立使用 配套 CMS 的新生代多线程选择
Parallel Scavenge 新生代 复制算法 多线程并行 STW 百毫秒级 较低 无 JDK 1.4+ 无法精确控制停顿,偏向吞吐量 高吞吐计算型后台批处理
Parallel Old 老年代 标记-整理 多线程并行 STW 秒级 / 百毫秒级 较低 无 JDK 1.5+ 大堆下 STW 时间不可控 与 Parallel Scavenge 配套,JDK 8 批处理首选
CMS 老年代 标记-清除 并发标记清除(2 次短 STW) 几十毫秒~上百毫秒 较高(需预留浮动垃圾空间) 增量更新写后屏障 JDK 1.5~14 移除 内存碎片化、退化 Serial Old 导致长时间 STW JDK 8 互联网服务堆在 4~8GB 内的传统选择
G1 逻辑分代 复制 + 整理 并发标记 + 并行转移 10ms ~ 200ms (可配) 额外元数据开销可能较高(RSet 占比随对象引用分布、堆布局、JDK 版本和负载变化,不应固定写成 10%~20%) SATB 写前屏障 JDK 7u4~现在 (JDK 9 默认) 预测模型失准时吞吐下降,巨型对象难受 堆在 4GB~32GB 的企业级核心在线系统
ZGC 全堆并发 (分代) 标记 + 并发复制 全并发 (2 次微秒 STW) < 1ms (不随堆增大) 中等 (额外读屏障指令开销) 染色指针 + 读屏障 JDK 15 生产, JDK 21 分代 读屏障带来 5%~15% 吞吐损失,需充足 CPU 堆 16GB~数 TB、对 P99/P999 延迟极端敏感的服务
Shenandoah 全堆并发 (分代) 标记 + 并发复制 全并发 (极短 STW) 低停顿目标;按工作负载压测 较高 (依赖矩阵元数据) 读引用屏障 + 写屏障 JDK 12 引入;JDK 25 引入分代模式(具体构建/发行版需核对) 与 ZGC 相比生态成熟度略逊,吞吐稍弱 低停顿目标的延迟敏感场景;需与 ZGC 在目标构建和流量下实测比较
Epsilon 全堆 不回收 (No-Op) 应用线程照常分配;收集器不执行垃圾回收 无 GC 回收停顿(直到 OOM;JVM 仍可能有其他停顿) 零额外开销 无 JDK 11 (JEP 318) 内存不回收,超出直接 OOM 崩溃 算法性能测试、生命周期小于几秒的 Serverless

选型表中的停顿、堆容量和吞吐损失是帮助形成直觉的经验量级,不是厂商 SLA,也不是跨硬件/工作负载的保证值。JDK 版本、堆布局、分配速率、CPU 配额、容器限制与业务延迟目标都会改变结果;正式选型应在目标版本和同类流量下压测,并同时比较 P95/P99、吞吐、CPU、RSS 与故障恢复表现。

垃圾收集器核心演进机制深度剖析
  1. Parallel 吞吐量平衡公式: $\(Throughput = \frac{T_{exec}}{T_{exec} + T_{gc}}\)$ 提供 -XX:MaxGCPauseMillis(期望最大停顿)与 -XX:GCTimeRatio(吞吐量倒数,默认 99,即允许 1% 的 GC 时间),配合 -XX:+UseAdaptiveSizePolicy 动态平衡堆分代。
  2. CMS 运行阶段与三大致命缺陷:
    • 四大阶段:初始标记(STW) \(\to\) 并发标记 \(\to\) 重新标记(STW,增量更新) \(\to\) 并发清除。
    • 致命缺陷 ①:内存碎片与 Concurrent Mode Failure:基于标记-清除(Mark-Sweep)不移动对象,大量碎片导致大对象无法分配,被迫退化为单线程 Serial Old 进行全堆 STW 整理,卡顿几十秒。
    • 致命缺陷 ②:浮动垃圾(Floating Garbage):并发清除阶段产生的垃圾只能留待下一次 GC 清除,必须通过 -XX:CMSInitiatingOccupancyFraction 提前预留空间。
    • 致命缺陷 ③:CPU 敏感:默认开启 (CPU + 3) / 4 个线程,核心数少时严重挤占业务算力。
  3. G1 的 RSet、CSet 与 Card Table 架构:
    • 堆划分为约 2048 个独立 Region(1MB~32MB,大小为 2 的幂)。
    • CSet(Collection Set):依据历史衰减均值预测停顿时间,选出回收价值最高的 Region 集合。
    • RSet(Remembered Set):记录“谁引用了我”(Points-into 结构),解决跨 Region 引用扫描全堆的开销;结合 Card Table(卡表,每 512B 对应 1B 卡页)分层管理(稀疏、细粒度、粗粒度)。
  4. ZGC 染色指针与自愈机制:
    • 经典 ZGC 染色指针布局会利用 64 位引用中的未使用地址位存储元数据,常见四个颜色位为 Marked0、Marked1、Remapped、Finalizable;不要脱离平台和 JDK 实现,把它们简单说成 64 位数值的最高 4 位。
    • 读屏障(Load Barrier)与转发表(Forwarding Table):应用线程读取指针时若处于未 Remapped 状态,触发读屏障自愈更新指针地址,彻底实现并发对象移动。JDK 21 引入分代 ZGC(JEP 439),通过更高效地处理年轻代对象改善部分分配密集型负载;它并不能消除所有内存耗尽风险,仍需保证堆空间余量、并发回收能力和分配速率相匹配。
  5. Epsilon No-Op 收集器(JEP 318):
    • 应用线程仍可通过 TLAB/分配路径申请对象,收集器本身不执行任何垃圾回收逻辑;堆耗尽时应用会因分配失败而 OOM。专门用于无外部干扰的微基准性能测试(Microbenchmarking)以及秒级执行完毕即销毁的 Serverless 函数。

2.1.11 三色标记与并发屏障机制深度横评

在并发标记阶段,并发垃圾回收器面临三色标记的“对象漏标”风险。发生漏标导致存活对象被误清除必须同时满足两个充要条件:

       [黑色对象] ────────── 新增引用 (条件一) ──────────> [白色对象]
           │                                                   ▲
           │                                                   │
       [灰色对象] ────────── 删除引用 (条件二) ─────────────────┘
  1. 充要条件一:黑色对象(已遍历完毕)新增了指向白色对象(未遍历)的直接或间接引用。
  2. 充要条件二:灰色对象(正在遍历)删除了指向该白色对象的直接或间接引用。

各大并发回收器采用完全不同的哲学破坏上述充要条件:

机制维度 CMS:增量更新(Incremental Update) G1:原始快照(SATB, Snapshot-At-The-Beginning) ZGC:读屏障指针自愈(Load Barrier Self-Healing)
破坏的条件 破坏条件一 破坏条件二 从读取源头消除指针不一致前提
底层屏障类型 写后屏障(Post-Write Barrier) 写前屏障(Pre-Write Barrier) 读屏障(Load Barrier)
核心执行机制 黑色对象写入新引用时,写后屏障捕获该操作,将黑色对象退化变回灰色对象 灰色对象切断旧引用前,写前屏障捕获被切断的白色引用,推入 SATB 本地队列强制当存活处理 放弃在写端拦截;应用线程在从堆读取引用瞬间,读屏障检测染色位并借助转发表现场自愈指针
带来的代价 重新标记(Remark)阶段必须以退化的黑色对象为根重新扫描子节点,导致 STW 显著拉长 本次 GC 周期内即使该白色对象已成为真正垃圾,也会被强制视为存活(浮动垃圾增加),留待下次清理 读屏障为每条引用加载指令增加额外 CPU 检测开销(约 5%~15% 吞吐损失),需要充沛 CPU 核心支撑

2.1.12 JVM 运行时全链路架构:从 class 文件到机器码

理解 JVM 时要把规范定义、HotSpot 的常见实现、操作系统内存管理分开。JVM 规范规定类文件格式、运行时数据区与指令语义;HotSpot 的 TLAB、分代收集器、C1/C2、对象头压缩和具体命令行参数属于实现层能力,不应直接套用于所有 JVM。

关键心智模型:Java 堆不是整个 Java 进程的内存,GC 也不是所有内存回收的总开关。进程 RSS 还可能包括 Metaspace、Code Cache、线程栈、直接缓冲区、JNI/native 库、GC 数据结构、内存映射文件以及分配器碎片。
源码 (.java)
  └─ javac / 编译器插件
       └─ class 文件:常量池 + 字节码 + 字段/方法元数据 + 属性
            └─ 类加载器:加载
                 └─ 连接:验证 → 准备 → 解析(解析时机允许延迟)
                      └─ 初始化:执行类初始化方法 <clinit>
                           └─ 解释执行 + 运行时画像(profiling)
                                └─ JIT 分层编译:C1 / C2(实现可能不同)
                                     └─ 本地机器码、内联、去优化与 OSR

对象运行链:分配(TLAB / 慢路径)→ 可达性分析 → GC 标记与屏障 → 回收 / 复制 / 整理
运行时保障:Safepoint / Thread Handshake、异常处理、同步、类卸载
诊断观测:jcmd / jstat / jstack / JFR / -Xlog / NMT / OS 指标
层次核心知识点面试与排障落点
类文件与类加载常量池、字节码、类加载器、验证/准备/解析/初始化;父子加载器的可见性与委派边界。定位 NoClassDefFoundError、ClassNotFoundException、LinkageError、重复类加载与类加载器泄漏。
运行时数据区每线程的 PC/Java 栈/本地方法栈;共享堆、方法区抽象及 HotSpot 的 Metaspace、运行时常量池。区分 StackOverflowError、Java heap OOM、Metaspace OOM、直接内存 OOM,不把“方法区”等同于某个固定物理内存池。
堆外与本地内存DirectByteBuffer、JNI/native、线程栈、Code Cache、GC 元数据、分配器 arenas 与内存映射。当 RSS 持续高于 heap committed 时,结合 NMT、容器指标、线程数、缓冲池、分配器统计分析,而不是盲目增加 `-Xmx`。
解释器与 JIT解释执行、分层编译、热点画像、内联、逃逸分析/标量替换、OSR、去优化、Code Cache。区分冷启动与稳态吞吐;排查编译队列、过度去优化、内联失效与代码缓存压力。具体优化策略取决于 JDK 版本和参数。
对象分配与 GCTLAB 快速分配、对象头/对齐、引用可达性、写屏障、记忆集、并发标记与回收。高分配速率即使没有内存泄漏也可能增加 GC CPU;GC 日志中区分分配失败、晋升失败、退化/Full GC 和大对象分配。
Safepoint 与 Handshake线程在可安全执行 VM 操作的状态汇合;部分操作可通过线程握手只影响目标线程,不应把所有 VM 操作都等同于全局 STW。长停顿既可能是 GC 工作,也可能是 TTSP(到达安全点前等待)、类重定义、堆转储等;结合 safepoint 日志拆分“到达安全点时间”和“安全点内时间”。
诊断与运维统一日志、JFR、线程/堆转储、NMT、JMX、操作系统容器指标。先建立线程、CPU、heap/Metaspace/direct、GC pause、分配率和请求延迟的证据链,再调整参数;禁止无证据地反复改 GC 参数。
JVM 内存指标必须分层看
  • Heap used / committed / max:used 是当前使用量,committed 是 JVM 已提交可使用的量,max 是上限;三者含义不同。GC 后 used 下降不意味着 committed 或 RSS 同步下降。
  • Metaspace:存放类元数据;其 native 使用会随类加载器、代理类/动态生成类、类卸载情况变化。持续增长要优先检查类加载器引用链和动态类数量。
  • Direct/native:直接缓冲区和其他本地分配可能消耗容器内存,但不都由 Java 堆 GC 直接控制。要结合 `BufferPoolMXBean`、NMT、进程 RSS 与容器 cgroup 数据。
  • 线程栈:线程数与栈大小一起决定潜在本地内存;大量平台线程、线程池失控或阻塞线程都可能推高 RSS。

2.1.13 JDK 8–27 的 JVM 演进主线:按维度看差异

表 6 按每个主要版本列出语言、标准库与 JVM/GC 变化;下面再按工程决策维度归纳,避免只背版本号。重点记住“何时引入、何时成为默认、何时移除”是不同问题。

维度JDK 8 时代基线中间演进关键节点JDK 25–27 当前口径实际升级建议
对象头与堆布局经典 HotSpot 对象头、指针压缩与对齐受平台/堆配置影响。JDK 24 引入 Compact Object Headers 实验性功能;JDK 25 转为产品特性但默认关闭。JDK 27 默认启用 Compact Object Headers;64 位 HotSpot 对象头从 96 bit 缩减到 64 bit。JDK 27 中 `UseCompressedClassPointers` 选项不再可控。不要依赖固定对象头位布局的诊断工具、Unsafe 偏移或本地 Agent;升级前测试堆占用、吞吐与内存布局相关工具。
GC 默认与代际模式Parallel GC 在常见 Server VM 环境中广泛使用;CMS 是历史上重要的低停顿选择。JDK 9 在 server-class 环境默认 G1;CMS 于 JDK 14 移除;ZGC 在 11 起以实验性形态出现,在后续版本成熟;JDK 21 引入 Generational ZGC,JDK 23 分代模式默认化,JDK 24 移除非分代模式。JDK 25 增加/完善分代 Shenandoah(取决于构建);JDK 27 让 G1 在所有环境默认。“默认值变了”不等于“最优 GC 变了”。升级后记录实际 collector、暂停分布、分配率、GC CPU、live set 与 RSS,再决定是否显式指定 GC。
启动与预热启动时类加载、解释执行、JIT 画像逐步积累;应用预热常依赖自定义流量。CDS/AppCDS、动态 CDS、JDK 24 AOT Class Loading & Linking,JDK 25 AOT 命令行/方法画像改进,JDK 26 AOT Object Caching 支持更多 GC 场景。启动加速不再只靠 JVM 参数,还可结合 CDS/AOT cache 与镜像/部署方式;可用能力随发行版和构建配置变化。把启动时间、首次请求延迟、稳态 P99、缓存命中、容器冷启动作为不同指标测量;缓存与构建产物要在相同 JDK/环境中验证。
并发与线程模型以平台线程与线程池为主,阻塞调用常占用操作系统线程。JDK 19 虚拟线程预览,JDK 21 正式;JDK 24 改进虚拟线程在 `synchronized` 监视器上的阻塞/pinning 行为;结构化并发和 Scoped Values 逐步演进。虚拟线程已稳定,但 Structured Concurrency 等在 JDK 27 仍是预览 API。阻塞 I/O 并发可以受益;CPU 密集任务、数据库连接数、HTTP 连接池和下游限流仍是瓶颈。虚拟线程不能消除容量管理。
模块与反射传统 classpath 和深反射框架较少碰到模块封装边界。JDK 9 引入 JPMS;JDK 16/17 强封装 JDK 内部 API,JDK 17 起 `--illegal-access` 不能恢复全局宽松访问;JDK 24 永久禁用 Security Manager。旧框架、代理、字节码增强、Java Agent 对内部 API/深反射的假设更容易在升级时暴露。以依赖升级和公开 API 替代为先;`--add-opens` 只能按模块/包精确过渡,不能作为长期兼容策略。
可观测性与诊断JDK 工具、GC 日志和线程/堆转储是主力,但日志参数分散。JDK 9 统一日志 `-Xlog`;JFR 在 JDK 11 开源并持续增强;JDK 25–27 加入多项 JFR 采样/安全脱敏改进。JDK 27 JFR 支持进程内对命令行参数及环境变量/系统属性初始值进行脱敏。生产统一采集 JFR、GC、线程与容量指标;脱敏不能替代避免秘密写入参数/日志的基本做法。
弃用/移除与兼容性PermGen、CMS、Nashorn、Java EE 内置模块等曾是历史运行环境的组成部分。PermGen 在 8 移除;CMS 在 14 移除;Nashorn 在 15 移除;JDK 11 移除 Java EE/CORBA 模块;JDK 24 永久禁用 Security Manager。JDK 27 对 `UseCompressedClassPointers` 等旧参数有进一步废弃/移除变化,并对通过深反射修改 `final` 字段发出警告。运行升级前静态扫描 JVM 参数、依赖树、Agent 和反射行为;升级后将 warning 视为迁移待办,不要忽略到下次大版本。

分代 Shenandoah、ZGC、Graal JIT、AOT 等功能的可用性和默认值可能因 OpenJDK 发行版、Oracle JDK、平台与构建选项而不同。本文版本矩阵以 Java SE / Oracle JDK 与 OpenJDK 的官方发行说明为主,不能替代目标发行版的实际验证。

2.1.14 JVM 生产诊断工具与命令矩阵

常见生产排障顺序是先采证据、再定位、最后调参。命令参数会随 JDK 版本和权限/容器环境有差异;在生产执行堆转储、长时间记录或高频采样前,应评估磁盘空间、CPU 开销、停顿风险与敏感数据暴露。

问题类型首选命令 / 工具观察重点注意事项
确认实际运行版本与启动参数jcmd PID VM.version
jcmd PID VM.command_line
jcmd PID VM.flags
实际 Java 版本、启动器参数、VM 最终生效参数;区分环境变量、脚本默认值与命令行覆盖。要连接到目标进程同一用户/容器命名空间;命令输出可能含敏感参数,分享前脱敏。
GC 暂停、分配与堆状态jcmd PID GC.heap_info
jstat -gcutil PID 1000
-Xlog:gc*,safepoint
Young/Mixed/Full GC 次数与暂停分布、分配速率、晋升、GC 后存活集、回收线程 CPU、TTSP 与 STW 内部耗时。统一日志语法从 JDK 9 起提供;老 JDK 用相应版本支持的参数。不要仅用平均暂停评价尾延迟。
RSS 高于 heap / 疑似 native 泄漏启动时启用 -XX:NativeMemoryTracking=summary
jcmd PID VM.native_memory summary
Heap 外的 Class/Thread/Code/GC/Internal/Compiler 等类别变化;结合容器 RSS、线程数、直接缓冲池与本地分配器。NMT 有开销且不能统计所有第三方 native 分配;需要启动时启用才能获得相应跟踪能力。
CPU 飙高top -H -p PID → 线程 ID 转十六进制 → jstack PID / jcmd PID Thread.print热点线程是在计算、锁竞争、忙循环,还是系统调用/GC;再用 JFR 或采样 profiler 定位调用栈。只看线程栈难以确定精确 CPU 占用;短周期多次采样比单次快照更有参考价值。
偶发长尾 / 不可复现问题jcmd PID JFR.start name=prod settings=profile duration=60s filename=/tmp/prod.jfr
jfr summary /tmp/prod.jfr
CPU 样本、锁竞争、线程停顿、分配、GC、I/O 与异常事件在同一时间轴上的相关性。评估事件级别/记录时长;JFR 文件可能含类名、路径、参数或业务数据,应限制访问并按安全要求脱敏。
疑似内存泄漏 / OOM-XX:+HeapDumpOnOutOfMemoryError
jcmd PID GC.heap_dump /path/dump.hprof
MAT / Eclipse Memory Analyzer
支配树、retained heap、GC Roots、集合/缓存增长、类加载器引用链;分清泄漏与合理的大存活集。堆转储可能非常大、耗时且包含敏感对象内容;磁盘空间与暂停风险需提前评估,不宜无差别生产执行。
Metaspace / 类加载器泄漏jcmd PID VM.classloader_stats(版本支持时)
JFR Class Loading 事件
jcmd PID VM.native_memory summary
类数量、动态生成类、类加载器存活链、Metaspace committed/used 走势,结合 redeploy/热加载周期判断。单纯类数量高不等于泄漏;重点看卸载预期与类加载器是否被静态引用、线程上下文类加载器等持有。
JIT / 分配优化异常JFR + async-profiler;必要时使用 JITWatch 分析编译日志内联失败/去优化、热点方法、锁消除、分配率与编译线程;将冷启动和预热后状态分开测。诊断参数/编译日志依 JDK 版本变化;避免在未建立基线前随意关闭分层编译或强制编译阈值。
JVM 排障证据链模板
  1. 先界定现象:响应时间 / 错误率 / QPS / CPU / RSS / GC pause 哪个首先变化,影响范围与起止时间是什么。
  2. 获取同一时间窗证据:部署版本与 JVM 参数、GC/安全点日志、JFR、线程快照、容器指标、业务流量与下游延迟。
  3. 提出可证伪假设:例如分配率过高、存活集变大、线程池饥饿、锁竞争、native 内存增长或 safepoint 到达延迟。
  4. 一次只改一个变量并对照:用相同流量/数据集比较 P50/P95/P99、错误率、CPU、内存与暂停分布,保留回滚方案。

2.1.15 从 JDK 8 升级到最新版本:兼容性核对清单

一次跨越 JDK 8 → 27 的升级不是简单替换运行时。建议用“目标版本选择、构建兼容、依赖与反射、运行参数、性能基线、灰度回滚”分阶段推进;业务系统不一定应直接生产采用非 LTS 的最新 feature release。

  • 构建与字节码:确认构建 JDK、编译目标与生产 JRE/JDK;用 `--release N` 锁定语言/API/字节码兼容级别,使用 `javap -verbose` 核对 major version(JDK 8 为 52,JDK 27 为 71)。
  • 模块与依赖:扫描 Java EE/CORBA、JAXB/JAX-WS、Nashorn、内部 `sun.*` API、`setAccessible` 深反射、Java Agent、字节码增强框架;先升级依赖到兼容版本,再考虑精确的 `--add-opens` 过渡。
  • JVM 启动参数:在目标 JDK 的真实构建上执行 `java -XX:+PrintFlagsFinal -version`(各版本参数支持有差异)并检查启动 warning;移除已经删除/失效的 CMS、旧 GC 日志以及旧参数。
  • GC 和对象布局:核对默认 GC 是否改变;JDK 23/24 的分代 ZGC 行为变化、JDK 27 G1 全环境默认与 Compact Object Headers 默认启用均应列入回归测试。
  • 虚拟线程与任务上下文:若引入虚拟线程,检查 `ThreadLocal` 大对象驻留、MDC/追踪上下文传播、锁和 pinning、数据库/HTTP 连接池上限,以及取消与超时是否能释放下游资源。
  • 本地接口与工具链:验证 JNI、Unsafe/对象偏移假设、探针/Profiler、AOT/CDS 缓存、容器运行镜像;确认供应商构建支持目标 GC 与诊断选项。
  • 性能与容量基线:同数据/同流量比较冷启动、预热时间、吞吐、P95/P99、GC CPU、分配率、live set、Metaspace、direct memory、RSS 与容器 OOM 风险。
  • 预览 API:JDK 27 的 Primitive Types in Patterns、Lazy Constants、Structured Concurrency 等仍为预览,Vector API 为孵化;除非明确接受版本锁定与变更成本,不作为一般业务的稳定 API 依赖。
  • 发布与回滚:在兼容性测试、压测、灰度和生产观测中逐步推进;把类加载失败、反射异常、GC 暂停、native RSS、TLS/字符集与时间区变化列入验收门槛。
企业升级建议:截至 2026-10-27,JDK 27 是最新 GA feature release;Oracle JDK 的最新更新为 27.0.1.0.3+1(2026-10-24),但不同供应商补丁号不同。JDK 25 是最新一代常见 LTS 选择。生产选型应按供应商支持周期、安全补丁、框架兼容与运维能力决策,而非仅因主版本最新就切换。

2.1.16 JVM 深水区:NUMA、致命崩溃与容器资源感知

本节将 JVM 参数、操作系统硬件拓扑和生产崩溃诊断放在同一个证据链中。NUMA、cgroup 与崩溃行为均有平台、JDK 更新版本和 GC 实现差异,不能把单一机器的压测结论推广为所有生产环境的规则。

NUMA:先识别拓扑,再判断是否需要绑核/绑内存
表 118:NUMA 调优与 JVM/容器资源证据链
检查维度诊断方法判读与风险
硬件拓扑lscpu -e、numactl --hardware、numastat -p <pid>确认 CPU 与内存节点数量、进程本地/远端分配比例;容器 CPU 集与内存节点限制也要一起看。
JVM 参数-XX:+UseNUMA;在目标 JDK 查看 java -XX:+PrintFlagsFinal -version 及对应 GC 文档。参数默认值和可用行为取决于收集器与 JDK 版本;不能假设它会在 G1、Parallel、ZGC 中以相同方式做物理内存绑定。先在同一 NUMA 拓扑下做基线压测。
可能症状观察吞吐、P99、GC pause、远端内存访问、CPU migrations 与 NUMA 命中情况。跨节点访问、内存带宽争用和不理想的线程放置可能增加尾延迟,但停顿变长不一定由 NUMA 单独造成;需与 GC 日志、线程调度和内存压力交叉验证。
调优原则对比默认策略、容器 CPU/内存拓扑和受控的 NUMA 策略。不要只因机器为双路 CPU 就启用参数;锁定 JDK/GC/硬件/负载后比较吞吐、P99、内存本地性和运行稳定性。
致命崩溃与 Core Dump:从 hs_err 到 JNI/本地库
  1. 保留证据:收集 hs_err_pid<pid>.log、Core 文件、JDK 精确版本/build、完整启动参数、容器限制、最近变更和动态库版本。
  2. 识别信号但不武断归因:SIGSEGV 常见于非法地址访问,SIGBUS 可能涉及未对齐访问或映射文件/底层内存异常;信号仅是线索,需结合 fault address、线程栈和 native frame 定位。
  3. 解析现场:用匹配的符号文件与调试符号,通过 gdb、coredumpctl、jhsdb(适用时)查看崩溃线程、寄存器、混合栈、堆与线程状态;不要用不同 build 的符号强行解释。
  4. 定位 JNI/FFM:核对 native library 的加载路径、ABI、符号、生命周期与缓冲区边界;排除过期指针、重复释放、越界写、错误的 direct buffer 地址和第三方 native 库。
  5. 复现与止血:在隔离环境缩小触发条件,必要时暂时关闭相关本地加速路径或回滚依赖;不要把升级 JDK 当作唯一诊断手段。

Core Dump 提前检查:Linux 下需确认进程 core-size 限制、kernel.core_pattern、容器写入权限、磁盘容量和敏感数据保管策略;生产 Core 可能包含凭据、业务数据和密钥,必须控制访问与保留期限。

cgroup v1/v2 与 JVM 容器感知
  • 容器 CPU 配额不等于宿主机逻辑核数;若 JVM 误判可用 CPU,GC 线程、ForkJoinPool、应用线程池与框架默认并行度可能被放大,导致调度抖动和 CPU throttling。
  • JDK 的容器感知能力随发行商与更新版本演进;早期 JDK 8 更新、厂商回移补丁、cgroup v1/v2 挂载方式可能不同,不能笼统说所有 JDK 8 都不支持 cgroup v2。
  • 排查时检查容器的 cpu.max/cpu.cfs_quota_us、cpuset.cpus.effective、memory.max/memory.limit_in_bytes;在支持的 JDK 上用 -Xlog:os+container=trace(旧版本日志参数不同)核验 JVM 的识别结果。
  • -XX:ActiveProcessorCount=N 可在支持的 JDK 中限制 JVM 对可用处理器数的认知,但应作为有依据的修正手段;还要同步检查线程池、连接池和 GC 并行度,而非仅修一个参数。

2.1.17 Async-profiler、Safepoint Bias 与 CPU/Wall-clock Profiling

性能剖析首先要分清“线程正在消耗 CPU”与“请求整体耗时很长”。部分依赖安全点协调或安全点抓栈的采样方案可能产生 Safepoint Bias:采样分布偏向容易在安全点停下的代码,从而低估某些长时间运行的紧密循环。Async-profiler 结合 Linux perf_events 与 HotSpot 的 AsyncGetCallTrace 等能力,降低传统安全点偏差,并支持 CPU、wall-clock、分配和锁竞争等剖析模式;它仍是采样工具,不保证捕获每个瞬间,也受操作系统权限、符号解析和平台限制。

表 130:Async-profiler 事件模式与问题定位
模式/命令示例主要观测对象适用问题与边界
-e cpu
asprof -d 30 -e cpu -f /tmp/cpu.html PID
线程消耗 CPU 的采样栈定位热点方法、密集计算、算法复杂度和 JIT 生成路径;CPU profile 不等于端到端延迟分布。
-e wall
asprof -d 60 -e wall -f /tmp/wall.html PID
运行、阻塞、睡眠等状态下的线程栈采样适合排查线程等待、锁竞争、I/O 阻塞、启动慢和线程池饥饿;需结合线程状态判断。
-e alloc分配采样及分配热点定位临时对象、装箱、集合扩容和大对象分配;采样不是对象分配的逐笔审计。
-e lockJava monitor/锁竞争及等待时长定位锁持有与等待热点;需确认运行时版本和所用事件是否受支持。
补充:JFR / JMCJVM 事件、延迟、分配、GC 与线程信息适合持续低开销观测与线上关联分析;事件配置、采样周期和版本会影响可见度。

实战判断:CPU 使用率持续高而请求延迟升高,先看 CPU profile;CPU 不高但请求仍慢,优先看 wall-clock、线程状态、连接池等待、远程依赖和锁。采样结果要与压测、请求 trace、GC 日志和系统指标交叉验证。采集前确认 perf_event 权限、容器 capability、安全策略及工具版本;生产火焰图可能暴露类名、SQL 或业务调用路径,需要按生产数据治理要求保存。

2.1.18 DirectByteBuffer、PhantomReference 与 Cleaner 堆外回收链

DirectByteBuffer 的 Java 包装对象位于堆中,其数据区通常来自堆外本机内存。包装对象不可达后,引用处理与 Cleaner/清理动作可安排底层内存释放;这条链路不是“堆内存释放即物理内存立即归还”的同步保证。JDK 内部实现(包括 Bits.reserveMemory、显式 GC 的重试策略与 deallocator 路径)会随版本变化,理解其原理后仍应以目标 JDK 的源码和运行指标为准。

表 131:Direct Memory 生命期与排障证据
环节机制与常见现象排查与治理
分配与预算分配路径预留 direct-memory 配额;达到 -XX:MaxDirectMemorySize 预算时,可能进入回收/重试路径,最终仍可能抛出 OutOfMemoryError: Direct buffer memory。记录目标 JDK 的默认值与实际启动参数;不能假设每次失败都必然同步调用 System.gc()。
引用与清理Cleaner 使用 PhantomReference/ReferenceQueue 感知对象进入 phantom-reachable 状态,再在清理线程执行动作;清理动作不得反向强引用待清理对象。优先使用明确的 close/释放 API 或受控生命周期;Cleaner 是兜底,不是确定时间的资源管理器。
内存观测堆内存正常并不代表进程 RSS 正常;direct、JNI、线程栈、代码缓存和原生库都可能贡献进程内存。查看 BufferPoolMXBean 的 direct/mapped 指标;必要时在启动时开启 Native Memory Tracking 并用 jcmd VM.native_memory 对比。NMT 不覆盖所有第三方原生分配。
回收边界Cleaner 回收时机取决于可达性分析与 GC/引用处理进度;进程退出也不保证每个清理动作都执行。长生命周期缓冲池要有容量上限、显式关闭、异常路径释放和监控;不要依赖 finalize() 实现关键资源回收。

Java 9 引入 Cleaner API;finalization 从 JDK 18 起被弃用并标记为待移除,而非所有 JDK 版本都已移除。排查时要区分 Java 堆 OOM、direct buffer 配额耗尽、容器 cgroup OOM 与系统原生内存不足。

2.1.19 JIT 逃逸分析衍生优化:锁消除与锁粗化

HotSpot JIT 可能基于类型信息、调用点与逃逸分析优化同步操作,但这些属于编译器在特定版本、编译层级和运行时剖面下作出的优化决策,不是源码里写了 synchronized 就一定消除锁。解释字节码、JIT 日志与真实竞争指标时,要把“语言语义保证”和“运行时优化可能性”分开。

表 132:锁消除与锁粗化的触发条件和验证方式
优化思路容易误判的地方
锁消除(Lock Elimination)若 JIT 能证明锁对象不逃逸,且相关同步对其他线程不可观察,可消除某些 monitorenter/monitorexit 操作。对象逃逸、反射/调用边界、去优化、不同编译层级都可能改变结果;不要把“局部对象”一概等价成一定无锁。
锁粗化(Lock Coarsening)将相邻或循环中的多次、同对象同步区合并到更大区域,减少重复进入/退出监视器的开销。合并后临界区变大可能影响并发性;这是编译器优化,不是鼓励人为扩大业务锁范围。
逃逸分析/标量替换当对象不需要作为整体存活时,JIT 可能拆解其字段,部分消除堆分配与关联同步。是否发生依赖 JDK、编译层级、方法内联和现场反馈;不要只看源码推断分配率。
验证方法用 JFR/async-profiler 观察分配与锁事件,结合目标 JDK 的编译日志、JITWatch 或受控基准测试。微基准要防止死代码消除、预热不足、编译污染和环境噪声;生产诊断优先看实际负载。

面试回答建议:先说明 HotSpot “可能”执行的优化,再讲触发条件、失效边界和如何测量,而不是把某一版 JVM 的实现细节说成 Java 语言规范。

2.2 并发编程栈(JUC 源码级与 JMM 深度)

表 5:并发栈复习条目

技术项 需掌握到的深度
JMM 底层 内存屏障(Load/Store Barrier)、happens-before、volatile 禁重排与可见性保证
硬件级并发极致 CPU 缓存行伪共享(False Sharing)、MESI 协议缓存行颠簸、@Contended 填充、LMAX Disruptor 环形无锁架构
AQS 框架 state 状态变量、CLH 双向队列、独占模式与共享模式的 acquire/release 流程;AQS 三组件源码差异
线程池 ThreadPoolExecutor 7 参数、饱和度监控指标、容量估算、CompletableFuture 陷阱
协作机制 协作式中断处理原则、任务取消传播、死锁与线程池饥饿间接死锁
并发容器 ConcurrentHashMap 从 Segment 分段到 Node+CAS+synchronized 的重构,transfer 多线程扩容
核心集合实现原理 HashMap 扰动函数与高低位扩容、LinkedHashMap LRU 双链表、TreeMap vs ConcurrentSkipListMap 跳表无锁并发、WeakHashMap 懒清理、IdentityHashMap 探测、ArrayList 连续内存与 subList 绑定、LinkedList 节点开销、CopyOnWriteArrayList 弱一致性、ArrayDeque 位运算循环、PriorityQueue 完全二叉小顶堆
新并发演进 虚拟线程适用边界与 pinning 治理、ScopedValue 转正(JEP 506)、结构化并发状态

2.2.1 并发三大特性与 Java 内存模型(JMM)

表 55:并发三大特性与底层解决机制

特性 含义 硬件/JVM 根因 常见解决机制
可见性 一个线程的写入能否被其他线程立即可见 CPU 缓存(L1/L2/L3)与写缓冲区(Store Buffer)延迟刷新 volatile、synchronized、显式锁、内存屏障(Load/Store Barrier)
原子性 一个或多个操作要么全部执行完毕,要么全部不执行 线程时间片轮转切换、多核心并发写内存 CAS 原语、锁、LongAdder 分段累加、原子类
有序性 程序执行的顺序是否按照代码编写顺序执行 编译器指令重排、CPU 乱序执行(Out-of-order execution) happens-before 原则、volatile 禁重排内存屏障、锁获取与释放规则
// volatile 经典状态标记应用(仅保证可见性,业务方法需自行保证线程安全)
private volatile boolean running = true;

public void stop() {
    running = false;
}

public void runLoop() {
    while (running) {
        doWork();
    }
}

2.2.2 三个共享模式组件的源码级区别

表 39:AQS 三组件对比

组件 AQS 模式 state 含义 是否可重用 关键区别 面试落点
CountDownLatch 共享(tryAcquireShared) 剩余计数,countDown() 减到 0 时唤醒所有等待线程 ❌ 一次性 基于 AQS 共享模式的传播唤醒 “一次性门闩,state 递减到 0 释放所有等待者”
CyclicBarrier 不直接基于 AQS(基于 ReentrantLock + Condition) 到达屏障的线程数,凑齐后 nextGeneration() 重置 ✅ 可重用 基于 Condition 的 await/signalAll,不是 AQS 共享传播;支持 Runnable 回调 “可重用屏障,每代凑齐后重置,支持 barrierAction”
Semaphore 共享(tryAcquireShared) 当前可用许可数,acquire() 减 1,release() 加 1 ✅ 反复使用 公平模式用 hasQueuedPredecessors() 保证 FIFO;非公平模式允许 barging “许可数,state 可反复加/减;公平模式用 CLH 队列保证先来先得”

2.2.3 虚拟线程适用边界与迁移三问

  • 适用场景:高并发 I/O 密集型业务(HTTP 调用、数据库查询、RPC)。不适用 CPU 密集型计算。
  • Pinning 解决状态:JDK 24 起(JEP 491)已消除 synchronized 块引起的载体线程挂起锁定;调用 JNI/Native 方法阻塞仍可能导致 Pinning。
  • 迁移三问:
    1. 虚拟线程要不要池化?不要。 “one virtual thread per task”是设计初衷,池化会破坏 M:N 调度模型。
    2. ThreadLocal 怎么迁移?对不可变、具有明确动态作用域的上下文值,可优先评估 JDK 25 转正的 ScopedValue(JEP 506);它不是所有 ThreadLocal 用法的直接替代,ThreadLocal 也不会仅因虚拟线程数量多就必然泄漏。
    3. 怎么渐进替换? 先替换下游纯 RPC/阻塞调用的线程池,配合 JFR 观察调度延迟与 Pinning 监控指标。

2.2.4 结构化并发的版本状态

截至 JDK 27(2026-10),结构化并发仍为预览特性:JDK 25 为第五次预览(JEP 505)、JDK 26 为第六次预览(JEP 525)、JDK 27 为第七次预览(JEP 533)。使用预览 API 需按对应 JDK 的要求在编译与运行阶段启用 --enable-preview;接口仍可能调整,不应把它描述为已正式稳定。

2.2.5 锁升级、CAS 与并发设计五问

  • 锁升级:偏向锁(JDK 15 废弃、JDK 21 彻底移除) \(\to\) 轻量级锁(CAS 修改 Mark Word 为栈帧 Lock Record) \(\to\) 重量级锁(膨胀为 ObjectMonitor,线程挂起于 WaitSet/EntryList)。
  • CAS 与 ABA 问题:硬件级 cmpxchg 指令保证原子比较交换;ABA 问题通过版本号解决(如 AtomicStampedReference)。
  • 并发计数优化:LongAdder 在高并发冲突下优于 AtomicLong,利用分段 Cell[] 数组通过哈希映射分散单点 CAS 竞争,最后聚合汇总。
  • 并发设计前必须回答的五问:
    1. 并发操作是否必须原子执行?
    2. 是否允许短暂的最终一致?
    3. 竞争是否集中在少数热点变量上?
    4. 是否存在 ABA 或状态回退风险?
    5. 是否可以通过批处理、分段分区或无状态化从架构上消除竞争?

2.2.6 线程池的运行机制、监控与容量估算

  • 任务提交与扩容逻辑:核心线程 \(\to\) 阻塞队列 \(\to\) 最大线程 \(\to\) 拒绝策略。
  • 避免无界队列:Executors.newFixedThreadPool 默认采用无界 LinkedBlockingQueue,突发流量下极易导致 OOM。
  • 线程池运行监控指标(八大指标):
    1. 活跃线程数;2. 当前池大小与最大池大小;3. 队列当前长度与剩余容量;4. 任务提交总数;5. 任务完成总数;6. 任务拒绝总数(Reject Count);7. 任务平均与 P99 执行耗时;8. 任务在队列中的排队等待耗时。
  • CompletableFuture 三大陷阱:
    1. supplyAsync 默认使用 ForkJoinPool.commonPool(),慢 I/O 会耗尽公共池并拖死全局 parallelStream,必须显式传递自定义业务线程池。
    2. thenApply 由执行前一阶段的线程执行,非异步;需显式使用 thenApplyAsync(..., executor) 隔离。
    3. orTimeout 仅使 Future 超时完成,不会物理中断正在进行的底层网络连接,超时预算必须下沉到底层 Client。

2.2.7 线程协作式中断、任务取消与超时传播

  • 协作式中断机制:Thread.interrupt() 并不强制杀死线程,只是设置中断状态。若线程在 sleep/wait/join 阻塞,会抛出 InterruptedException 并重置标志位。
  • 正确处理规范:捕获 InterruptedException 后,若无法在本层处理,必须重新设置中断位(Thread.currentThread().interrupt())或向上抛出,绝不能吞没中断信号。
try {
    blockingOperation();
} catch (InterruptedException e) {
    // 恢复中断标记,确保上层调度器获知中断请求
    Thread.currentThread().interrupt();
    return;
}
  • 超时与取消传播:Future.cancel(true) 会尝试调用执行线程的中断,但若底层网络库或驱动不支持响应中断,连接仍将卡死;分布式场景必须结合超时预算与调用链 Context 主动取消下游。

2.2.8 死锁、活锁与资源依赖排查证据链

  • 死锁四个必要条件:互斥、占有且等待、不可抢占、循环等待。打破策略:固定全局锁加锁顺序、引入 tryLock(timeout) 超时退避。
  • 活锁与饥饿:活锁即线程都在主动退让重试却都无法推进(引入随机退避 Jitter 解决);饥饿即低优先级线程长期拿不到 CPU 或锁资源。
  • 七步排查顺序:
    1. 发现接口超时、吞吐断崖下跌或监控告警;
    2. jstack -l <pid> 获取线程转储,排查 BLOCKED 与 WAITING 状态线程;
    3. 搜索 Found one Java-level deadlock: 明确相互等待的 monitor 锁持有者;
    4. 检查是否有父子任务共用同一个有界线程池导致的“线程池饥饿间接死锁”;
    5. 对照数据库连接池与外部 RPC 调用栈;
    6. 修复锁顺序或打破循环等待;
    7. 引入并发压测回归验证。

2.2.9 CPU 缓存行伪共享(False Sharing)与 LMAX Disruptor 无锁架构

当多线程高并发系统要求单机承载百万级 QPS 时,性能瓶颈会直接转移到 CPU 硬件级缓存一致性协议(MESI)。伪共享(False Sharing)是这一层级的头号杀手。

概念/组件 底层机制与架构解析
缓存行伪共享(False Sharing) 现代 CPU 缓存以缓存行(Cache Line,通常为 64 字节)为基本单位。若变量 A 与变量 B 物理上相邻位于同一个 64 字节缓存行内,当 Core 1 上的线程修改 A,Core 2 上的线程修改 B 时,尽管业务上互不影响,底层 MESI 协议仍会强制将对方的核心缓存行置为 Invalid。两核心间频繁通过总线同步最新缓存行,引发严重的 Cache Line Bouncing(缓存行颠簸),使多核并行退化为串行
解决方案:内存填充与 @Contended ① 手动填充(Padding):在关键变量前后定义 7 个无用的 long 变量(\(7 \times 8 = 56\) 字节),确保目标变量独占整个 64 字节缓存行;② JVM 原生注解 @Contended:JDK 8 引入,由 JVM 自动在字段周围插入填充字节(需开启 -XX:-RestrictContended 参数,JDK 9+ 默认对特定内部类开启)
LMAX Disruptor 架构核心 ① 预分配环形数组(RingBuffer):避免高频 GC,通过位运算 sequence & (bufferSize - 1) 取模定位槽位;② 缓存行填充序列号(Sequence):通过字节填充消除生产者与消费者的 Sequence 伪共享;③ 无锁游标协调(CAS 代替锁):采用内存屏障与单调递增游标协调单生产者/多消费者,吞吐量比 ArrayBlockingQueue 高 5~10 倍

2.2.10 并发核心 API 与协作题型对照

PDai 的并发题库强调线程状态、互斥与协作、线程池、ThreadLocal、FutureTask、ScheduledThreadPoolExecutor、Phaser 和 Exchanger;《成神之路》也强调 start/run、sleep/wait、notify/notifyAll 与生产者—消费者。下面整理成便于面试对比的语义表,并与本章线程池、JMM 和中断专题配合复习。

表 81:并发 API 语义与协作机制

主题核心语义面试追问与生产边界
start() vs run()start() 让 JVM 调度新线程执行一次;直接调用 run() 只是当前线程的普通方法调用。一个 Thread 实例不能重复 start。线程创建、任务执行与线程状态不是一回事;优先使用 Executor 管理任务。
sleep() vs wait()sleep() 不释放已持有的监视器;wait() 必须先持有同一对象监视器,并在等待期间释放它,收到通知后重新竞争锁。等待条件必须放在 while 中重新检查,不能假设唤醒即意味着条件成立。
notify() vs notifyAll()notify() 任意唤醒一个等待者;notifyAll() 唤醒所有等待者,之后仍需竞争锁。多个条件队列或等待条件异构时,误用 notify 可能留下符合条件的线程无人唤醒。
中断与取消interrupt() 是协作式取消信号,不是强制杀线程;阻塞方法抛出 InterruptedException 时通常会清除中断标记。处理后继续抛出,或在无法抛出时恢复标记:Thread.currentThread().interrupt()。
ThreadLocal 与线程池ThreadLocalMap 的 key 为弱引用,但 value 是强引用;在线程池中,工作线程可能长期存活并保留 value。使用 try/finally 清理:threadLocal.remove();注意 MDC、用户上下文和租户上下文的传播边界。
FutureTask vs CompletableFutureFutureTask 将 Callable/Runnable 封装为可等待结果的任务;CompletableFuture 额外提供阶段组合、异常处理与异步编排。显式选择执行器;避免在公共 ForkJoinPool 中阻塞等待慢 I/O,留意异常链与超时传播。
周期任务调度scheduleAtFixedRate 按计划频率追赶;scheduleWithFixedDelay 在上次执行结束后再等待固定间隔。周期任务若抛出未处理异常,后续执行可能被抑制。明确是否允许重叠、补跑、跳过、超时取消及关闭策略;耗时任务通常优先考虑固定延迟。
同步器选择CountDownLatch 通常一次性;CyclicBarrier 可重复使用且固定参与方;Phaser 支持动态注册参与者和多阶段推进。按参与方是否动态、是否分阶段、是否需要重复使用选择,不要仅按类名背诵。
Exchanger vs SynchronousQueueExchanger 让两个线程交换数据;SynchronousQueue 不存储元素,要求生产者与消费者直接交接。二者都不适合被当成普通有缓冲队列;容量与交接语义影响背压设计。
有界生产者—消费者有界队列能把吞吐不匹配转化为可观测的背压;无界队列可能把故障延迟转化为内存堆积。明确队列容量、拒绝/阻塞策略、关闭信号、积压告警、重试上限及任务幂等性。
synchronized vs Lock显式 Lock 可提供可中断获取、tryLock、多个 Condition 和可选公平策略;内置监视器使用简单且会自动释放。Lock 必须在 finally 中 unlock;不要笼统断言某种锁永远更快,需结合竞争度和目标 JDK 测量。

2.2.11 VarHandle:Plain、Opaque、Acquire/Release 与 Volatile

VarHandle 是 Java 9 引入的强类型变量访问抽象,可引用实例字段、静态字段、数组元素等,并提供不同内存序的读写与原子更新。它不是简单地“替代所有 Unsafe”,而是把可用访问模式和内存语义显式化。

表 119:VarHandle 内存访问模式与排序语义
模式代表操作内存序语义(简述)典型使用边界
Plainget / set普通访问;不建立线程间可见性/排序保证(仍受 Java 内存模型其他规则约束)。无并发共享语义要求的访问;不能把它当成 volatile。
OpaquegetOpaque / setOpaque对同一变量提供一致的、不撕裂的访问顺序约束,但不建立完整的跨变量 acquire/release 顺序。极细粒度状态观察;必须能证明仅需同变量一致性。
Acquire / ReleasegetAcquire / setReleaseRelease 之前的访问不能被重排到发布之后;匹配的 Acquire 读到该发布后,后续访问不能被重排到获取之前。发布/读取一次性初始化状态、无锁发布数据结构;需用 happens-before 推理。
VolatilegetVolatile / setVolatile提供 volatile 读写的内存语义;volatile 访问之间有更强的全序约束。需要与 volatile 字段同等语义时;可能比较弱模式付出更高排序成本。
原子更新compareAndSet、compareAndExchange、getAndAdd按指定访问模式提供原子条件更新/数值更新;具体支持模式取决于 VarHandle 类型。仍须考虑 ABA、竞争重试、活锁、公平性和复合不变量;单次 CAS 不等于多个字段的事务。

硬件屏障不是 Java API 承诺的直接一一映射:HotSpot 会基于目标 CPU 架构和 JIT 生成必要指令。面试时应先陈述 Java 内存模型保证,再谈 x86/ARM 上可能的实现差异;未经测量,不应仅为减少屏障而从 volatile 改成较弱模式。

2.2.12 JCTools 无锁队列与虚拟线程的阻塞边界

JCTools:根据生产者/消费者拓扑选队列
表 120:JCTools 队列拓扑与并发约束
类型含义优势与约束
SPSCSingle Producer / Single Consumer单写单读可减少争用;调用拓扑一旦违反,正确性假设即失效。
MPSCMulti Producer / Single Consumer多个生产者提交、单消费者串行消费;MpscArrayQueue 使用有界环形数组并优化游标发布,适合 Netty 等场景的同类拓扑。
SPMC / MPMC单生产者多消费者 / 多生产者多消费者并发竞争和协调成本更高;要按容量、有界性、延迟分布及实际线程拓扑做基准测试。
  • 伪共享:热点游标/计数器被不同核心频繁修改时,缓存行所有权转移会增加成本。部分实现使用 padding/字段布局降低 false sharing,但内存开销、JDK 字段布局和版本实现均需实测。
  • 环形序列:生产者发布槽位前必须确保元素可见;消费者读取后应正确回收槽位。容量、游标回绕和发布顺序属于算法正确性的一部分,不应仅根据“无锁”标签推断一定更快。
  • 生产使用:优先选择成熟队列实现,不自创无锁算法;验证满队列策略、背压、取消、内存可达性、队列观测成本与压测尾延迟。
虚拟线程与普通文件 I/O:不要把所有阻塞都等同于 Socket 阻塞

虚拟线程对许多 JDK 支持的阻塞操作能在等待时卸载载体线程,但并非任意本地调用/文件系统操作都保证以相同方式卸载。普通文件 I/O 的可等待语义与 Socket/selector 不同,具体行为受 JDK、文件系统、Native 路径和实现影响。对高频文件读写、同步文件系统调用或 native 库调用,必须在目标 JDK 与生产文件系统上验证载体线程占用;需要时用异步 I/O、专用有界执行器、批量化与背压隔离,不能只把平台线程替换成虚拟线程就认为容量问题消失。

2.3 语言版本与新特性栈

2.3.1 JDK 8–27 核心功能演进全景对照

表 6:JDK 8–27 核心功能演进全景(含语言、标准库、JVM 与 GC)

阅读口径:“JDK 版本功能”与“某发行版实际包含的功能”不是同一件事。GC、JIT、诊断能力及默认参数会受 HotSpot/其他 JVM、供应商构建、平台和启动参数影响。LTS 标签也属于发行商支持策略,不是 Java SE 规范强制属性;JDK 8/11/17/21/25 常被主流供应商作为 LTS,当前最新 GA 为 JDK 27,最近的 LTS 为 JDK 25。
版本 / class 文件主版本语言与标准库核心变化JVM、GC、启动与诊断变化迁移与面试落点
JDK 8 · 2014-03
52 · 常见 LTS
Lambda、Stream、Optional、接口默认方法、JSR-310 时间 API、CompletableFuture;函数式/流式编程成为现代 Java 基础。PermGen 移除,改为 Metaspace;HotSpot 仍以 Parallel GC 等传统收集器为常见默认选择,取决于 VM 模式与构建。迁移关注 PermGen 参数失效、元空间与本地内存;`-Xmx` 不是进程 RSS 上限。
JDK 9 · 2017-09
53
JPMS 模块系统、JShell、集合工厂方法、Stack-Walking API;平台模块边界开始影响反射访问。G1 在 server-class 配置中成为默认 GC;统一日志 `-Xlog`、CDS 改进、`jlink` 自定义运行时。GC 日志参数从旧式 `PrintGCDetails` 等向 `-Xlog:gc*` 迁移;强封装与模块可见性会影响旧框架。
JDK 10 · 2018-03
54
局部变量类型推断 `var`;语言本身变化相对小,工程侧强调容器环境。容器 CPU/内存感知增强;G1 Full GC 可并行;AppCDS 扩展。检查容器配额识别与 CPU 核数;容器限制、JVM ergonomics 与线程池容量需一起验证。
JDK 11 · 2018-09
55 · 常见 LTS
标准 HTTP Client(HTTP/2、异步 API)、String 增强、单文件源码运行;TLS 1.3。JFR 开源;ZGC、Epsilon GC 在相应 OpenJDK 构建中以实验性方式提供;删除 Java EE/CORBA 模块。盘点 JAXB/JAX-WS 等依赖及替代包;GC 是否可用、可用平台与发行版差异需实测。
JDK 12 · 2019-03
56
Switch Expressions 首次预览;String 新方法与微基准工具改进。Shenandoah 在部分 OpenJDK 构建中实验性提供;G1 引入可中止的 Mixed GC 以控制回收成本。GC pause 不是只由算法名称决定,要结合分配速率、存活集与并发回收 CPU。
JDK 13 · 2019-09
57
Text Blocks 首次预览;动态 CDS 归档。ZGC 可将未使用的堆内存归还给操作系统;小对象/堆内存占用不等于进程 RSS。关注容器内存回收、空闲堆与 RSS 差异;Text Blocks 当时仍为预览功能。
JDK 14 · 2020-03
58
Switch Expressions 正式;Records 与 `instanceof` 模式匹配预览;Helpful NullPointerExceptions。CMS 移除;JFR Event Streaming;G1 NUMA 感知改进;ZGC 支持的平台随发行版而异。CMS 退役前需完成迁移;借助 NPE 增强信息更快定位链式访问空值来源。
JDK 15 · 2020-09
59
Text Blocks 正式;Sealed Classes 预览;隐藏类(Hidden Classes)。ZGC/Shenandoah 在包含它们的构建中进入产品级状态;默认禁用偏向锁;移除 Nashorn。隐藏类是框架/代理生成类的实现工具,不是普通业务类的替代;不要依赖已移除 Nashorn。
JDK 16 · 2021-03
60
Records 正式;`instanceof` 模式匹配正式;Unix Domain Socket 支持。Elastic Metaspace 降低空闲元空间碎片与归还延迟;ZGC 并发处理线程栈等改进。升级后关注元空间 Native Memory Tracking 变化、序列化兼容与反射框架访问。
JDK 17 · 2021-09
61 · 常见 LTS
Sealed Classes 正式;强封装 JDK 内部 API 成为默认;macOS/AArch64 支持。`--illegal-access` 不再恢复整体宽松访问;特定深反射场景需显式 `--add-opens`(仅作为过渡手段)。重点排查 CGLIB/ORM/代理/字节码工具、Java Agent 和使用 `sun.*` 的依赖。
JDK 18 · 2022-03
62
UTF-8 成为默认字符集;简单 Web Server;Javadoc `@snippet`。Finalization 弃用并计划移除;核心反射实现改用 Method Handles。检查文件/网络编码假设、区域环境下的中文乱码、依赖 finalize 的资源释放逻辑。
JDK 19 · 2022-09
63
虚拟线程首轮预览;Record Patterns 预览;Structured Concurrency 与 FFM 进入预览/孵化阶段。Project Loom、Foreign Function & Memory 等方向开始进入可体验阶段,但 API 仍可能变化。预览功能需显式启用,不能把预览 API 当作稳定生产契约。
JDK 20 · 2023-03
64
虚拟线程第二轮预览;Scoped Values、Structured Concurrency 与 FFM 继续演进。线程模型与外部内存访问 API 的迭代阶段;JVM 层适配与诊断工具持续完善。关注预览版之间的 API 变更;升级应用不要直接依赖早期预览实现细节。
JDK 21 · 2023-09
65 · 常见 LTS
虚拟线程正式(JEP 444);Record Patterns、Pattern Matching for switch 正式;Sequenced Collections。Generational ZGC 引入(在 JDK 21 为实验性/需显式启用);Scoped Values、Structured Concurrency 当时仍预览。虚拟线程适合大量阻塞 I/O,不会让 CPU 密集任务变快;检查 pinning、ThreadLocal 和下游连接池容量。
JDK 22 · 2024-03
66
Foreign Function & Memory(FFM)API 正式;未命名变量/模式、多文件源码启动器。G1 对 JNI Critical 区域引入 Region Pinning 改进;Class-File API 与 Stream Gatherers 等继续预览。FFM 可减少部分 JNI 样板,但仍须管理生命周期、边界检查与本地崩溃风险。
JDK 23 · 2024-09
67
Markdown 风格文档注释;Stream Gatherers 等继续预览。ZGC 的分代模式成为默认,非分代模式弃用;Graal JIT 仅在特定发行版(如 Oracle JDK)按相应方式提供。GC 默认行为变化要通过启动参数和运行日志确认;别把 Oracle JDK 的专有发行差异当作所有 OpenJDK 构建共性。
JDK 24 · 2025-03
68
Security Manager 永久禁用;JEP 485 Stream Gatherers 在 JDK 24 正式转正,支持自定义 Stream 中间操作;JEP 484 Class-File API 在 JDK 24 正式转正,提供标准 class 文件解析、生成与转换 API(java.lang.classfile)。Compact Object Headers 为实验性功能(JEP 450);AOT Class Loading & Linking(JEP 483);虚拟线程在 synchronized 监视器上的阻塞不再按旧方式 pinning;移除非分代 ZGC。清理 Security Manager 依赖;不要再依赖 ZGC 非分代模式;Stream Gatherers 与 Class-File API 是 JDK 24 正式功能。确认构建使用的 --release 与运行 JDK 一致,升级字节码工具链并运行兼容测试。
JDK 25 · 2025-09
69 · 最新 LTS
Scoped Values、模块导入声明、Compact Source Files 与 Instance Main Methods 正式;部分模式匹配仍为预览。Compact Object Headers 成为产品特性但默认未开启;AOT CLI ergonomics 与 Method Profiling;JFR 增强;部分构建支持分代 Shenandoah。LTS 适合作为企业升级重点候选;对象头功能的可用性/默认值、分代 Shenandoah 参数以供应商发行说明为准。
JDK 26 · 2026-03
70
HTTP Client 增加 HTTP/3 支持;Primitive Types in Patterns、Lazy Constants、Structured Concurrency 继续预览/演进。G1 减少同步开销(JEP 522);AOT Object Caching 扩展为 GC-agnostic(JEP 516);继续推进预览/孵化特性。HTTP/3 的实际可用性仍取决于服务端、网络和实现;对预览 API 做兼容性封装。
JDK 27 · 2026-09
71 · 当前最新 GA
Primitive Types in Patterns 第五轮预览;Lazy Constants 第三轮预览;Structured Concurrency 第七轮预览;Vector API 第十二轮孵化。G1 成为所有环境默认 GC(JEP 523);Compact Object Headers 默认启用(JEP 534,64 位 HotSpot 对象头从 96 bit 降至 64 bit);JFR 进程内敏感数据脱敏(JEP 536);TLS 1.3 加入后量子混合密钥交换支持;`UseCompressedClassPointers` 选项不再生效。先看启动参数弃用/移除警告、对象头布局假设、JFR 敏感数据与预览 API;Oracle 最新更新为 27.0.1.0.3+1(2026-10-24),其他供应商版本号不同。

class 文件主版本号从 JDK 8 的 52 起每个主要版本递增 1:major = JDK 主版本 + 44。使用 `javap -verbose SomeClass` 可检查字节码版本;构建兼容性优先使用 `javac --release N`,而不是只设 `-source`/`-target`。

2.3.2 GraalVM AOT 的收益、限制与选型判断

  • 核心收益:启动时间从秒级降至毫秒级,内存显著降低,无 JIT 预热,契合 Serverless/FaaS。
  • 核心限制:反射、动态代理、动态类加载、JNI 需要在编译前提供完整的 JSON 元数据配置;构建时间极长;调试困难。
  • 替代路线 CRaC:Coordinated Restore at Checkpoint,通过内存快照实现亚秒级极速热启动,无需牺牲 JIT 峰值吞吐。
2.3.2.1 Java 启动加速三条路线:Native Image、CRaC 与 Leyden AOT Cache

不要把三条路线简单排成固定优劣序。它们优化的阶段不同:Native Image 把应用与可达代码提前编译为本机可执行文件;CRaC 恢复检查点前已经运行/预热的 JVM 进程状态;Project Leyden 的 HotSpot AOT Cache 仍运行在常规 JVM 上,逐步缓存类加载/链接、方法画像与对象数据。必须在目标 JDK、依赖和部署环境上实测冷启动、首请求延迟、稳态吞吐、RSS 与运维复杂度。

表 142:Java 启动加速方案决策对照
路线主要收益主要约束与风险更适合的场景
GraalVM Native Image生成本机可执行文件,通常可降低冷启动和常驻内存,不需要传统 JIT 预热。封闭世界/可达性分析会暴露反射、动态代理、资源、序列化与动态类加载假设;需补 Reachability Metadata/Runtime Hints。峰值吞吐、内存和启动收益依工作负载而异,不能一概断言低于或优于 JIT。命令行工具、短生命周期任务、Serverless、启动和内存目标优先且依赖可兼容的服务。
CRaC(Checkpoint/Restore)保存已启动或预热的常规 JVM 状态,恢复后可跳过大量初始化/预热阶段,保留 JIT 运行模式。检查点前需关闭或协调 Socket、文件句柄、线程、定时器、连接池与随机数等资源;恢复后需重建不可复用资源并验证环境一致性。恢复时间与快照大小、平台和应用状态有关。启动初始化成本高、实例频繁伸缩且能够控制检查点与恢复钩子的服务。
Project Leyden / HotSpot AOT CacheJDK 24 的 AOT 类加载/链接,JDK 25 的命令行与方法画像改进,JDK 26 的 AOT 对象缓存,逐步减少常规 JVM 的启动和预热成本。不是 Native Image,也不意味着所有代码已 AOT 编译;缓存和训练流程需匹配 JDK 构建、应用依赖、启动参数及部署条件。未被画像覆盖的代码仍可能需要运行时优化。希望保留 HotSpot、动态反射和现有 Java 运行模型,同时改善启动与预热的存量应用。

版本口径:JEP 483 在 JDK 24、JEP 514/515 在 JDK 25、JEP 516 在 JDK 26 引入相应 AOT Cache 能力。它是渐进演进的启动加速方案,不应写成“开放世界下无需校验任何动态行为”或“无需预热即可达到峰值 JIT 性能”。

2.3.3 Java 21/25 新特性深入:模式匹配与有序集合

  • Pattern Matching for instanceof & Switch:消除显式强转,支持空值处理与条件守卫(when)。
  • Record Patterns:解构对象属性,配合 sealed class 实现模式穷尽性检查。
  • Sequenced Collections(JEP 431):统一了 getFirst()、getLast()、reversed() 访问有序视图的 API 规范。

2.3.4 Project Panama(FFM API):告别 JNI,安全调用原生代码

表 44:JNI 与 Project Panama (FFM API) 对比

维度 传统 JNI Project Panama (FFM API, Java 22+)
类型安全 ❌ 运行时易崩溃,无编译期类型检查 ✅ 编译期强类型绑定,基于 MethodHandle
内存安全 ❌ 手动申请释放容易内存泄漏或段错误 ✅ MemorySegment 与 Arena 自动托管(AutoCloseable)
胶水代码 必须编写 C/C++ 动态链接库头文件 纯 Java API 调用,零 C 胶水代码
调用开销 JNI 穿透开销较大 JIT 内联调用桩,性能接近手写 C
// Panama FFM API 典型用法:分配原生内存并保证安全回收
try (Arena arena = Arena.ofConfined()) {
    MemorySegment segment = arena.allocate(100);
    segment.set(ValueLayout.JAVA_BYTE, 0, (byte) 42);
} // 离开作用域立即自动安全释放堆外物理内存

2.3.5 JDK 26/27 新特性与版本状态(截至 2026 年 10 月)

截至 2026-10-27,Oracle JDK 27.0.1.0.3 于 2026-10-24 正式发布;Oracle 下载页当前将 JDK 27 标为最新功能版本、JDK 25 标为最新 LTS。 这只代表 Oracle 发行线;其他 OpenJDK 发行版的版本、补丁、支持周期与安全基线应以各供应商公告为准。新版本 GA 不代表所有生产系统都应立即升级,需结合依赖兼容、测试基线、支持周期与回滚能力判断。

主题版本状态面试与生产注意点
G1 默认收集器JDK 27(JEP 523)将 G1 默认选择扩展到所有环境。不要再按“客户端环境一定默认 Serial”回答;显式指定的 GC 参数仍会影响选择。升级前对比吞吐、P95/P99、GC 暂停和容器 CPU。
紧凑对象头JDK 25 的 JEP 519 将其从实验性功能转为产品功能;JDK 27 的 JEP 534 默认启用。官方说明 64 位架构上的对象头布局从 96 bit 缩减至 64 bit;总体堆内存收益取决于对象数量、对齐与对象分布,不宜承诺固定“节省 20%”。JDK 27 中 UseCompressedClassPointers 已过时(obsolete),应清理旧启动脚本里的该参数。
结构化并发JDK 27 为第七次预览(JEP 533),尚未正式化。预览功能需匹配编译器与运行时版本并启用预览开关;生产库 API 设计应避免无意绑定到预览接口。
HTTP/3 ClientJDK 26 的标准 HTTP Client 增加 HTTP/3 支持(JEP 517)。不要把“有 API 支持”直接等同于生产链路已端到端可用;需测量代理、负载均衡、TLS、网络策略、连接迁移和服务端协商行为。
JDK 26 其他重要变化G1 同步开销优化(JEP 522);AOT 对象缓存支持任意 GC(JEP 516);深反射修改 final 字段进入警告阶段(JEP 500);移除 Applet API(JEP 504)。升级前重点回归依赖反射修改 final 字段的 ORM/序列化/测试框架;如使用 AOT Cache,需检查所选 GC、镜像构建与启动参数的兼容性。
原始类型模式匹配与 Lazy ConstantsJDK 27 的原始类型模式匹配为第五次预览(JEP 532);Lazy Constants 为第三次预览(JEP 531)。预览特性适合试验和技术验证;记录开关、源码兼容性和下一版本迁移成本,勿误称为正式语言/库特性。
Vector API 与 PEM 编码Vector API 为第十二次孵化(JEP 537);PEM 编码密钥、证书等密码对象的 API 为第三次预览(JEP 538)。Vector API 仍处孵化阶段,接口可能继续变化;PEM 编码 API 的预览状态同样不代表生产接口稳定。仅在明确需要向量化数值计算或标准化密码对象 PEM 编解码时评估。
最终字段反射修改JDK 26 起对通过深反射修改 final 字段的行为发出警告,JDK 27 仍需关注相关兼容性与未来限制。排查依赖反射改写 final 字段的框架、ORM、序列化库和测试工具;不要用关闭警告替代依赖升级及兼容性验证。
JDK 27 移除项与废弃参数Oracle JDK 27 发布说明列出部分工具/参数移除,例如移除 JVMCI 组件、相关模块与 -XX:+UseGraalJIT,以及 -noverify、-Xverify:none、-noclassgc、-verifyremote 等旧选项。旧选项迁移应逐项核对 Oracle/OpenJDK 对应发行版说明:-noclassgc 可评估使用 -Xnoclassgc,-verifyremote 可评估使用 -Xverify:remote;-noverify/-Xverify:none 没有直接替代项。不要假定其他供应商构建或定制 JDK 完全相同。升级前扫描容器镜像、启动脚本、构建流水线、监控诊断脚本和 Graal/JVMCI 集成;按目标 JDK 的 Migration Guide 与具体发行版说明核对,不能简单删除参数后就假设行为无变化。
JFR 数据脱敏JDK 27 引入 JFR 进程内数据脱敏能力(JEP 536)。生产诊断时仍应落实录制权限、文件留存、访问控制和敏感信息审查;脱敏能力不是忽略日志治理的理由。
  • LTS 与生产基线:Java 25 是 LTS 并不意味着必须立即迁移;对现有 Java 8/11/17/21 系统,应按依赖、JDK 供应商、安全支持、GC 行为、Agent/native library 兼容性和灰度回滚方案制定升级计划。
  • 版本事实边界:JDK 的特性预览次数、默认参数和废弃/移除状态都可能逐版本变化。回答面试题时先说清 JDK 版本,再说明该版本的具体行为;不把某一发行版的实现细节泛化为 Java 语言规范。

官方资料:JDK 27 Release Notes · JDK 27 Changes and Issues · JDK 26 Release Notes · JDK 27 GC Tuning Guide.

2.4 Java 语言机制、集合框架与标准库边界

2.4.1 Java 集合框架源码级深入与全架构剖析

表 49:核心集合组件机制对比与高频追问

集合组件 底层数据结构 扩容机制与因子 线程安全性 关键机制与高频追问
HashMap 数组 + 链表 + 红黑树(JDK 8+) 默认容量 16,负载因子 0.75,扩容翻倍(\(newCap = oldCap \ll 1\)) ❌ 非线程安全 为什么是 0.75(泊松分布时空折中);容量为 2 的幂以 (n-1)&hash 替代取模;树化阈值 8,退化链表阈值 6
ConcurrentHashMap 数组 + 链表 + 红黑树 CAS + synchronized 锁桶头节点,多线程协作 transfer 迁移 ✅ 线程安全 弱一致性迭代器不抛 CME;size() 采用 CounterCell[] 分散计数;不允许 key 或 value 为 null
ArrayList 动态 Object 数组 初始容量 10,扩容 1.5 倍(\(old + (old \gg 1)\)) ❌ 非线程安全 随机访问 \(O(1)\),中间插入移动元素 \(O(n)\);扩容由 Arrays.copyOf 实现
LinkedList 双向链表(Node) 无容量限制,动态添加节点 ❌ 非线程安全 内存开销大(前后指针引用);查找必须遍历 \(O(n)\),头尾操作 \(O(1)\)
2.4.1.1 Map 体系核心实现原理与底层寻址
  1. HashMap 散列扰动函数与高低位扩容:
    • 散列扰动函数:

      static final int hash(Object key) {
          int h;
          return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
      }
      

      通过高 16 位与低 16 位异或,在数组较小(如 16,掩码 15 即低 4 位为 1)时,将高位特征混合至低位,极大降低低位特征相同引发的哈希冲突。

    • 高低位指针扩容(JDK 8+): 扩容翻倍后,无需重新计算 hash。依据 (e.hash & oldCap) == 0:

      • 若为 0:新位置等于原位置(loHead/loTail 链表);
      • 若为 1:新位置等于原位置 + oldCap(hiHead/hiTail 链表)。 JDK 8 改用尾插分拆链表,避免了 JDK 7 头插法在特定并发扩容场景中出现链表成环的经典问题;但 HashMap 依然不是线程安全容器,并发写仍需外部同步或改用并发容器。
    • 树化阈值 8 与退化阈值 6 的数学依据: 在理想随机哈希码等假设下,桶节点数可用泊松分布近似描述(参数 \(\lambda \approx 0.5\)),桶中达到 8 个及以上节点的概率约为 \(6 \times 10^{-8}\)(约一亿分之六)。这说明长链桶在理想分布下较少见,但不代表每次都由攻击导致。JDK 8 HashMap 在容量达到 MIN_TREEIFY_CAPACITY = 64 时才优先树化;容量不足时优先扩容。树化/退化阈值是实现策略,不是并发安全保证。

  2. LinkedHashMap:双向链表与 LRU 实现机制:
    • 继承 HashMap,其节点 Entry<K,V> 增加 before 和 after 指针构成独立于哈希桶的全局双向链表。
    • accessOrder = true:开启访问顺序。调用 get() 或命中 put() 时,触发 afterNodeAccess 将节点移动至双向链表尾部。
    • 重写 removeEldestEntry(Map.Entry eldest) 方法,在 size() > MAX_ENTRIES 时返回 true,配合 afterNodeInsertion 自动淘汰双链表头部(最久未访问)元素,实现定长 LRU 缓存。
  3. TreeMap 与 ConcurrentSkipListMap:有序检索与并发跳表:
    • TreeMap:基于红黑树实现,依靠节点的左旋、右旋与变色维持平衡,操作复杂度严格 \(O(\log N)\)。非线程安全。
    • ConcurrentSkipListMap:并发有序场景下若使用红黑树,旋转再平衡操作需锁定多个祖先和兄弟节点,锁竞争剧烈。因此采用多层跳表(SkipList),利用 CAS 与 Marker Node(辅助标记删除节点)实现无锁并发插入与删除,支持高并发读写且复杂度稳定为 \(O(\log N)\)。
  4. WeakHashMap 与 IdentityHashMap:内存语义与引用感知:
    • WeakHashMap:其内部 Entry 继承 WeakReference,将 Key 包装为弱引用并关联 ReferenceQueue。当 Key 无强引用被 GC 回收后,JVM 自动将弱引用压入队列。在后续调用 put()/size() 等方法时触发 expungeStaleEntries 懒清理,将失效节点从桶链表移除。避坑:若 Value 强引用了 Key 会导致引用成环使弱引用失效;禁止使用缓存常驻对象(如 Integer.valueOf(1))作为 Key。
    • IdentityHashMap:比较 Key 相等性强制采用引用全等(k1 == k2),哈希计算强制采用 System.identityHashCode(k)。放弃拉链法,采用扁平大数组(偶数存 Key,奇数存 Value)结合开放寻址法(线性探测 Linear Probing)解决冲突。广泛用于 Spring 循环依赖解析与 Jackson/Fastjson 对象图防环递归检测。
2.4.1.2 List 体系物理内存布局与访问开销
  1. ArrayList:连续内存、扩容边界与视图陷阱:
    • 扩容算法:newCapacity = oldCapacity + (oldCapacity >> 1)(1.5 倍)。
    • 底层由 System.arraycopy 本地方法映射操作系统底层 memmove 汇编指令迁移内存。
    • subList() 强绑定视图陷阱:subList 返回的是内部类,仅保存对原数组的索引偏移量和原数组的 modCount。原 List 发生任何结构性修改(add/remove)都会使原 List modCount 自增,后续访问 subList 立即抛出 ConcurrentModificationException。长期持有一小段 subList 还会导致整个原底层大数组无法被 GC 释放,造成隐蔽的内存泄漏。
  2. LinkedList:指针膨胀与 CPU 缓存行击穿:
    • 双向链表实现,node(index) 采用折半二分法减少一半遍历。
    • 性能劣势:每个数据项包装为 Node 对象,64 位开启压缩指针下每个节点占用 24 字节(对象头 12B + 3个引用 12B),内存利用率极低;堆中节点内存离散分布,破坏 CPU 硬件预取(Hardware Prefetching),导致高频 L1/L2 缓存行未命中(Cache Miss),遍历性能远逊于 ArrayList。
  3. CopyOnWriteArrayList:写时复制与弱一致性迭代器:
    • 读操作无锁访问 volatile Object[] array;写操作加独占锁 ReentrantLock 复制 len + 1 大小的新数组完成修改并替换 volatile 引用。
    • 迭代器获取创建瞬间的快照数组引用,迭代期间其他线程写入不影响遍历,迭代器弱一致且不支持修改。
    • 严禁用于高频写场景:频繁深拷贝大数组会导致年轻代被瞬间填满,引发连续 GC 与严重内存尖刺。
2.4.1.3 Queue 与 Deque 体系高效实现
  1. ArrayDeque:基于位运算的高性能循环数组:
    • 底层为可扩容数组;容量管理与回绕实现属于 JDK 具体版本的实现细节。阅读源码时,应以目标 JDK 的 ArrayDeque 实现为准。
    • 在采用位掩码回绕的实现中,可通过位运算计算循环索引;不要将某一版本的内部实现当作 Java API 的永久契约:
      • head = (head - 1) & (elements.length - 1)
      • tail = (tail + 1) & (elements.length - 1)
    • 数组实现避免了每个元素对应的链表节点对象开销;官方 API 文档指出其作为栈通常比 Stack 快、作为队列通常比 LinkedList 快,但实际表现仍受操作分布、扩容、容量和 JDK 实现影响,关键路径应以目标负载基准测试确认。
  2. PriorityQueue:基于完全二叉堆的高效优先级队列:
    • 数组物理存储映射逻辑完全二叉小顶堆(Min-Heap)。
    • 父子节点索引关系:父节点 (i - 1) >>> 1;左子节点 (i << 1) + 1;右子节点 (i << 1) + 2。
    • 核心调整:插入元素执行 siftUp(上浮,与父节点比较交换,时间 \(O(\log N)\));弹出堆顶执行 siftDown(下沉,与较小子节点比较交换,时间 \(O(\log N)\))。

表 64:Java 核心集合容器底层原理与复杂度特性对比表

容器类 接口类型 底层数据结构 查找复杂度 插入/删除复杂度 线程安全性 核心特性与避坑注意
HashMap Map 数组 + 链表 + 红黑树 平均 \(O(1)\),最坏 \(O(\log N)\) 平均 \(O(1)\),最坏 \(O(\log N)\) ❌ 线程不安全 扰动函数降冲突;容量必为 2 的幂;扩容按高低位分流
LinkedHashMap Map HashMap + 全局双向链表 \(O(1)\) \(O(1)\) ❌ 线程不安全 accessOrder=true + 重写 removeEldestEntry 构筑定长 LRU
TreeMap NavigableMap 红黑树(Red-Black Tree) \(O(\log N)\) \(O(\log N)\) ❌ 线程不安全 键严格按自然或 Comparator 排序;并发场景下重平衡锁开销巨大
ConcurrentSkipListMap ConcurrentNavigableMap 多层跳表(SkipList) \(O(\log N)\) \(O(\log N)\) ✅ 线程安全 替代红黑树的并发有序映射,CAS + Marker Node 无锁并发删除
WeakHashMap Map 哈希表 + WeakReference \(O(1)\) \(O(1)\) ❌ 线程不安全 引用队列懒清理;Value 不得直接或间接强引用 Key
IdentityHashMap Map 扁平 Object[] 数组 平均 \(O(1)\) 平均 \(O(1)\) ❌ 线程不安全 比较依赖引用全等 == 与 identityHashCode;线性探测法寻址
ArrayList List 连续 Object[] 数组 \(O(1)\) 随机访问 尾部 \(O(1)\),中间 \(O(N)\) ❌ 线程不安全 1.5 倍扩容;CPU 缓存局部性极高;持有 subList 引发隐式大对象泄漏
LinkedList List / Deque 离散双向链表 Node \(O(N)\) 折半遍历 头尾 \(O(1)\),中间 \(O(N)\) ❌ 线程不安全 压缩指针下节点开销 24B;内存离散破坏 CPU 缓存行预取
CopyOnWriteArrayList List volatile 数组 + 独占写锁 \(O(1)\) 随机访问 \(O(N)\) 数组全拷贝 ✅ 弱一致读 读完全无锁;快照迭代器不抛 CME;严禁写密集场景
ArrayDeque Deque 循环 Object[] 数组 \(O(1)\) 头尾访问 头尾 \(O(1)\) ❌ 线程不安全 容量为 2 的幂,位运算回绕指针;无节点 GC 开销,单线程替代 Stack
PriorityQueue Queue 数组物理小顶堆 \(O(1)\) 查堆顶 \(O(\log N)\) 插入/弹出 ❌ 线程不安全 完全二叉堆;siftUp / siftDown 动态调整;不支持存入 null

2.4.2 泛型、类型擦除与桥接方法

  • 类型擦除原理:Java 泛型是编译期检查,编译后类型参数被擦除为边界类型(无界则擦除为 Object),并自动插入类型强转指令。因此在运行时无法直接 new T()、new T[] 或使用 instanceof List<String>。
  • PECS 原则:Producer Extends, Consumer Super。只读数据源用 ? extends T(协变),只写消费容器用 ? super T(逆变)。
  • 桥接方法(Bridge Method):当子类继承泛型类或重写协变返回类型的方法时,编译器会自动在字节码中生成带有原始签名的合成桥接方法(Synthetic Bridge),在其中调用具体重写方法,确保多态分派正确。
// 泛型原始类型破坏类型安全示例:
List<String> names = new ArrayList<>();
List raw = names; // 编译器警告:原始类型赋值
raw.add(123);     // 编译通过!破坏泛型约束
String name = names.get(0); // 运行时抛出 ClassCastException!

2.4.3 equals、hashCode 与对象契约

  • 契约准则:两对象 equals() 相等,hashCode() 必须相等;反之不要求。重写 equals() 必须重写 hashCode()。
  • 可变 Key 灾难:如果作为 HashMap 的 key 对象,其计算 hashCode 的字段在 put 后被修改,后续 map.get(key) 将因定位到错误的桶而返回 null,引发逻辑数据丢失甚至内存泄漏。
  • BigDecimal 比较陷阱:BigDecimal.equals() 同时比对数值与标度(scale),new BigDecimal("1.0").equals(new BigDecimal("1.00")) 返回 false;纯数值大小比较必须使用 compareTo() == 0。

2.4.4 集合迭代器、并发修改与视图陷阱

  • fail-fast 机制局限:通过 modCount 检查并发修改,一旦发现多线程或迭代器外部 list.remove() 即抛出 ConcurrentModificationException。它绝不能作为并发安全保证,其检查是尽最大努力的;安全单线程移除必须使用 Iterator.remove()。
  • 只读视图 vs 深度不可变:Collections.unmodifiableList() 只是原集合的浅层只读包装,原集合被修改时视图依然同步改变;真正不可变需要防御性拷贝或使用 JDK 9+ List.of()。
  • Arrays.asList() 边界:返回的是内部固定长度适配数组,调用 add()/remove() 会抛出 UnsupportedOperationException。

2.4.5 异常设计与资源管理规范

  • 受检 vs 非受检:受检异常代表业务可预见且可恢复的场景,非受检异常(RuntimeException)代表编程错误或不可恢复的基础设施故障。现代框架普遍采用非受检异常结合明确错误码。
  • 异常链保留:转换异常类型时必须保留原始 cause(new BusinessException("msg", cause)),严禁 catch 后仅记录日志却吞没异常导致调用链上下文断裂。
  • try-with-resources 与 Suppressed Exception:自动关闭实现 AutoCloseable 的资源。若 try 块与 close 方法均抛出异常,try 块异常为主异常抛出,close 产生的异常被追加到 e.getSuppressed() 中,彻底消除传统 finally 中异常覆盖的问题。

2.4.6 时间、时区与高精度金额计算

  • 时间规范:严禁混用旧版 java.util.Date 与 Calendar。后端存储及接口传输必须统一使用 Instant(标准 UTC 时间戳)或带明确时区偏移的 OffsetDateTime;前端展示再由业务按时区渲染。
  • 金额精确计算:严禁直接使用 double/float 运算。金额运算必须使用 BigDecimal 且必须使用字符串构造方法(new BigDecimal("19.99"))。乘除运算必须明确指定小数精度与舍入模式(如 RoundingMode.HALF_UP),舍入规则必须由业务契约清晰定义。
// 金额标准运算:明确指定精度与舍入模式
BigDecimal amount = new BigDecimal("19.90");
BigDecimal taxRate = new BigDecimal("0.13");
BigDecimal tax = amount.multiply(taxRate).setScale(2, RoundingMode.HALF_UP);

2.4.7 序列化与跨系统对象兼容性治理

  • Java 原生序列化禁令:Java 原生序列化开销大且存在严重的反序列化 RCE 漏洞风险,跨服务及缓存禁止使用。跨系统交互首选 JSON(Jackson)、Protobuf 或 Avro。
  • 兼容性演进原则:字段只增不减;新增字段必须设置默认值;禁止重命名已有字段;生产者与消费者必须配置忽略未知字段(FAIL_ON_UNKNOWN_PROPERTIES=false)。

2.4.8 Java 基础语义、数值、编码与时间陷阱

对照两份知识图谱后,补齐容易在“会用框架”阶段被忽略、但基础面试常追问的语言语义与标准库边界。已有集合、泛型、equals/hashCode、时间与序列化专题仍保留,本节只整理交叉核对后需要集中对比的基础点。

表 80:Java 基础语义与标准库常见陷阱

知识点核心结论回答时应覆盖的边界
值传递与对象引用Java 参数始终按值传递;对象参数传入的是“引用值的副本”。方法内修改对象可被外部观察,但把形参重新指向另一个对象不会改变调用方变量。用一个“修改字段”和一个“重新赋值形参”的小例子区分,避免笼统说 Java 有引用传递。
重载、重写与多态重载主要在编译期按静态类型和参数签名选择;实例方法重写的具体实现通常在运行期动态分派。静态方法隐藏而非实例多态重写;构造器不继承。结合协变返回、访问权限、异常声明和 @Override 解释边界;不要把重载与重写混为一谈。
final / finally / finalizefinal 用于变量、方法或类的约束;finally 用于清理控制流(仍需理解进程终止等极端边界);finalize() 是不可靠的旧式终结机制,已弃用并计划移除。资源管理优先用 try-with-resources 与 AutoCloseable,不依赖 finalize 释放连接、文件或锁。
浮点数与金额二进制浮点数无法精确表示许多十进制小数,因此 0.1 + 0.2 通常不严格等于 0.3。金额运算明确精度、舍入模式与币种。构造 BigDecimal 优先使用字符串或明确的整数最小货币单位;数值比较通常用 compareTo,equals 还比较 scale。
String 与可变字符串String 不可变;StringBuilder 适合单线程拼接,StringBuffer 的方法带同步语义。字符串常量池与 intern() 会影响驻留行为。不要把 intern 当通用缓存;循环拼接先考虑复杂度、分配和编译器优化,再用基准测试确认。
字符集与编码Unicode 是字符编码标准,UTF-8/UTF-16 是编码形式;GBK/GB18030 是中文环境中常见的兼容编码。URL percent-encoding、HTML escaping 和 JSON escaping 解决不同问题。文件、HTTP、数据库连接显式统一字符集;排查乱码时分清字节、字符和显示字体,避免重复或漏做编码。
日期与时区SimpleDateFormat 非线程安全;DateTimeFormatter 可共享使用。yyyy 是日历年,YYYY 是周基年,年末年初可能出现差异。存储与传输明确时间语义:Instant/UTC 时间点、ZoneId 地区规则、本地日期时间;考虑 DST 跳时/重叠与历史时区规则。详细见 2.4.6 时间与金额。
接口、抽象类与组合接口表达可实现的契约,抽象类可共享状态和受保护实现;组合通常比深层继承更易演进。平台无关性依赖字节码、虚拟机与标准库契约,不等于所有环境行为完全相同。结合 SOLID、接口隔离、依赖倒置和测试替身说明设计理由,不要把“面向对象三大特征”停留在背定义。
位运算与整数边界熟悉 &, |, ^, ~, <<, >>, >>>;Java int/long 是固定宽度补码运算,移位距离会按类型宽度截取。哈希扰动、位掩码和状态压缩需明确 signed/unsigned 右移、溢出和负数边界;不宜为了炫技替代可读代码。
对象契约与集合键equals/hashCode 的一致性与可变键问题决定 HashMap/HashSet 行为;这部分已有独立专题。与 2.4.3 equals/hashCode 联动复习,重点讲清可变字段参与哈希后为何无法按原位置查找。

2.4.9 反射、注解、内部类、对象复制与序列化补充

上传 PDF 的“Java 基础”部分还专门列出反射、注解、内部类、对象复制和 Java 序列化。这些内容在现有语言语义专题中有交集,但值得形成一张独立的面试速查表;以下按现代 JDK 的封装与安全边界重新整理。

表 92:反射、注解、内部类、复制与序列化的核心边界

主题核心知识点面试追问与工程边界
反射与 Class`Class` 可由 `对象.getClass()`、`类型.class` 或 `Class.forName(...)` 获取;可检查构造器、方法、字段、注解并进行动态调用。`Class.forName(name)` 默认会初始化目标类;需要只加载不初始化时使用带 `initialize=false` 与指定 `ClassLoader` 的重载。模块封装可能限制深反射;反射不应成为绕过类型安全与权限校验的默认方案。
注解与元注解`@Target`、`@Retention`、`@Documented`、`@Inherited`;运行时反射、编译期注解处理器、重复注解与类型注解。`@Inherited` 只影响类层级上的注解继承,不等价于接口或方法注解自动继承;编译期代码生成和运行时扫描是不同机制。
内部类与匿名类静态嵌套类不持有外部实例;非静态成员内部类通常隐含外部对象引用;局部类/匿名类可捕获符合规则的局部变量。长生命周期任务、监听器、缓存若保留非静态内部类实例,可能连带保活外部对象;必要时改为静态嵌套类并显式传递依赖。
对象复制赋值复制的是引用值;浅拷贝复制顶层对象但共享内部引用;深拷贝递归复制可变对象图。`clone()` 的契约与实现复杂,`Cloneable` 本身不提供一个通用深拷贝实现;优先考虑复制构造器、静态工厂、显式 mapper 或不可变对象。
Java 原生序列化`Serializable`、`serialVersionUID`、`transient`、`writeObject/readObject` 与继承层级的序列化行为。静态字段属于类状态,不随普通实例字段序列化;类演进需评估兼容性。严禁对不可信字节流直接执行原生反序列化,优先使用受控 DTO/明确 schema 的协议格式。

2.4.10 SPI / ServiceLoader、字符串常量池与类初始化顺序(表 110)

JavaGuide 的基础题目录明确涵盖 SPI、序列化、反射与 String;现有报告已覆盖反射、注解和序列化,但没有把 SPI 与字符串常量池作为独立面试专题。本节补足这几个常见追问,并强调实现细节应结合目标 JDK 验证。

主题核心理解常见追问与边界
API vs SPIAPI 通常由能力提供方定义并供调用方使用;SPI 通常由调用框架定义扩展契约,由第三方提供实现,框架负责发现和加载。SPI 体现控制反转与可插拔扩展;不要把“接口”本身就等同于 SPI。
ServiceLoader传统 classpath 场景通过 META-INF/services/接口全限定名 声明实现;模块化场景可用 provides ... with ... 与 uses 声明。关注延迟发现/实例化、类加载器可见性、提供者构造失败与实现选择;单个 ServiceLoader 实例不要假定为线程安全。
String 不可变性不可变性来自封装、没有暴露修改内部内容的操作,以及类本身不可被继承等设计共同作用,而不是仅因内部引用被 final 修饰。JDK 9 起 String 的底层存储从 char[] 改为紧凑字符串的 byte[]/coder 表达;这是实现细节,不应把其字段布局当成 Java 语言规范承诺。
字符串常量池与 intern()字符串字面量和编译期常量可能被复用;new String(...) 显式创建对象。intern() 返回池中对应内容的规范引用。“创建几个对象”必须说明常量池是否已有该字符串、编译器优化与运行时语境;不要对不受控海量动态字符串盲目 intern。
类初始化顺序类初始化通常先处理父类,再按源码文本顺序执行静态字段初始化与静态初始化块;对象创建时先设置默认值,随后沿父类到子类的构造链执行,各类的实例字段初始化器和实例初始化块按声明顺序在该类构造器体之前执行。编译期常量的读取不一定触发声明类初始化;区分类加载、链接、初始化,注意主动使用触发规则、构造器中可见的默认值,以及父子类初始化顺序带来的风险。

面试回答建议:先讲规范层面的结论,再用一个最小代码片段验证目标 JDK 的结果;若问题问“JVM 一定如何实现”,应区分规范约束和 HotSpot 当前实现。


2.5 字节码增强与 Java Agent 栈

维度 内容
两种加载方式 premain(-javaagent 启动期挂载)、agentmain(Attach API 运行时动态挂载,如 Arthas)
核心机制 Instrumentation 接口配合 ClassFileTransformer;已加载类需调用 retransformClasses
类库选型 ASM(底层指令级、性能极致)、Javassist(源码编译级)、ByteBuddy(类型安全、生产首选高阶 DSL);JDK 24+ 还可评估标准 java.lang.classfile Class-File API,用于 class 文件解析、生成和转换,减少工具对 JDK 内部 API 及第三方 ASM 版本的耦合。现有 ASM/Byte Buddy 仍需按功能、目标 JDK 和生态兼容性评估,不能一键替换。
生产限制 动态增强会影响 JIT 方法内联,且增加方法栈深度;严禁线上全量扫描增强,必须精确白名单拦截

2.6 设计模式速查

表 50:经典设计模式在 Spring/Java 框架中的映射

模式 分类 典型应用与映射 面试追问落点
单例(Singleton) 创建型 Spring 默认 Bean 作用域、枚举单例 双重检查锁定(DCL)中 volatile 禁重排必要性
工厂方法(Factory) 创建型 BeanFactory、FactoryBean、JDBC Connection 复杂 Bean 实例化生命周期与依赖注入解耦
代理(Proxy) 结构型 JDK 动态代理(基于接口 InvocationHandler)、CGLIB(子类字节码) Spring AOP 事务自调用失效根因
责任链(Chain of Resp.) 行为型 Servlet Filter、Spring MVC HandlerInterceptor、Sentinel SlotChain 调用链的前置与后置拦截机制
策略(Strategy) 行为型 Spring 资源加载器 ResourceLoader、线程池拒绝策略 RejectedExecutionHandler 消除庞大 if-else,运行时根据条件动态路由算法
模板方法(Template) 行为型 JdbcTemplate、TransactionTemplate、AQS 的 tryAcquire 骨架 算法骨架固定在父类,具体扩展点延迟至子类或回调实现

2.6.1 GoF 设计模式全量速查与 SOLID 原则

《Java 工程师成神之路》对设计原则、创建型/结构型/行为型模式、单例实现与 Spring 中的模式应用有系统分类。本表补齐原速查表未逐组列出的模式目录;复习重点是识别问题与权衡,不要求每个模式都在项目中强行套用。

表 82:GoF 23 种设计模式与 SOLID 原则

分类模式/原则解决的问题面试落点
创建型(5)单例、工厂方法、抽象工厂、建造者、原型对象创建复杂、希望隔离具体实现或控制实例生命周期。枚举单例、静态内部类、带 volatile 的双重检查锁;配置复杂对象用 Builder;工厂方法延迟具体类型选择。
结构型(7)适配器、桥接、组合、装饰器、外观、享元、代理处理接口不兼容、抽象与实现分离、树形结构、动态增强、简化子系统或共享不可变数据。Spring AOP/事务代理、Servlet Filter、装饰器包装流、适配第三方 SDK;代理与装饰器关注点不同。
行为型(11)责任链、命令、解释器、迭代器、中介者、备忘录、观察者、状态、策略、模板方法、访问者处理行为变化、算法替换、事件传播、请求排队/撤销和复杂流程扩展。策略替代条件分支、责任链做校验/过滤、模板方法固定流程骨架、观察者用于事件解耦;要控制隐式调用链的可观测性。
SOLID 与组合原则单一职责、开放封闭、里氏替换、接口隔离、依赖倒置;组合优于继承、面向接口编程。原则不是“每个类只做一件事”的机械规则,而是控制变更传播、替换成本与依赖方向。用真实变化点解释抽象层:为什么抽象、由谁拥有接口、错误的抽象会引入什么间接层与维护成本。
Spring 中的模式工厂(BeanFactory)、代理(AOP/事务)、模板(JdbcTemplate)、策略(资源加载/执行器)、责任链(过滤器链)、观察者(事件机制)。框架通常组合多个模式,模式名称不是实现机制的全部解释。说明模式如何通过接口/回调/代理完成扩展,以及它带来的生命周期、调试、异常传播或性能成本。

3. 框架与中间件栈

3.1 Spring 全家桶栈

阅读顺序:3.1.1–3.1.5 是循环依赖、扩展点、事务失效、异步/定时代理、配置与就绪诊断的专题深挖;3.1.6–3.1.14 是系统化知识地图、生态矩阵与场景自检。两部分有意采用“高频问题深挖 + 全景覆盖”的双层结构;复习时把前者当作机制案例,后者用于查漏,不必重复背诵同一结论。

表 7:Spring 栈复习条目

技术项 需掌握到的深度
IoC 容器 Bean 生命周期全流程;循环依赖三级缓存;BFPP / BPP 扩展点与执行链
AOP 机制 JDK 动态代理与 CGLIB 选择策略;AOP 代理在 BPP after-init 阶段创建;事务自调用失效根因
长事务治理 事务与连接池耗尽、远程调用拖垮数据库连接的排查与 TransactionTemplate 编程式收敛
配置治理 启动配置优先级覆盖、就绪探针(Readiness)与存活探针(Liveness)的严格分离
版本演进 Spring Framework 7.0.x / 6.2.x 与 Spring Boot 4.1.x / 4.0.x / 3.5.x 的稳定线并存;截至 2026-10-27,官方参考页列出 Framework 7.0.10/6.2.19、Boot 4.1.2/4.0.9/3.5.16。升级前以官方兼容矩阵、JDK 基线与项目 BOM 为准。

面试覆盖边界:本节把 Spring Core、Boot、MVC、AOP/事务、安全、数据访问、缓存、任务调度、测试与主流生态项目纳入同一地图;不代表每个岗位都要求全部背到源码级,优先按 P0/P1 和目标 JD 选择深度。

3.1.1 三级缓存:为什么二级不够

三级缓存存的是 ObjectFactory(lambda),只有在“确实发生循环依赖且允许提前引用”时才调用 getObject(),由 getEarlyBeanReference 决定是否在此刻创建 AOP 代理。本质是把代理对象的创建时机推迟到确定真的有人提前引用它的那一刻。如果直接放二级缓存,在有 AOP 的场景下其他 Bean 拿到的会是原始对象而不是代理对象。

3.1.2 BFPP 与 BPP:Spring 真正的扩展点

表 40:BFPP 与 BPP 对比

维度 BeanFactoryPostProcessor (BFPP) BeanPostProcessor (BPP)
操作对象 BeanDefinition(Bean 元数据定义) Bean 实例(内存真实对象)
执行时机 所有普通 Bean 实例化之前,仅执行一次 每个 Bean 创建时执行两次(init 前 + init 后)
能否替换 Bean 不能 能——postProcessAfterInitialization 返回代理对象是合法的
典型应用 PropertySourcesPlaceholderConfigurer、ConfigurationClassPostProcessor AutowiredAnnotationBeanPostProcessor、AbstractAutoProxyCreator(AOP 代理生成)
核心区别 修改配置定义,不能实例化业务 Bean 修改或包装对象实例;AOP 动态代理就是在 BPP 的 postProcessAfterInitialization 阶段创建

3.1.3 事务失效根因与长事务治理

  • 代理失效五大根因:自调用(绕过代理对象)、非 public 方法、异常被内部 catch 吞掉、受检异常未指定 rollbackFor=Exception.class、多线程环境下分属于不同 Connection 连接。
  • 长事务危害与治理:长事务会持续占用数据库连接;事务已获取的行锁等资源可能一直持有到提交/回滚,从而耗尽 HikariCP 连接池并放大锁等待。通常应避免在持有数据库事务的同时调用慢 RPC/HTTP 或执行耗时计算;可先完成外部校验,再开短事务完成 DB 更新。若业务要求跨系统协作,评估 Outbox、Saga、状态机和补偿机制,而不是简单地把事务边界机械收缩到单条 SQL。

3.1.4 @Async 与 @Scheduled 的代理陷阱

注解 失效/陷阱 机制与修复
@Async 自调用绕过代理 与 @Transactional 同源;必须通过代理对象调用
@Async 实际执行器取决于异步支持配置与容器中的 Executor 候选;需检查目标 Spring/Spring Boot 版本与 Bean 解析 纯 Spring 未配置执行器时可能回退到 SimpleAsyncTaskExecutor(不复用线程);Spring Boot 自动配置会影响实际执行器。生产应显式配置有界执行器、队列容量、拒绝策略、优雅停机与告警(可通过 AsyncConfigurer 或具名 Executor Bean 等方式接入)。
@Async ThreadLocal/MDC 不自动传递 导致链路 TraceId 丢失;需通过 TaskDecorator 或 TransmittableThreadLocal 传播上下文,并防止请求间上下文泄漏。
@Scheduled 默认单线程调度 一个任务卡死会导致全局定时任务阻塞;必须配置 TaskScheduler 线程池
@Scheduled 分布式环境下重复执行 多实例同时触发;需引入 ShedLock 或分布式调度平台(XXL-Job)

3.1.5 配置治理与应用启动就绪诊断

  • 配置覆盖优先级:命令行参数 > Java 系统属性(-D) > 环境变量 > application-{profile}.yml > 内部 application.yml。生产凭据禁止明文硬编码于 Git 仓库,必须通过 Vault/K8s Secret 或配置中心动态下发。
  • 启动诊断与探针分离:
    • Liveness Probe(存活探针):检测容器死锁或严重崩溃,失败后重启 Pod。
    • Readiness Probe(就绪探针):检测应用内部连接池、下游依赖是否准备就绪,未就绪时仅摘除流量,绝不随意重启 Pod。
    • Startup Probe(启动探针):保护慢启动 Java 应用避免在初始化期间被存活探针误杀。

3.1.6 IoC 容器、Bean 生命周期与依赖解析全景

面试不能只背“控制反转、依赖注入”。要能从 BeanDefinition 注册、实例化、依赖填充、Aware 回调、初始化前后处理、初始化方法、代理暴露到销毁阶段,讲清对象由谁创建、何时可被其他 Bean 引用、哪些扩展点能改变定义或包装实例。

表 71:Spring IoC 容器与 Bean 生命周期面试对照

主题必须能回答常见追问 / 易错点
容器与定义BeanFactory 与 ApplicationContext 的职责;BeanDefinition、别名、父子定义、FactoryBeanFactoryBean.getObject() 产出的对象与 FactoryBean 本身如何区分(& 前缀);延迟初始化何时执行
依赖解析按类型、名称、@Qualifier、@Primary、泛型候选与集合注入的优先级思路同类型多个候选为什么启动失败;@Resource 与 @Autowired 的解析策略不能简单视为完全相同
生命周期构造/实例化、属性填充、Aware、BeanPostProcessor、初始化回调、销毁回调@PostConstruct、InitializingBean、自定义 init-method 的执行关系与版本注意项
作用域singleton、prototype、request、session、application、websocket 等适用边界prototype 注入 singleton 通常只解析一次;需延迟取新对象时使用 Provider/ObjectProvider、查找方法或受控代理
循环依赖单例 setter/字段注入与构造器循环依赖的差异;提前暴露与三级缓存的作用循环依赖并非所有对象图都能解;AOP 代理提前暴露一致性、Boot 禁止/限制循环依赖的配置与设计取舍
配置类@Configuration、@Bean、@Import、组件扫描、条件注册proxyBeanMethods=true/false 对 @Bean 方法相互调用的影响;Lite 模式下不能假定每次调用都返回容器单例
扩展点BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor、BeanPostProcessor、SmartInitializingSingleton、ApplicationListener修改 BeanDefinition 与包装 Bean 实例是两类工作;过早获取 Bean 可能使其错过部分后处理器
Spring Boot启动过程、Starter 与自动配置条件、AutoConfiguration.imports、配置绑定与覆盖、Actuator、优雅停机、AOT/Native Image 边界
Web MVC 与 RESTDispatcherServlet 请求链、参数解析与校验、消息转换器、Filter/Interceptor/AOP 边界、统一异常与响应
安全与身份Spring Security 过滤器链、Authentication/Authorization、方法级权限、Session/JWT、OAuth2/OIDC、CSRF/CORS
数据与工程化Spring JDBC/ORM、事务管理器与传播行为、Spring Cache、事件、Batch/Integration、TestContext、Testcontainers
生态与兼容Spring Cloud、Spring Cloud Alibaba、Spring Kafka/AMQP/Pulsar、Spring Cloud Stream、Spring Modulith/AI;按官方兼容矩阵和 BOM 对齐版本
  • 面试答题主线:先说容器中元数据何时注册,再说对象何时实例化和注入,最后解释后处理器、代理、生命周期回调及销毁。
  • 源码入口:AbstractApplicationContext.refresh()、DefaultListableBeanFactory、AbstractAutowireCapableBeanFactory、DefaultSingletonBeanRegistry;应结合目标 Spring 版本读源码,不要把某个版本的内部调用顺序当成永恒 API 契约。

3.1.7 AOP、代理机制与切面执行链

表 72:Spring AOP 代理机制与切面执行链对照

知识点核心内容高频陷阱
代理选择JDK 动态代理、CGLIB 子类代理;容器配置、接口和具体类形态会影响选择不要仅凭“有接口就一定用 JDK”推断所有应用;检查实际 Spring 配置与代理对象
执行链Advisor、Pointcut、Advice;前置、后置、返回、异常、环绕通知及多个切面的排序环绕通知的 proceed()、异常传播、返回值与顺序会影响事务、安全、缓存等切面
代理边界通常通过代理调用才触发代理式 AOP;代理对象和 target 是不同角色同类自调用绕过代理;构造器/初始化阶段的调用、private/final 方法及代理限制需按代理类型分析
代理与事务事务、缓存、方法安全、异步等都可能依赖代理基础设施不要把所有失效都归因于“注解没生效”;先确认 Bean 是否为代理、调用路径、切面顺序、异常与配置
代理与 AspectJSpring AOP 主要是代理模型;AspectJ 可在编译期/加载期织入,能力范围和部署复杂度不同不能用 Spring AOP 的代理语义解释所有 AspectJ 织入行为
  • 能解释为什么事务、缓存、权限、异步注解经常共享代理失效模式,以及如何通过重构服务边界、独立 Bean 或显式编程式 API 修复。
  • 源码阅读建议关注自动代理创建器、Advisor 匹配、代理创建时机和拦截器链;以当前 Spring 官方文档为基准,避免记忆早期版本的实现细节。

3.1.8 Spring 声明式事务:传播、隔离与真实边界

表 73:Spring 事务传播行为与真实边界对照

传播行为典型含义面试要点
REQUIRED有现有事务则加入,没有则新建默认值;内层异常标记 rollback-only 后,外层即使捕获异常也可能在提交时报 UnexpectedRollbackException
REQUIRES_NEW挂起外层事务,使用独立事务会额外占用连接;连接池容量、锁顺序和外层持锁都要考虑,可能形成连接池耗尽
NESTED在支持的事务管理器/资源中使用保存点形成嵌套回滚边界不是任意数据库、任意 JPA/事务管理器都支持;不等价于独立提交的 REQUIRES_NEW
SUPPORTS / NOT_SUPPORTED有事务时参与或挂起事务后非事务执行需清楚调用方事务对当前方法的影响以及资源是否仍被占用
MANDATORY / NEVER强制要求已有事务 / 要求不能存在事务适用于明确声明事务前置条件的内部服务边界
  • 回滚规则:默认情况下,运行时异常和 Error 通常触发回滚;受检异常需结合 rollbackFor 等规则,不应死记为“所有异常都会回滚”。确认当前 Spring 版本的默认回滚规则及项目自定义配置。
  • 隔离与传播不是一回事:传播定义如何加入/创建事务,隔离级别定义并发事务的数据可见性;实际效果还取决于数据库、驱动和事务管理器。
  • 线程边界:传统 JDBC 事务上下文通常绑定当前线程;切换线程、@Async、虚拟线程任务交接不意味着自动继承同一事务。响应式事务则使用 Reactor Context 等不同机制。
  • 长事务:避免持有数据库事务执行慢 RPC、消息等待或大规模计算;跨服务一致性优先评估 Outbox、Saga、幂等与补偿,而不是把本地事务误当全局事务。
  • 事务管理器:理解 PlatformTransactionManager、TransactionTemplate、JDBC/JPA/R2DBC 管理器的资源边界;多数据源场景需明确事务管理器绑定,跨库原子提交另做方案设计。

3.1.9 Spring Boot:自动配置、配置绑定与启动过程

  • 启动主流程:SpringApplication.run()、环境准备、配置数据加载、ApplicationContext 创建、Bean 定义注册、自动配置条件评估、上下文刷新、Runner 执行和就绪事件。能说清 ApplicationRunner/CommandLineRunner 与应用真正接流量前后的边界。
  • 自动配置原理:@SpringBootApplication 的组合含义;自动配置类、条件注解和 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(适用于相关现代版本);@ConditionalOnClass、@ConditionalOnMissingBean、@ConditionalOnProperty、排除项与 Condition Evaluation Report。
  • Starter 与依赖治理:starter 负责聚合常用依赖,自动配置负责按条件注册 Bean;理解 BOM/依赖管理、版本对齐、传递依赖冲突、排除规则和 Boot/Framework/Cloud 兼容矩阵。不要无验证地强行覆盖 Spring 管理的底层依赖版本。
  • 配置绑定:@ConfigurationProperties 适合类型安全、分组、校验的配置;@Value 适合少量简单注入。掌握 profile、多文档配置、环境变量命名、外部文件覆盖、命令行覆盖、配置刷新机制及其组件边界。
  • 生产能力:Actuator health/info/metrics/prometheus、启动与就绪探针、优雅停机、线程池和连接池指标、敏感端点保护、HTTP 暴露范围及自定义健康指标。暴露 Actuator 不等于自动完成安全配置。
  • 原生镜像 / AOT:理解 AOT 生成阶段、反射/动态代理/资源提示、可达性元数据与 Native Image 的启动/内存收益及动态特性限制;把它作为选型专题,不要与普通 JVM 启动混为一谈。

3.1.10 Spring MVC 请求链、参数绑定与异常处理

高频请求链可按“Servlet 容器 → Filter → DispatcherServlet → HandlerMapping → HandlerAdapter → 参数解析/数据绑定/校验 → Controller → 返回值处理/HttpMessageConverter → 异常解析器 → 响应”讲述。具体实现以使用的 Spring MVC 版本和配置为准。

表 74:Spring MVC 请求链与参数处理对照

主题核心知识场景题
Filter / Interceptor / AOP容器级过滤、Handler 执行前后拦截、方法代理增强的覆盖范围与执行顺序认证、TraceId、跨域、请求签名、审计分别适合放哪里;异常和异步请求时的执行边界
参数解析与绑定@RequestParam、@PathVariable、@RequestBody、Converter、Formatter、消息转换器Content-Type、JSON 反序列化、日期格式、参数缺失与类型错误如何返回一致错误码
校验Jakarta Bean Validation、分组校验、嵌套校验、自定义约束区分格式校验、领域不变量、数据库约束与权限检查;不把业务校验全塞到 Controller
异常与响应@ControllerAdvice、异常解析器、统一响应体、Problem Details(按版本与规范使用)避免吞异常/泄漏堆栈;区分业务拒绝、客户端错误、可重试故障和系统故障
HTTP 边界内容协商、文件上传/下载、消息体大小限制、CORS、请求超时与异步处理大文件流式响应、重复提交、客户端取消和反向代理超时的联动治理

3.1.11 Spring Security:认证、授权与安全过滤器链

  • 请求安全链:SecurityFilterChain、安全过滤器顺序、SecurityContext、Authentication、AuthenticationManager/Provider、UserDetailsService、PasswordEncoder,以及认证成功/失败处理。
  • 认证与授权的区别:认证回答“你是谁”,授权回答“你能做什么”;掌握请求级授权、方法级安全(例如 @PreAuthorize)、角色/权限表达式、对象级授权与多租户隔离。
  • Session / JWT:无状态不等于无需撤销策略;讨论 Token 过期、刷新、密钥轮换、撤销/黑名单、受众与签发方校验、时钟偏差、密钥泄露与日志脱敏。JWT 不是加密的同义词。
  • OAuth 2.0 / OpenID Connect:区分授权与身份认证,理解 Authorization Code + PKCE、Resource Server、Client、Issuer、Scope、ID Token 与 Access Token。不要在新系统中照搬已不适合公有客户端的旧流程。
  • CSRF / CORS / 安全头:CSRF 主要取决于浏览器是否自动携带凭据;CORS 是浏览器跨域策略,不是后端授权。按 Cookie、Bearer Token、跨域凭据和前后端部署方式分别选型。
  • 面试故障:自定义 Filter 顺序错误、SecurityContext 在异步线程丢失、OPTIONS 预检失败、方法权限绕过、JWT 算法/密钥错误、开放重定向与登录回调校验缺失。

3.1.12 数据访问、缓存、事件、任务调度与测试

表 75:Spring 数据访问、缓存与测试边界对照

模块核心面试范围失效/边界
Spring JDBC / ORMJdbcTemplate、Spring Data、JPA/Hibernate、MyBatis 整合;Repository/DAO、异常转换、事务资源绑定理解 Spring 事务只协调当前事务管理器管理的资源;不要默认不同数据源会自动原子提交
Spring Cache@Cacheable、@CachePut、@CacheEvict、Key/CacheResolver、TTL 与缓存实现代理自调用、缓存键碰撞、空值、并发击穿、缓存与数据库一致性、批量失效范围
事件ApplicationEvent / @EventListener、事务事件监听进程内事件不是可靠消息队列;需要“提交后再发”或跨进程可靠性时使用事务事件的正确阶段、Outbox 或 MQ
异步与定时@Async、@Scheduled、TaskExecutor、TaskScheduler、错误处理有界线程池、拒绝策略、上下文传播、关机时的在途任务、集群重复调度与幂等
Spring Batch / Integration批处理 Job/Step、重启与断点、分块事务;Integration 的 MessageChannel、Endpoint、Adapter、Flow批处理需处理重跑、幂等和检查点;Integration 是集成编排框架,不是 MQ Broker
测试JUnit 5、Mockito、TestContext、Spring MVC Test、WebTestClient、Testcontainers、切片测试区分单元、切片、集成、契约与端到端测试;避免过度使用全量 @SpringBootTest 造成慢且脆弱的测试

3.1.13 Spring 生态框架矩阵与版本兼容

“Spring 全家桶”不是单一框架。面试中要能说清核心框架、Boot 装配层、Cloud 分布式组件、数据集成模块和外围项目的职责。以下列的是资深 Java 岗位常见候选,而不是每个岗位都要求全部掌握。

表 76:Spring 生态框架与能力分层矩阵

类别常见项目/组件掌握要求
核心 WebSpring Framework、Spring MVC、Spring WebFlux、WebClient生命周期、请求链、代理、阻塞/非阻塞模型、超时与线程模型
应用装配Spring Boot、Starter、Auto-configuration、Actuator、AOT启动过程、条件装配、配置绑定、可观测性、优雅停机、依赖对齐
安全与会话Spring Security、Spring Authorization Server、Spring Session、Spring LDAP认证/授权、OAuth2/OIDC、Session 外置、LDAP/企业身份集成(按岗位)
数据与 APISpring Data JPA/JDBC/Redis/MongoDB/Elasticsearch、Spring for GraphQL选择适当抽象;理解底层事务、连接池、查询模型和一致性,而不是只记 Repository API
分布式Spring Cloud Gateway、OpenFeign、LoadBalancer、CircuitBreaker、Config;Spring Cloud Alibaba(Nacos/Sentinel/Seata)服务发现、配置、流量入口、超时重试、熔断隔离、版本兼容矩阵
消息与集成Spring for Apache Kafka、Spring AMQP、Spring for Apache Pulsar、Spring Cloud Stream、Spring Integration、JMS客户端封装与 Broker 语义的边界;消费确认、重试、事务与 Binder 抽象
任务与模块化Spring Batch、Spring Modulith、Spring Shell、Spring Vault批处理、模块边界/事件、运维工具或密钥集成;按目标岗位决定深度
AI 与新领域Spring AI、Spring GraphQL 等企业 AI 岗位关注 ChatClient/Advisor/Tool/RAG;普通后端面试不应替代 JVM/事务等 P0 重点
  • 版本策略:以官方兼容矩阵和依赖 BOM 对齐 Spring Boot、Spring Framework、Spring Cloud release train、Spring Kafka/AMQP 等版本;先确认 JDK 基线、Jakarta 命名空间和第三方 starter 的适配范围,再升级。不要把“最新版本”自动等同于现有生产系统的最佳版本。
  • 重点迁移项:Spring 5 → 6 / Boot 2 → 3 涉及 Java 基线、javax → jakarta、部分 API 与依赖变化;Spring 6 → 7 / Boot 3 → 4 则需继续检查 JDK 基线、依赖模块拆分、自动配置和第三方集成兼容性。以目标小版本迁移指南为准。

官方版本快照(核验截至 2026-10-27,供复习时识别版本边界,不是升级推荐):Spring Boot 稳定线包含 4.1.2,要求 Java 17 起并声明兼容到 Java 27;对应 Spring Framework 7.0.10。Spring Cloud 2025.1.x(Oakwood)对应 Boot 4.0.x,且从 2025.1.2 起支持 Boot 4.1.x;Spring for Apache Kafka 4.1.2 与 Boot 4.1.x 对应,Spring AMQP 4.1.2。Boot 系统要求、Spring Cloud 兼容矩阵、Spring Kafka 版本矩阵、Spring AMQP 当前版本。特别提醒:Boot、Framework、Cloud train、各集成项目和第三方 Starter 必须按官方兼容矩阵/BOM 联动,不能只把某个依赖升到最新号。

3.1.14 Spring 高频场景题自检

  • 为什么循环依赖有时可解决、有时失败?构造器循环依赖和 AOP 代理提前暴露有何区别?
  • 为什么 @Transactional 在自调用、非代理调用、异常被吞、多线程和多数据源情况下会失效或产生不同结果?
  • 一个 Bean 为什么没有按预期自动配置?如何用条件评估报告、Bean 列表、依赖树定位?
  • Filter、HandlerInterceptor、AOP 的边界与顺序如何影响认证、链路追踪和异常处理?
  • JWT 登录后接口仍返回 401/403,如何区分认证失败与授权失败,并沿过滤器链排查?
  • Spring Cache 与 MQ 事件如何避免双写不一致?如何定义失败重试和补偿?
  • 服务启动慢、Readiness 一直失败、优雅停机丢请求,应从哪些日志、指标和生命周期点定位?
  • 如何把一个启动慢、堆内存增长、线程池耗尽的 Spring Boot 服务拆成可复现的证据链,而不是盲目增加机器?


3.1.15 Servlet 容器、Tomcat 线程模型与生命周期

两份资料都将 Servlet 容器、Tomcat/Jetty/WebLogic 等传统 Web 基础纳入 Java 工程师知识图谱。资深岗位不一定要求容器源码级掌握,但应能说明请求如何进入应用、线程与连接如何受限,以及故障如何从容器层定位。

表 83:Servlet 容器与 Web 请求处理边界

主题核心知识点生产排查与面试追问
Servlet 生命周期容器加载类、实例化、init 一次、并发处理多个请求、destroy 释放资源。典型 Servlet 实例通常会被多线程并发调用;不要把请求状态放在可变实例字段中。
Filter / Interceptor / ListenerFilter 属于 Servlet 过滤链,可处理请求/响应;Spring MVC Interceptor 围绕 Handler 执行;Listener 监听 ServletContext、Session 等生命周期事件。执行顺序、注册位置和可见范围不同;异常处理、安全鉴权和跨切面逻辑要选对层次。
Tomcat 连接器与线程模型Connector 负责接入协议与连接管理,ProtocolHandler/Endpoint 负责底层网络处理,容器流水线执行请求;NIO/NIO2/APR 可用性随版本与配置变化。区分 accept 队列、最大连接、工作线程与业务线程池;队列太大可能延迟暴露过载而不是提高吞吐。
maxThreads / maxConnections / acceptCount线程数限制并发处理能力;最大连接数限制可被服务端管理的连接;acceptCount 是连接/任务排队边界之一,具体行为与 Connector 实现及版本有关。用压测与 JMX/指标验证;不要把三个参数当成同一个“并发数”,HTTP keep-alive 与异步请求也会改变关系。
容器与生命周期治理优雅停机需停止接收新流量、等待在途请求、结束后台任务并关闭资源;容器终止宽限时间过短会使优雅停机失效。结合 readiness 摘流、线程池关闭、消息消费者暂停与超时预算;Tomcat、Jetty、Undertow 的选择按连接模型、团队经验和功能需求决定。
诊断与管理JMX 可暴露线程、连接器、会话和资源池管理指标;线程转储用于排查阻塞、死锁与线程池饥饿。把容器指标与应用 P99、连接池、GC、下游延迟关联;不能只看 active threads 判断是否健康。

3.1.16 动态数据源与声明式事务:连接过早绑定陷阱

使用 AbstractRoutingDataSource 或读写分离路由时,路由键通常在连接获取阶段决定。事务拦截器若已经开始事务并将连接绑定到当前线程,之后再修改 ThreadLocal 路由键通常不会把已绑定连接“切换”为另一个库。

  1. 典型错误:外层方法带 @Transactional,进入方法时事务管理器已获取/绑定主库连接;方法内部再设置“读库”标记,后续 JDBC 仍使用当前事务绑定的连接。
  2. 排查证据:检查数据源切面与事务切面的执行顺序、实际 Connection 的 JDBC URL、连接获取时的路由 key、事务同步状态及 propagation;仅打印 ThreadLocal 值不足以证明连接已切换。
  3. 方案一:在事务开始前由更外层路由切面选择数据源,确保路由逻辑先于事务拦截器获得连接,避免依靠模糊的默认 AOP 顺序。
  4. 方案二:把读写动作拆分到独立 Spring Bean/独立服务方法,使用明确事务边界;必要时通过编程式 TransactionTemplate 在正确的数据源/事务管理器下运行。注意 REQUIRES_NEW 会创建新事务,但如果路由切面仍顺序错误或事务管理器绑定错误,依然不能自动修复问题。
  5. 方案三:明确读后写一致性、事务内读路由、只读事务标记与复制延迟策略;“readOnly=true”并不等于自动选择从库。

3.1.17 Spring Boot + Kubernetes 优雅停机的完整时序

表 121:Spring Boot + Kubernetes 优雅停机时序
阶段发生什么必须防住的竞态
1. Pod 进入 TerminatingAPI Server 更新 Pod 状态;EndpointSlice/负载均衡控制面开始反映终止状态。摘流不是瞬时全局完成;客户端连接池、代理缓存和节点规则同步均可能有延迟。
2. preStop(如配置)Kubelet 在发送终止信号前执行 hook;有些部署会用短暂 sleep 给摘流传播留窗口。preStop 时间计入 termination grace period;sleep 只是缓冲,不替代 readiness、连接排空或健康检查。
3. SIGTERM → Spring Boot应用上下文关闭;嵌入式 Web Server 进入 graceful shutdown,拒绝新请求并等待在途请求在宽限期内完成。后台任务、消费线程、数据库事务、流式响应和长连接可能超过 Web 请求的默认生命周期;要定义各自的停止顺序。
4. 等待与强制终止Spring 生命周期阶段有自身 timeout;Kubernetes 的 terminationGracePeriodSeconds 到期后可发送 SIGKILL。配置必须满足 preStop + 应用停止耗时 + 安全余量 ≤ Pod 总宽限期;超时应可观测,不能只提高超时掩盖死锁。

建议把 spring.lifecycle.timeout-per-shutdown-phase、server.shutdown=graceful(按 Spring Boot 版本核对)和 Kubernetes 宽限期放在同一部署模板里管理。发布演练应验证:摘流后不再接新流量、在途请求成功率、消息消费者停止拉取、连接池清理、超时强杀比例及回滚行为。

3.1.18 Spring Boot 3/4、Framework 6/7:AOT、Runtime Hints 与 Native Image

AOT 会在构建阶段分析 Spring 容器并生成更固定的初始化/调用安排;Native Image 构建还要求显式描述某些反射、资源、序列化与代理的动态使用。不是所有库都要手工注册 Hints,Spring 已能推导一部分元数据;重点是找到运行时动态行为与可达性分析之间的缺口。

表 133:Native Image 构建失败的常见原因与修复路线
动态能力常见失败表现工程处理方式
反射/构造器/方法访问运行时报告某类型或成员无法反射访问。实现 RuntimeHintsRegistrar,注册需要的类型与成员;尽量优先使用框架可推导的标准编程模型。
Classpath 资源JVM 模式可以读取配置/模板,Native Image 中提示资源不存在。通过 hints.resources().registerPattern(...) 显式注册,模式要控制范围,不要一股脑打包敏感文件。
JDK 动态代理/序列化代理接口未注册、序列化目标未包含或反序列化失败。注册 JDK proxies、序列化类型等相应 hints,并给第三方动态特性建立最小可复现测试。
第三方库隐式动态行为依赖在运行时动态加载类、扫描资源、生成代理或调用反射。升级支持 AOT 的库;按需添加 hints;使用 RuntimeHints 相关测试和 native-image-agent 采集候选配置后进行审阅。采集只覆盖实际执行到的路径。
构建和验证闭环普通 JVM 测试通过,但 native build 或原生运行失败。先跑 Spring AOT/RuntimeHints 测试,再做 native build、关键路径集成测试、启动与内存基线测试,保持可回滚的 JVM 部署方案。
final class AppRuntimeHints implements RuntimeHintsRegistrar {
    @Override
    public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
        hints.resources().registerPattern("dicts/*");
        hints.reflection().registerType(
            MyPayload.class,
            MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS,
            MemberCategory.INVOKE_PUBLIC_METHODS);
    }
}

@Configuration
@ImportRuntimeHints(AppRuntimeHints.class)
class NativeImageHintsConfiguration {}

示例展示资源和反射提示的基本形式,需按应用类型选择最小权限的 MemberCategory。Spring Framework AOT 与 Spring Boot Native Image 的具体插件、测试支持及兼容版本请按项目使用的 Framework/Boot 版本查阅对应官方文档。

3.1.19 Spring Cloud Gateway:Netty EventLoop、阻塞调用与 DataBuffer 生命周期

Spring Cloud Gateway 的响应式请求通常运行在 Reactor Netty EventLoop 上。一个 EventLoop 负责多个连接;若在过滤器中直接执行阻塞 JDBC、同步 HTTP、长时间锁等待或大量 CPU 计算,会拖住该 EventLoop 上的其他连接,表现为看似“整个网关随机变慢”。同理,Request/Response Body 的缓冲与转发需要遵守 DataBuffer 的所有权和释放约定。

表 134:Gateway 过滤器的阻塞与内存风险治理
风险点症状/根因实践边界
EventLoop 阻塞线程名常见 reactor-http-nio-*;多个连接一起延迟,EventLoop 线程 CPU 或阻塞栈异常。优先改用真正的非阻塞客户端;不可避免的阻塞任务移到有界、可监控的专用 Scheduler/线程池,设置并发、队列、超时和拒绝策略。
错误使用 block()/subscribe()在响应式链中强行阻塞或自行订阅,破坏错误传播、取消传播和生命周期管理。通过 Mono/Flux 组合返回结果,让框架订阅;避免在 Filter 内创建脱离请求生命周期的订阅。
DataBuffer 泄漏读取/聚合 Body 后,原缓冲区在取消、异常或分支路径中未释放;堆正常但 direct memory/RSS 上升。能用 Gateway 内置的 CacheRequestBody、ModifyRequestBody 等过滤器时优先用;自定义聚合必须明确缓冲区所有权,并在错误/取消路径按 API 要求释放。不要对仍由下游使用的缓冲区重复释放。
无限制聚合请求/响应体缓存大 Body、无限制并发或长时间上游阻塞造成 direct memory 与连接耗尽。限制 Body 大小、并发、排队和超时;使用背压;监控 EventLoop、连接池、direct/mapped buffer、请求体尺寸与取消率。
排障证据链延迟升高与连接数、EventLoop 活跃度、上游连接池、DataBuffer 内存同时波动。抓取线程栈与 wall-clock profile,检查 Reactor Netty/HTTP 客户端指标、超时与取消日志;在压力环境复现并做回归。

不要把所有 DataBuffer 都机械地手动 release:先确认缓冲区所有权、是否已被框架消费,以及使用的是哪一版 Spring Framework/Reactor API。泄漏检测应在测试环境打开并覆盖取消、异常和重试路径。

3.2 微服务与分布式框架栈

表 8:Spring Cloud Alibaba 组件栈复习条目

组件 需掌握到的深度
Nacos AP/CP 模式切换、Distro 与 Raft 的边界、配置监听长轮询
Sentinel 滑动时间窗口统计、ProcessorSlotChain 责任链、系统自适应保护
Seata AT/TCC/SAGA/XA 四种模式的选型依据
Gateway 路由断言与过滤器机制、与 Sentinel 集成

表 9:Dubbo SPI 与 JDK SPI 五维对比

维度 JDK SPI Dubbo SPI
加载方式 一次性加载全部实现 按名称按需加载(getExtension("name"))
文件位置 META-INF/services/接口全名 META-INF/dubbo/接口全名,key-value
依赖注入 不支持 支持 setter 注入其他扩展
包装增强 不支持 支持 Wrapper 自动包装(AOP 能力)
自适应 不支持 @Adaptive 生成动态代理,按 URL 参数运行时选实现
  • Sidecar Mesh vs Proxyless Mesh(Sermant):Sidecar 具有多语言优势但增加一跳网络延迟;Proxyless Mesh 基于 Java Agent 在进程内直连控制面,保持零额外时延。

3.2.1 RPC 契约与跨语言协作

  • 协议选择:比较 REST/OpenAPI 与 gRPC/Protobuf 的可调试性、代码生成、跨语言契约、流式调用、网关支持和运维门槛;不要只按吞吐量决定。
  • 可靠性边界:为调用设置 deadline 并向下游传播;定义重试条件、幂等要求、最大重试预算、取消语义和背压行为,避免重试叠加放大流量。
  • 契约演进:兼容新增字段、未知字段和枚举扩展,明确破坏性变更策略;对跨服务变更使用契约测试、灰度验证和可回滚的发布顺序。
  • 可观测与身份:传播 trace context、调用方/服务身份与必要审计字段;在网关、服务和业务对象层分别执行授权,而不是仅凭网络可达判定权限。

3.2.2 微服务治理:发现、配置、流量与韧性

  • 服务发现与注册:理解注册、心跳/租约、健康实例、摘除与缓存一致性;区分存活探针、就绪探针和注册中心中的健康状态。Nacos、Consul、Eureka 等的协议、数据模型和一致性语义不同,不能把所有注册中心都理解成同一种强一致 KV。
  • 配置中心:配置来源优先级、profile/环境隔离、动态刷新边界、配置变更审计、密钥与普通配置分离;对不可热更新的线程池、数据源或安全参数应采用受控重建/滚动发布,而非假设所有配置都能实时生效。
  • 网关与负载均衡:路由、鉴权、限流、灰度标记、超时与请求体限制要有明确职责边界;对象级授权仍需在业务服务执行,不能仅凭请求经过可信网关就跳过资源权限校验。
  • 超时、重试与熔断隔离:设置端到端 deadline 并向下游传播;为每层明确连接/读取/总超时、重试条件、幂等前提、指数退避与抖动、重试预算;通过 Circuit Breaker、Bulkhead、限流和负载 shedding 控制级联故障。多层重试相乘可能放大流量。
  • 发布与兼容:滚动、蓝绿、金丝雀/灰度发布要与 API/消息 Schema 的向后兼容策略配合;数据库采用 Expand–Migrate–Contract,确保新旧版本并存期间字段和事件契约兼容,并准备暂停、回滚与数据补偿。
  • 可观测性:统一 trace context、服务身份、关键业务 ID 和错误分类;从请求延迟分位数、依赖错误率、线程池/连接池饱和度、重试次数和 SLO/error budget 判断是否限流、降级或扩容。

3.2.3 RPC 与客户端框架选型:Dubbo、gRPC、OpenFeign 与 HTTP

  • Dubbo:关注服务接口契约、注册/发现、集群容错、负载均衡、过滤器链、SPI 扩展、超时与重试;具体行为依 Dubbo 主版本和协议/注册中心扩展而异。
  • gRPC:关注 Protobuf 契约、生成代码、HTTP/2、多路复用、deadline、状态码、取消传播、拦截器和四类 RPC(Unary/Client streaming/Server streaming/Bidirectional streaming);浏览器、网关和负载均衡环境还需核对代理与协议支持。
  • OpenFeign / REST Client / WebClient:理解同步阻塞与异步/响应式调用差异、连接池、DNS、TLS、超时、重试和错误映射;WebClient 本身并不会自动让下游业务链路无阻塞,也不能把阻塞数据库调用放到事件循环线程。
  • 跨语言契约:REST 优先看 OpenAPI 与 HTTP 语义;RPC 看 IDL/Protobuf/Avro 等 Schema 兼容、枚举扩展、未知字段、错误码、认证、版本发布顺序和契约测试。避免把 Java 原生序列化对象作为长期跨服务协议。
  • 选型结论:按调用模型、跨语言、流式需求、端到端 deadline、调试与治理工具、团队熟悉度和运维成本选择;不以单次吞吐测试决定。服务网格可以承接部分流量治理能力,但不替代业务幂等、领域授权和应用级错误处理。

3.2.4 ZooKeeper:会话、ZNode、Watch 与 ZAB 协调机制

上传 PDF 第 11 章(目录标注页 171–174)整理了 ZooKeeper 角色、ZAB、投票与 ZNode。面试时应把它视为协调服务,而不是泛化的高吞吐数据库;重点理解会话、临时节点和一致性协议如何组合支撑注册发现、配置协调与分布式互斥。

表 93:ZooKeeper 核心结构与常见追问

主题机制要点边界/故障追问
ZNode 与节点类型持久节点、临时节点、顺序节点及临时顺序节点;节点可附带数据、版本与 ACL。临时节点随所属 session 失效后清理;临时节点不能再创建子节点。顺序节点编号适合构建竞争队列,但业务仍需处理会话失效与重建。
Session 与 Watch客户端维持会话,服务端跟踪会话状态;Watch 用于在数据/子节点变化时通知客户端。通知应视为“状态发生变化”的提示,不是可持久重放的事件流;客户端需要重新读取当前状态、处理重连并按所用 API 正确重新注册 Watch。
Leader/Follower/ObserverLeader 处理写入协调;Follower 参与投票/复制;Observer 可扩展读服务但不参与法定人数投票。写入确认依赖 quorum;脑裂、网络分区或法定人数不可达时,可用性会受限,这是强协调服务的设计取舍。
ZAB 与 zxidZAB 维护更新顺序,核心过程涉及崩溃恢复/Leader 选举、数据同步与消息广播;zxid 关联 epoch 和事务顺序。ZAB 与 Raft 都涉及 Leader 与日志/状态同步,但不是同一个协议;不要用“都是选主”替代对恢复、安全性与提交条件的解释。
常见落地模式服务发现、配置协调、主节点选举、临时顺序节点锁与成员管理。临时顺序节点锁仍需处理客户端暂停与锁过期后的旧持有者继续写入问题;关键写入应考虑 fencing token 或由目标资源进行版本/租约校验。

3.2.5 负载均衡、入口高可用与算法选型

上传 PDF 第 18 章(目录标注页 203–213)覆盖四层/七层负载均衡、算法、LVS、Keepalived、Nginx 与 HAProxy。以下保留其知识主线,并按现代部署的分层职责整理。

表 94:负载均衡常见产品、算法与适用边界

层面/方案处理方式适合场景与主要限制
四层 L4依据 IP/端口与传输层连接转发;常见实现包括 LVS、云网络负载均衡。协议通用、开销低;通常不了解 HTTP 路径与业务语义。NAT/DR/TUN/FULLNAT 是不同转发模式,路由、源地址保留与网络拓扑要求不同。
七层 L7依据 HTTP Host、路径、Header、Cookie 等应用层信息路由;常见 Nginx、HAProxy、API Gateway。适合 TLS 终止、路径路由、灰度与限流;需评估代理层 CPU/连接数、头部信任、超时和长连接行为。
轮询/加权轮询/随机轮询适合能力相近的后端;加权按容量分配;随机可用于简单分流。不考虑真实请求耗时与连接占用;后端容量差异大时需权重与健康检测配合。
最少连接/最短响应时间根据活跃连接或延迟指标偏向当前压力较小的节点。指标需要采样与更新;长连接、请求成本差异和指标滞后会影响实际效果。
IP Hash/一致性哈希将客户端或业务 key 稳定映射到后端节点。有助于会话粘性或缓存亲和,但会导致热点、分布不均与扩缩容迁移;不能替代服务端会话外置。
Keepalived / 健康检查通过 VRRP 或平台机制维持入口冗余,并按健康状态摘除节点。需要区分进程存活、端口可连、应用就绪和下游依赖健康;检查过于激进会引发抖动摘除。

3.2.6 Netty 与自定义 RPC:事件循环、编解码和请求关联

上传 PDF 第 8 章(目录标注页 147–158)涉及 Netty 高性能机制、Reactor、零拷贝、内存池、RPC 请求 ID、回调映射、Protobuf、Thrift 与 RMI。资深面试更关注网络线程模型与失败处理,而不是只背“异步、NIO、高性能”。

表 95:Netty/RPC 的关键机制

主题核心机制容易遗漏的边界
事件循环与 PipelineEventLoop 管理一组 Channel 的 I/O 事件;ChannelPipeline 按顺序执行入站/出站 Handler;常见 boss/worker 模型负责接入与连接 I/O。不能在 EventLoop 线程上执行长时间阻塞业务、同步 RPC 或重计算,否则单个事件循环可能拖慢其管理的多个连接。
ByteBuf 与内存ByteBuf 支持读写索引、堆/直接内存与引用计数;池化可减少分配压力。引用计数必须按所有权规则释放;泄漏会造成堆外内存增长。直接内存、池化和“零拷贝”都不是无成本,需结合分配/复制/缓存局部性测量。
协议分帧与序列化TCP 是字节流;需要长度字段、固定头/分隔符等方式解决粘包拆包,再进行解码、校验与反序列化。协议需限制帧长、字段数量、嵌套深度和解压比例,防止恶意输入导致内存/CPU 放大;协议版本与字段演进要兼容。
RPC 请求关联常见流程:生成 requestId → 写请求 → pending-call map 记录回调/Future → 响应按 requestId 匹配 → 完成结果。必须处理超时清理、取消、连接断开、迟到响应、重复响应与 pending map 泄漏;超时不等于远端业务未执行,重试仍需幂等。
调用治理连接管理、心跳、服务发现、负载均衡、超时传播、重试预算、限流与背压。连接断开重建、服务下线与注册信息滞后要有边界;禁止没有请求期限和最大重试次数的无限等待/重试。
协议与框架Protobuf/Thrift 等 IDL/编码方案;RMI 是 Java 生态的远程调用方式;Dubbo、gRPC 与自研 Netty RPC 的抽象层不同。比较时看跨语言、Schema 演进、序列化 CPU/体积、流式调用、生态与治理能力;不可只按单次序列化微基准作选型。

3.3 消息队列栈

表 10:四款消息中间件考察侧重对照

产品 高频考察技术点 考察侧重与适用场景
Kafka ISR、ACK、HW/LEO、幂等(PID+seq)、事务、零拷贝 适合高吞吐事件流与日志型工作负载;常用于平台数据基础设施
RocketMQ 顺序消息、延迟消息、事务消息(半消息+回查) 交易/订单/业务事件的常见候选;事务消息用于构建最终一致性,不代表数据库与 Broker 具备全局强一致
RabbitMQ Exchange 类型、confirm/return、Quorum Queue(Raft) 轻量集成与灵活路由;经典镜像队列已在 RabbitMQ 4.0 移除,复制场景需评估 Quorum Queue 的语义、性能与迁移成本
Pulsar 存算分离(Broker + BookKeeper)、多租户、分层存储 海量主题、多租户平台型业务

面试范围:至少能比较 Kafka、RocketMQ、RabbitMQ,并理解 Pulsar、JMS/ActiveMQ Artemis、云托管消息服务及 Spring 集成框架的定位。把 Broker、客户端库、Spring 适配器和流处理工具区分清楚。

3.3.1 MQ 通用基础:模型、投递语义与顺序边界

表 77:MQ 通用模型与投递语义对照

主题必须掌握追问边界
通信模型点对点队列、发布订阅、事件流;Topic/Queue/Exchange/Partition/Subscription 等概念不同产品同名概念的语义并不完全相同;先讲抽象,再讲具体 Broker 的实现
投递语义至多一次、至少一次、有限场景的恰好一次;生产确认、持久化、消费确认和位点提交“Broker 内部 EOS”不自动等于数据库、HTTP、外部系统的端到端 exactly-once;外部副作用通常仍需幂等或事务设计
顺序全局顺序、分区/队列内顺序、业务 Key 顺序顺序通常以牺牲并行度或引入同 Key 串行作为代价;重试、重新入队、重平衡可能改变实际处理顺序
确认与偏移生产端 confirm/ACK;消费端 ACK/NACK;Kafka offset 与其他 Broker 的消息确认模型不能把 Kafka 的 offset 提交与 RabbitMQ 的 ACK 混为一个机制
可靠性副本、ISR/quorum、持久化策略、消费者重试、DLQ、消息过期和保留策略“持久化消息”仍受队列是否 durable、复制/确认配置、故障域和磁盘状态影响
流控批量、预取、分区数、消费者并发、背压、速率限制、滞后指标扩消费者不一定提高吞吐,可能受分区上限、数据库连接池、热点 Key 或下游限流约束
契约消息 Schema、版本兼容、Header、追踪 ID、业务事件 ID、时间戳与重放语义不要把 Java 序列化类直接作为跨团队长期契约;优先考虑明确的 Schema 和兼容规则

3.3.2 消息端到端防丢、消费幂等与重试风暴防范

  • 防丢闭环:生产端带回调重试;Broker 采用同步落盘/多副本同步;消费端严禁自动提交位点,业务处理成功后再手动 ACK。
  • 消费幂等兜底:在至少一次投递、消费者超时重试、提交确认丢失或进程故障等场景下,可能出现重复投递/重复处理。对这类业务应使用“业务唯一键 + 本地数据库唯一约束(或分布式状态机)”实现原子防重,并明确消费位点提交与业务事务的边界。

覆盖范围说明:原版只对 Kafka 机制做了较细说明,并用 Kafka、RocketMQ、RabbitMQ、Pulsar 做了产品级对比;对 MQ 通用语义、各 Broker 内部机制、JMS/云托管消息服务及 Spring/集成框架覆盖不完整。本轮已补齐主流面试地图。消息产品持续演进,以下按“常见度 + 机制代表性”整理,不声称罗列全球所有商用产品。

3.3.3 Kafka 核心机制与可靠性因果链条

  • 高吞吐五大来源:顺序追加写(Append-only)、OS 页缓存利用、sendfile 零拷贝(省去两次 CPU 拷贝与用户态切换)、批量压缩、分区分段稀疏索引(每 4KB 记录一条索引)。
  • 可靠性链条:acks=-1(all) + min.insync.replicas=2;Leader 维护 ISR,HW 决定消费者可见性边界,防止未提交数据在 Leader 切换时引发脏读。
  • 生产端幂等:enable.idempotence=true,分配 PID 并通过单调递增 Sequence 避免重复发送。

3.3.4 Kafka 深入:日志、消费者组、事务与运维

  • 存储模型:Topic/Partition、Leader/Follower、日志段、索引、保留策略与 log compaction;区分消息保留和消费者是否已消费。
  • 副本与可见性:ISR、LEO、HW、消费可见性与 Leader 选举;理解 acks、min.insync.replicas、副本数的配合及其在故障时的可用性/数据丢失权衡。
  • 生产端:batching、linger、压缩、重试、超时、buffer.memory、幂等生产者 PID/sequence;幂等生产者的范围和配置依赖版本。
  • 消费端:Group Coordinator、分区分配、rebalance、心跳/拉取间隔、位点提交、重试与暂停分区;扩容消费者超过可分配分区数后不一定提升并行度。
  • 事务与 EOS:事务生产者、read_committed、事务性消费-处理-生产链路;若数据库已提交而 Kafka offset 尚未提交,或外部调用已成功,应由幂等、Outbox/Inbox 或可恢复状态处理跨系统边界。
  • 生态:Kafka Streams 的流处理状态、窗口与再处理;Kafka Connect 的 Source/Sink 连接器;Schema Registry 与 Avro/Protobuf/JSON Schema 兼容策略;MirrorMaker 2/复制与跨集群灾备。
  • 运维:Consumer Lag、分区不均衡、热点分区、ISR 收缩、磁盘水位、请求队列、网络与请求超时、重平衡循环;用指标定位生产者限流、Broker 瓶颈还是下游消费慢。

3.3.5 RocketMQ 深入:业务消息能力与 4.x/5.x 差异意识

  • 架构:NameServer/路由发现、Broker、CommitLog、ConsumeQueue/索引等基础结构;新旧版本在代理、客户端协议、消费模型和部署选项上可能存在差别。
  • 消息模型:普通、顺序、延迟/定时、事务消息、批量与过滤;掌握 Topic、Tag、Consumer Group、消费进度、重试主题与死信队列。
  • 事务消息:半消息、执行本地事务、提交/回滚以及 Broker 回查;必须讨论本地事务可查询性、回查幂等、最终一致性和业务状态机。
  • 顺序消息:按业务 Sharding Key 路由到同一队列并串行消费;需要明确热点业务 Key、失败重试对队头阻塞的影响。
  • 重试和死信:区分短暂故障与毒消息;配置最大重试、延迟退避、死信监控、人工修复/重投和业务幂等。
  • 迁移题:从 4.x 到 5.x 不应只改客户端依赖;按官方迁移说明核对客户端协议、Broker 版本、部署形态、权限、延迟/定时消息和消费行为。

3.3.6 RabbitMQ 深入:Exchange、Confirm、ACK 与 Quorum Queue

  • 路由模型:Exchange 的 direct/topic/fanout/headers 类型,Queue、Binding、Routing Key、Virtual Host、TTL、优先级与死信转发。
  • 生产可靠性:Publisher Confirms 确认 Broker 接收/处理状态;Return 处理不可路由消息;结合持久化消息、durable queue 和合适队列类型设计完整链路。
  • 消费确认:manual ACK/NACK、requeue、prefetch/QoS、消费者超时与连接断开后的重投;ACK 只代表消息被确认,不代表业务副作用天然原子。
  • 队列类型:Quorum Queue 基于 Raft 的复制与一致性取舍;Streams 适用于可重复读取的日志式用法;需理解经典队列与不同版本特性的迁移边界,不能继续把旧式镜像队列当成所有新部署的默认方案。
  • 常见故障:连接/Channel 数过多、Unacked 堆积、预取过大、队列持续增长、磁盘告警、不可路由消息、死信循环、重投风暴;结合管理 UI、Broker 指标与应用日志定位。

3.3.7 Apache Pulsar 深入:多租户、订阅与存算分离

  • 架构角色:Broker 处理协议与分发,BookKeeper/Bookie 持久化日志,元数据/协调组件负责集群元数据;具体部署依版本和托管形态而异。
  • 命名和隔离:Tenant / Namespace / Topic、资源配额、权限、保留和 TTL;多租户平台要同时考虑性能隔离与成本隔离。
  • 订阅类型:Exclusive、Failover、Shared、Key_Shared;理解是否保序、并发度与消费者故障切换之间的取舍。
  • 进阶能力:分层存储、Schema、重放、事务、地理复制、持久/非持久主题;每项能力都应核对目标版本、配置和运营限制。
  • 与 Kafka 对比:从分区/订阅模型、存储架构、多租户、消费模式、生态、团队运维复杂度和迁移成本比较,不以单项吞吐测试直接下结论。

3.3.8 JMS、ActiveMQ Artemis 与传统企业消息系统

  • JMS API:理解 ConnectionFactory、Connection、Session、Destination、MessageProducer/Consumer、消息选择器、持久订阅、事务 Session 与 ACK 模式。JMS 是 Java 消息 API/规范体系,不是 Broker 产品。
  • ActiveMQ Artemis:Queue/Topic、地址与队列路由、协议支持、DLQ/过期队列、集群/桥接、持久化和事务语义;注意它与 ActiveMQ “Classic”是不同产品线。
  • 企业级选项:IBM MQ、Oracle AQ/TxEventQ 等可能出现在金融、制造或既有企业系统;掌握系统边界、事务/安全/运维要求即可,不必在没有目标岗位依据时追所有专有运维细节。
  • 与 Spring 对接:Spring JMS、JmsTemplate、监听容器与事务管理;重点理解 JMS Session 事务和数据库事务是否由同一管理器原子协调,不能默认跨资源自动原子化。

3.3.9 MQ 产品与 Java 集成框架总览

面试时要分清三层:Broker/托管消息服务负责存储路由和投递;Java 客户端/适配器负责 API 与确认/重试封装;集成/流处理框架负责抽象、编排、连接器或事件处理。它们不是同一类竞品。

表 78:MQ 产品、客户端、集成与流处理框架矩阵

类别常见产品 / 框架定位与面试深度
高吞吐事件流Apache Kafka、Redpanda(Kafka API 兼容实现/发行形态)、Amazon Kinesis、Azure Event Hubs分区日志、消费位点、保留/回放、消费组、流处理;Kinesis/Event Hubs 属托管服务,不应与自建 Broker 运维完全等同
业务消息 BrokerApache RocketMQ、RabbitMQ、Apache ActiveMQ Artemis、IBM MQ、Oracle AQ/TxEventQ路由、业务解耦、确认、重试/DLQ、事务和企业集成;按目标行业选择深入对象
多租户消息平台Apache Pulsar、Solace PubSub+多租户、跨地域、协议/事件平台能力与平台运维成本
轻量发布订阅NATS JetStream、Redis Streams低延迟/轻量消息或 Redis 生态内流式消费;需评估持久化、回放、复制、规模和运维能力,不默认视为 Kafka 的完全替代
IoT 消息MQTT 协议;EMQX、HiveMQ、Mosquitto 等 MQTT BrokerQoS 0/1/2、会话、遗嘱消息、主题订阅;MQTT 是协议,Broker 才是产品
云消息服务AWS SQS/SNS/EventBridge、Azure Service Bus/Event Hubs、Google Cloud Pub/Sub托管服务的可用性、投递语义、费用、配额、死信、跨区域与云厂商锁定问题
Spring 原生集成Spring for Apache Kafka、Spring AMQP、Spring for Apache Pulsar、Spring JMSKafkaTemplate/@KafkaListener、RabbitTemplate/@RabbitListener、PulsarTemplate/Listener、JmsTemplate;核心在理解容器、确认、事务、错误处理与版本兼容
跨 Broker 抽象Spring Cloud Stream、Spring Cloud Function、Spring Integration、Apache CamelFunction / Binder / MessageChannel / Integration Flow / Route 与企业集成模式;抽象降低耦合,但不抹平 Broker 语义差异
数据集成与流处理Kafka Connect、Debezium、Kafka Streams、Apache Flink、Schema RegistryCDC、Source/Sink、流式状态与窗口、Schema 演进;Flink/Streams 属流处理框架,不是传统消息 Broker
  • 优先掌握:Kafka + RocketMQ + RabbitMQ 的核心区别,至少一种 Spring 集成方式,以及通用可靠消息设计。
  • 按岗位扩展:数据平台深入 Kafka/Pulsar/Connect/Flink;交易系统深入 RocketMQ/RabbitMQ/事务消息;金融和大型企业关注 IBM MQ/JMS;IoT 关注 MQTT Broker;云原生/多云平台关注托管消息服务与跨云治理。
  • 不应机械背诵所有产品:掌握消息语义、故障边界、运维指标和迁移成本,远比记住几十个产品名称更重要。

官方版本快照(核验截至 2026-10-27,仅用于建立版本意识):Apache Kafka 4.4.0(2026-10-22 发布)、RabbitMQ 4.4.0(2026-10-20)、Apache RocketMQ 5.5.1(2026-08-20)、Apache Pulsar 5.0.1(2026-10-26)。各项目版本策略、支持周期、客户端/服务端兼容性并不相同;尤其 MQ 升级必须检查协议/元数据格式、集群滚动升级顺序、客户端版本、复制/事务行为及回滚路径。Kafka 官方发布说明、RabbitMQ 支持与发布信息、RocketMQ 官方下载/版本页、Pulsar 官方版本页。

3.3.10 端到端可靠消息:Outbox、CDC、重试与幂等

表 79:端到端可靠消息方案选型对照

模式解决的问题成本 / 必须补齐的点
本地事务 + Outbox业务数据与待发送事件在同一本地事务中提交,避免 DB 与 Broker 双写窗口后台投递、重复发送、Outbox 清理、失败告警;消费者仍需幂等
CDC 发布从数据库日志捕获 Outbox/变更并投递到消息平台关注复制位点、Schema、删除语义、重复事件、延迟和回放;CDC 工具不是天然的业务事务协调器
Inbox / 唯一约束消费者记录已处理的业务事件 ID,在本地事务中原子防止重复副作用唯一键设计、保留时长、并发冲突处理、状态生命周期;不能先记已处理再执行业务而不保证原子性
重试 + DLQ暂时性故障延迟重试;毒消息转死信等待排查区分可重试/不可重试;指数退避加抖动、最大次数、队列上限、告警、回放幂等和人工纠错
事务消息 / Saga特定 Broker 的事务消息或业务补偿处理跨系统最终一致性事务回查、补偿可重入、超时悬挂、状态机、对账与人工介入;不等同于所有数据库与 Broker 的全局 ACID
  • 幂等键:优先使用稳定业务事件 ID/订单号 + 业务动作;不能简单用消息内容 Hash 作为唯一业务依据(合法重复业务可能内容完全相同)。
  • 顺序与重试:先定义业务要求的顺序范围;失败后重试时决定阻塞当前分区/队列、退避重投还是进入独立重试队列,并接受相应顺序代价。
  • 重放:明确从哪个 Offset/时间点/业务水位重放,如何隔离副作用、避免重复扣款/通知,以及如何验证数据补偿完成。
  • 事务边界:说明数据库 commit、Broker confirm、消费 ack/offset 的先后次序,并逐个分析进程在每个时间点崩溃会发生什么。

3.3.11 MQ 性能、监控、安全与故障场景

  • 容量估算:消息速率 × 平均消息大小 × 保留时长估算原始数据量,再计入副本、索引、压缩与安全水位;容量规划需按峰值和恢复窗口而非日均吞吐设计。
  • 核心指标:生产失败率、发送延迟、Broker 磁盘/网络/请求队列、副本健康、消费 Lag/积压增长率、最老消息年龄、重试和 DLQ 速率、消费处理耗时、未确认消息数。
  • 安全:TLS、SASL/认证、ACL/Topic 权限、租户隔离、凭据轮换、敏感载荷治理、审计与网络边界;权限不能只给到集群级通配符。
  • 故障题:消息丢失、重复消费、积压持续增长、顺序错乱、Broker 切主、消费者重平衡循环、死信堆积、消息过期、队列不可路由、磁盘打满、跨机房复制延迟。
  • 排查顺序:先确认生产端是否发出且收到确认,再确认 Broker 持久化/副本与路由,接着看消费者是否收到、处理耗时和 ack/offset,最后核对下游 DB、线程池、连接池及重试策略。
  • 架构决策题:从消息大小、吞吐与延迟、顺序范围、保留/回放、多租户、事务要求、协议兼容、运维能力、云服务费用、团队熟悉度和迁移成本做决策,不用“哪个 MQ 最快”替代场景分析。


3.4 网络与 IO 栈

表 11:网络与 IO 最小必讲集合

技术项 需掌握到的深度
TCP 基础 三次握手/四次挥手、TIME_WAIT 与 CLOSE_WAIT、半连接/全连接队列溢出
HTTP/HTTPS HTTP/1.1 与 HTTP/2 多路复用差异、QUIC、TLS 握手开销
传输零拷贝极限 HTTPS 加密导致 sendfile 失效悖论、Linux kTLS(Kernel TLS)与硬件网卡卸载
超时体系 连接超时 vs 读取超时 vs 业务超时;超时预算逐层递减
连接池 HikariCP ConcurrentBag 的低开销连接借用路径(ThreadLocal、共享列表、CAS/等待机制等)与泄漏检测;不要将整个获取流程概括成“绝对无锁”
重试与幂等 指数退避加 Jitter、全链路重试预算设计

3.4.1 连接池与 HTTP 客户端故障模式(表 33)

主题 需掌握到的机制
HikariCP 并发 ConcurrentBag 无锁借还;leakDetectionThreshold 借出超阈值未归还打印泄漏堆栈日志
超时层级预算 网关超时 \(\ge\) 聚合服务超时 \(\ge\) 基础服务超时 \(\ge\) 下游 Client/JDBC 超时,严格逐层递减
连接池与熔断联动 下游慢时连接池先于熔断器感知阻塞(获取连接超时);“连接池耗尽”是下游故障的先兆信号

3.4.2 HTTP/2 与 HTTP/3 协议深入(表 51)

维度 HTTP/1.1 + 连接池 HTTP/2 HTTP/3 (QUIC)
传输层 TCP 文本协议 TCP 二进制分帧 UDP(QUIC 协议)
多路复用 靠多个 TCP 连接并发 单 TCP 连接并发多 Stream 单 UDP 连接并发多独立 Stream
队头阻塞 存在应用层队头阻塞 解决应用层阻塞,但仍有 TCP 队头阻塞 避免 TCP 跨流队头阻塞(不同 QUIC Stream 可独立交付;同一流内仍会受丢包/重传与共享拥塞控制影响)
握手延迟 1 RTT (TCP) + 1~2 RTT (TLS) 2~3 RTT 0~1 RTT 快速握手连接
网络切换 IP 变动导致连接断开重连 断开重连 基于 Connection ID,移动网络切换零断连

3.4.3 网络请求全链路分阶段耗时排查

生产网络排障应将一次请求分解为六个阶段分别衡量:

$\(\text{总耗时} = \text{DNS解析} + \text{TCP握手} + \text{TLS协商} + \text{请求发送} + \text{服务端处理} + \text{响应传输}\)$

避免将所有延迟笼统归结为“网络慢”。

3.4.4 数据库事务、连接池与线程池协同治理

  • 级联枯竭风险:Tomcat 线程在长事务中持有数据库连接并发起慢 RPC,导致 HikariCP 连接池耗尽,阻塞后续请求线程,进而拖垮 Tomcat 线程池引发全局雪崩。
  • 容量配比准则:

$\(\text{数据库实例最大承载连接} \ge \sum (\text{各应用实例数} \times \text{HikariCP maximumPoolSize})\)$

保持连接池精简,通过压测寻找吞吐拐点,避免无序放大。

3.4.4.1 HikariCP 小连接池原则与定容起点

连接池不是用来给每个应用线程分配一个数据库连接。数据库能同时高效执行的查询数有限;把连接池从 20 盲目放大到 200,可能增加数据库锁争用、运行队列、上下文切换和 P99 延迟,而不是线性提升吞吐。入口并发应通过线程池/信号量/队列在应用侧受控,并用连接获取耗时、活动连接、等待线程、SQL 执行时间和数据库 CPU 一起判断瓶颈。

表 143:连接池定容的经验式与验证原则
项目工程起点边界与验证
HikariCP 经验式active_connections ≈ core_count × 2 + effective_spindle_count这是经验起点而非通用定律;core_count 不应简单把 SMT/HT 逻辑线程都算入,effective spindle 与工作集缓存命中、存储类型相关;HikariCP Wiki 也提醒 SSD 场景没有一条通用的已验证常数公式。
初始配置范围许多普通服务可从每实例约 10–30 个连接的压测区间开始,而非预设必须达到该范围。高延迟 SQL、长事务、批处理、多数据源或大量实例会改变最优值。先计算数据库总连接预算:所有实例的池上限之和不能超过 DB 的连接与并发执行预算。
放大池子的风险更多连接并不等于更多有效并行查询。观察 TPS/吞吐拐点、P95/P99、CPU、锁等待、磁盘 I/O、连接获取等待;若吞吐已平坦而延迟上升,应回退池大小并限制上游并发。
防死锁公式pool size ≥ Tn × (Cm − 1) + 1仅用于讨论每个线程会同时持有多条连接时避免某类资源等待死锁的下限,不是吞吐最优公式;优先避免单线程嵌套获取多连接。

定容流程:统计全局 DB 连接预算 → 估算并发 SQL 能力 → 设置保守初值 → 用生产相似的混合负载压测 → 找吞吐和延迟拐点 → 验证连接池耗尽、慢 SQL、DB 故障与流量突增时的保护效果。

3.4.5 零拷贝的暗礁:HTTPS 传输层加密悖论与 Linux kTLS 架构

Kafka 和 Netty 的高性能神话建立在操作系统 sendfile(零拷贝)之上。但在全站 HTTPS / TLS 普及的今天,资深架构师必须洞察一个底层的断裂:传统用户态 TLS 通常不能直接复用纯明文 sendfile 的数据路径;内核态 TLS(kTLS)等机制可在受支持的条件下恢复部分内核态数据路径优化。

表 59:kTLS 与传统用户态 TLS 零拷贝性能对比

维度 传统 sendfile(纯明文 HTTP) 传统 TLS(HTTPS + sendfile) Linux kTLS(Kernel TLS 架构)
数据流转路径 磁盘 \(\to\) PageCache \(\to\) Socket Buffer(DMA 传输,零 CPU 拷贝) 磁盘 \(\to\) PageCache \(\to\) 用户态 JVM 内存(解密/加密计算) \(\to\) 内核 Socket Buffer 磁盘 \(\to\) PageCache \(\to\) 内核 kTLS 驱动直接加密 \(\to\) 网卡(DMA)
CPU 参与度 避免把有效载荷搬入用户态再复制回内核;CPU 仍参与系统调用与内核网络协议处理,DMA 通常负责网卡数据搬运 通常需要经过用户态缓冲及 TLS 加密处理,增加数据拷贝和 CPU 加密开销;具体路径与成本取决于 TLS 库、内核能力和应用实现 加密可在内核执行;部分平台/密码套件可结合 NIC Offload。内存拷贝路径与收益取决于内核、TLS 配置及硬件能力
零拷贝状态 ✅ 内核态数据路径可避免常规用户态有效载荷复制(具体仍依赖操作系统、文件与网络路径) ⚠️ 传统用户态 TLS 通常无法直接沿用纯明文 sendfile 路径;常需经过用户态缓冲/加密,现代内核与 TLS 实现存在其他优化路径 ✅ 在受支持的内核态 TLS 发送路径中可恢复 sendfile 类优化(需满足内核、协议、密码套件与应用栈条件)
吞吐与延迟 极高吞吐,微秒级延迟 可能引入显著的复制/加密开销;损失幅度与负载、TLS 实现和硬件有关,需实测 在适配路径上可减少用户态复制和加密开销;与明文传输的性能差距必须按目标环境实测

架构破局与工程选型:

  1. Netty TLS 引擎选型:JDK JSSE/SSLEngine 与 netty-tcnative(OpenSSL/BoringSSL,取决于构建和平台支持)各有兼容性、性能和运维成本。不要预设 JDK 实现必然低效,也不是所有服务都必须引入原生 TLS;应在相同协议、密码套件、证书配置和负载下进行吞吐、延迟、CPU、启动与故障回退压测后再选型。
  2. Linux kTLS 接入:Linux 4.13 引入内核 TLS 基础能力,但 TLS 版本、密码套件、发送/接收方向、网卡卸载与应用框架支持随内核及库版本变化。若评估 Netty 与 kTLS/ sendfile 联用,应核对目标 Netty/native transport、OpenSSL/内核版本、TLS 配置和实际使用路径;不是只开启 CONFIG_TLS 就能保证恢复零拷贝。

3.4.6 经典 I/O 模型、网络协议与 Reactor

在 HTTP/2、HTTP/3 与连接池专题之外,补齐 PDai 的 Linux I/O 模型、Reactor、TCP 流语义与基础网络协议问题,以及《成神之路》的 HTTP、DNS、Cookie/Session 与反向代理主题。

表 84:I/O 模型与网络编程核心问法

主题核心知识点常见追问与排障边界
五种 I/O 模型阻塞 I/O、非阻塞 I/O、I/O 多路复用、信号驱动 I/O、异步 I/O;需要区分“系统调用是否阻塞”与“数据是否已准备好”。I/O 多路复用通常让一个线程监视多个 fd,但应用实际读写仍可能阻塞;不要将“使用 NIO”直接等同于端到端异步。
select / poll / epollselect 使用固定集合/位图且通常有 fd 数量限制并涉及集合拷贝;poll 用数组表达 fd;epoll 通过注册兴趣与就绪事件机制减少每次遍历开销。优势受连接数、活跃比例、内核版本和事件模式影响;ET 边沿触发一般需读写到 EAGAIN,避免漏事件。
Reactor vs ProactorReactor 通知“就绪”,业务再执行读写;Proactor 通知“操作完成”。常见 Linux epoll 服务模型是 Reactor 风格。区分事件分发、I/O 执行与业务处理线程;Netty 的 EventLoop 不应被长时间阻塞任务占住。
TCP 流与粘包/拆包TCP 是可靠有序的字节流,不保留应用消息边界;一次 write 不保证对应一次 read。用固定长度、分隔符、长度字段或协议帧解码定义边界;同时处理半包、粘包、最大帧长度与恶意超长输入。
流量控制与拥塞控制接收窗口用于保护接收方处理能力;拥塞控制根据网络状况调节发送量。二者目标相关但不同。结合 RTT、重传、窗口、发送队列与应用耗时区分网络拥塞和服务端慢处理。
连接生命周期理解 SYN 半连接/全连接队列、TIME_WAIT 与 CLOSE_WAIT;后者持续增加通常提示应用未关闭本端 socket/响应体等资源。先用 ss/netstat、连接池指标与线程栈定位原因,再决定连接复用、超时和内核参数;不要把调内核参数当第一解法。
DNS / TLS / Cookie / SessionDNS 解析涉及缓存、TTL、记录类型与递归解析;TLS 提供机密性、完整性和对端身份校验;Cookie 通常由客户端保存,Session 状态通常在服务端或共享存储。注意 DNS 缓存与切流延迟、证书链/主机名验证、Cookie 的 Secure/HttpOnly/SameSite、Session 粘性与多实例共享。
HTTP 状态与重定向区分 2xx 成功、3xx 重定向、4xx 客户端请求问题、5xx 服务端处理失败;301/302 与 307/308 对方法/请求体转发语义不同。结合幂等性、重试策略、Location、代理缓存和请求体可重放性排查,不要见 5xx 一概盲目重试。

3.4.7 CDN、边缘缓存与源站保护

上传 PDF 第 9 章(目录标注页 159–168)列出 CDN 的分发、负载均衡与管理系统。把 CDN 理解成“离用户更近的可编程缓存与流量入口”,需要同时理解缓存键、过期、刷新、回源和访问控制。

表 96:CDN/边缘缓存的关键设计点

主题需要掌握的内容生产风险与处理
缓存键与缓存策略Host/Path/Query/Header/Cookie 是否纳入 Cache Key;Cache-Control、TTL、静态与动态内容缓存边界。缓存键不完整会造成跨用户数据串读;把所有查询参数纳入缓存键又可能降低命中率。需按接口语义设计白名单。
刷新与失效TTL 到期、主动 Purge/Invalidate、版本化静态资源、stale-while-revalidate 等策略。大规模同时失效会产生回源洪峰;更新策略需要错峰、预热、旧版本可回退和源站限流。
回源与源站保护回源鉴权、连接复用、请求合并、限流、失败重试与源站健康检查。CDN 缓存未命中不应无限重试;必须限制单对象回源并发,避免热门对象失效时击穿源站。
安全与可观测性签名 URL/Cookie、HTTPS、可信代理头、WAF/访问控制、命中率和回源延迟指标。不要无条件信任客户端提交的 X-Forwarded-For;只信任受控代理链,并避免将私有响应或授权结果缓存到公共键。

3.5 响应式编程栈(Reactor/RxJava/WebFlux)

  • 核心概念:响应性、弹性、伸缩性与背压(Backpressure)机制。
  • 陷阱与禁区:严禁在 Reactor/WebFlux 事件循环线程中调用阻塞式 I/O(如 JDBC、同步 HttpClient),否则将导致少量核心调度线程被永久阻塞,服务瞬间瘫痪。

4. 数据存储与缓存栈

4.1 MySQL 栈

表 12:MySQL 栈复习条目

技术项 需掌握到的深度
索引底层 B+ 树、最左前缀、覆盖索引、索引下推(ICP)、MRR、EXPLAIN 分析
事务与锁 MVCC(ReadView、Undo Log)、当前读与快照读、Next-Key Lock 防幻读
日志与恢复 Undo、Redo Log(WAL 保证崩溃恢复)、Binlog;两阶段提交与恢复判据
分库分表 ShardingSphere、分片键选型、不停机双写对账迁移、规避 Full Route 与笛卡尔积
大表治理 冷热分离、分区表代价、大表 DDL 四层方案(表 41)、MDL 锁链式阻塞
容灾与约束 RPO/RTO、PITR 恢复;防止超卖的数据库原子条件更新机制

4.1.1 隔离级别、读类型与幻读两条路径(表 13)

隔离级别 快照读(普通 SELECT) 当前读(FOR UPDATE / UPDATE / DELETE)
RC 每次执行 SELECT 均生成新 ReadView,存在不可重复读与幻读 常规搜索/索引扫描通常不使用间隙锁;外键约束检查和重复键检查仍可能使用间隙锁。因而可能出现幻读,具体锁行为取决于语句、索引与隔离级别。
RR 事务首次执行快照读生成 ReadView 并复用,避免快照读幻读 通过 Next-Key Lock 锁住区间阻断并发插入,避免当前读幻读

4.1.2 一条 UPDATE 的日志旅程与两阶段提交

1. 写 Undo Log :记录物理旧值,支撑事务回滚与 MVCC 快照读。
2. 改内存并写 Redo Log (Prepare) :修改 Buffer Pool 数据页,写 Redo Log 物理日志,状态置为 Prepare(WAL 机制)。
3. 写 Binlog :Server 层写入逻辑 binlog 并落盘(由 sync_binlog 控制)。
4. 提交并写 Redo Log (Commit) :Redo Log 状态变更为 Commit,响应客户端成功。

4.1.3 分库分表、不停机迁移与 ShardingSphere 三大坑(表 38)

坑点 机制 解法
不带分片键查询 \(\to\) Full Route 无法路由,向所有分片下发 SQL,连接池瞬间打满 强制带分片键;多维查询走 ES 检索兜底;小字典表用广播表
跨分片 JOIN \(\to\) 内存笛卡尔积 应用内存组装笛卡尔积,极易 OOM 配置绑定表(Binding Table)转化为单库本地 JOIN,或在应用层两次查询组装
雪花 ID 时钟回拨 \(\to\) 重复主键 NTP 回拨导致 ID 冲突 采用号段模式(Leaf-segment)或等待时钟追平补偿
4.1.3.1 冷热分离与数据归档(表 34)
主题 需要能讲清的边界
触发信号 单表过亿、查询条件高度集中在近期数据(如近 3 个月)、历史数据访问极低
实现方式 同库不同表路由、异构存储(MySQL 热数据 + HBase/ClickHouse/OSS 冷数据)
迁移一致性 异步 CDC 双写迁移,迁移脚本可重入,定期对账,冷数据保持只读可查
4.1.3.2 分区表真实代价与大表 DDL 四层方案(表 41)
  • 分区表真实代价:分区表是单库内物理分段,分区键必须在主键中;若查询未命中分区键将引发全分区扫描,性能比单表更差;分区过多导致元数据与 DDL 极慢。
  • 大表 DDL 四层方案(表 41):
    1. MySQL 8.0 Instant DDL:秒级修改元数据(仅限追加列等)。
    2. Online DDL INPLACE:支持并发 DML,但仍有 MDL 锁和从库延迟风险。
    3. gh-ost:解析 Binlog 同步至影子表,无触发器开销,首选推荐。
    4. pt-online-schema-change:基于触发器同步,高并发下主库争用大。
  • MDL 锁链式阻塞:DDL 等待长事务释放 MDL 读锁,导致后续所有读查询在 MDL 队列排队,瞬间打满连接池。大表 DDL 必须低峰期执行并设置超时。
4.1.3.3 MySQL + ShardingSphere 与 TiDB / OceanBase 选型边界

这是架构权衡而非单纯性能排名。ShardingSphere 以应用侧/代理侧分片与路由为主,保留单分片 InnoDB 的局部低延迟优势,但需要治理跨分片事务、JOIN、全局索引、分布式分页、扩缩容和数据迁移。TiDB/OceanBase 将分布式 SQL、共识复制与分布式事务纳入数据库体系,降低应用层分片编排负担,但跨节点协调、时钟/事务协议、网络 RTT、数据分布和集群运维都会影响延迟与成本。

表 144:分库分表与 NewSQL 选型对照
维度MySQL + ShardingSphereTiDB / OceanBase 等分布式 SQL决策要点
扩展方式按业务路由键水平拆分实例/表,容量与迁移策略由应用和中间件共同治理。数据库集群内部负责数据分片、复制、调度和部分透明扩展。评估数据增长、热点键、分布式运维能力与现有团队经验。
事务与关联单分片交易接近普通 InnoDB;跨分片事务/JOIN 受事务模式、路由键与中间件能力限制,需要明确失败和补偿语义。提供数据库原生分布式事务;TiDB 的事务设计受 Percolator 启发并使用 TSO,OceanBase 使用基于 Paxos 的多副本日志同步等机制。是否必须跨分片 ACID、业务键能否共置、冲突热点和事务长短决定实际代价。
延迟与吞吐正确路由的单分片读写可避免跨节点事务协调,但应用扇出查询会放大连接、网络和聚合成本。单分区/共置访问与跨节点事务的代价不同;跨节点写入通常增加网络协调,性能依拓扑、复制数、负载和事务形态而变。不要把“1–2 ms”或“数毫秒”当成承诺;用真实数据分布、P95/P99 与故障场景压测。
运维复杂度需治理分片键、全局唯一 ID、扩容迁移、跨分片查询、数据对账与回滚。需理解副本/共识、拓扑、容量均衡、升级兼容和分布式事务监控;硬件与运营能力要求通常更高。将许可/云托管费用、SRE 能力、灾备和回滚成本一并纳入 TCO。
倾向选型已有成熟 MySQL、负载可以按业务键分片、以单分片 OLTP 为主且可接受应用治理复杂度。需要透明水平扩展、跨分片事务/SQL 能力或统一 SQL 入口,且团队能承担分布式数据库运维。先通过 POC 验证 DDL、事务隔离、备份恢复、兼容性、热点和故障切换,避免只看基准跑分。

4.1.4 索引失效七类、深分页与主从延迟

  • 索引失效七大场景:1. 隐式类型转换(字符列传数字);2. 索引列使用函数或表达式;3. 前导通配符 like '%xxx';4. 联合索引跳过首列(不满足最左前缀);5. or 条件一侧无索引;6. !=、not in 导致全表;7. 优化器成本估算回表代价过高。
  • 深分页优化:采用延迟关联(通过覆盖索引子查询取主键再 JOIN 原表)或游标分页(where id > :last_id order by id limit 20)。
  • 主从延迟治理:开启并行复制(slave_parallel_workers,MySQL 8.0 writeset);关键业务读强制走主库;大事务拆分。

4.1.5 数据库备份、灾备恢复与 RPO/RTO 治理

  • RPO(Recovery Point Objective):业务容忍丢失的最大数据时间跨度(如 \(\le\) 5分钟)。
  • RTO(Recovery Time Objective):发生灾难至恢复可用状态允许的最长耗时(如 \(\le\) 30分钟)。
  • PITR(Point-in-Time Recovery):基于全量物理备份基线重放连续 Binlog,精确恢复至任意历史秒级时间点。定期自动演练校验备份的真实可恢复性。

4.1.6 业务不变量与并发条件更新保护机制

如果业务只在应用层执行无锁的“先查后改”,并发请求可能基于同一旧值继续写入,产生超卖等竞态。应根据业务约束使用数据库原子条件更新、唯一约束、行锁或乐观锁(版本号)实现并发保护:

UPDATE inventory
SET available = available - :quantity
WHERE sku_id = :skuId AND available >= :quantity;

通过检查受影响行数判断扣减成功与否,配合乐观锁版本号(version)防御更新丢失。


4.1.7 关系模型、范式、并发控制与数据库可编程对象

上传 PDF 第 19 章(目录标注页 214–224)除了 MySQL 索引/事务,还列出数据库范式、ACID、存储过程、触发器、乐观/悲观并发策略、锁层级与分库分表。现有 MySQL 专题已经深入 InnoDB,因此本节只补关系设计与通用概念,不重复 MVCC/Next-Key Lock 细节。

表 97:关系数据库基础与并发控制补充

主题核心知识点面试/设计边界
1NF/2NF/3NF1NF 关注列值与域的原子性;2NF 在满足 1NF 后,消除非主属性对候选键的部分函数依赖;3NF 进一步限制非主属性对候选键的传递依赖(用正式函数依赖解释)。范式是分析工具,不是越高越好;为读性能做反规范化时,必须设计唯一约束、更新路径与数据对账。避免用“一个表只描述一件事”代替严格定义。
ACID 与事务原子性、一致性、隔离性、持久性;本地事务、跨资源事务与业务最终一致方案。一致性依赖业务不变量与约束,不是单由事务框架保证;跨服务调用不因加上 `@Transactional` 就自动组成一个原子事务。
乐观/悲观并发控制乐观方式通过版本号/条件更新检测冲突;悲观方式用锁先行约束竞争。高冲突下乐观重试可能放大负载;长时间持有悲观锁会阻塞并拖垮连接池。方案需要考虑冲突概率、重试代价和事务时长。
锁粒度与范围行锁、表锁、页锁是数据库产品与引擎的实现选择;索引范围、谓词和隔离级别会改变实际锁集合。不要把“执行 UPDATE 就只锁这一行”当作普遍事实;需结合执行计划、索引、隔离级别、外键与具体数据库版本分析。
存储过程与触发器存储过程适合数据库侧复用逻辑;触发器可在数据变更时自动执行审计/派生逻辑。它们会隐藏副作用、增加迁移与测试复杂度,并带来数据库厂商耦合;核心业务流程是否下沉应按一致性、可观测性、团队治理和跨库可移植性决定。

4.1.8 EXPLAIN 执行计划解读与 SQL 优化证据链(表 111)

现有 MySQL 章节已覆盖索引、事务、MVCC、深分页和主从延迟;本节把面试中常见的“如何证明 SQL 慢在哪里”落到执行计划字段和诊断次序,避免只背索引失效场景。

检查项怎么看判断时的陷阱
type / 访问方式结合 const、eq_ref、ref、range、index、ALL 等判断扫描策略和范围。不能只看一个字段就判定好坏;表大小、选择性、回表成本和连接顺序都会影响计划是否合理。
possible_keys / key确认候选索引与最终采用的索引,并核对联合索引的列顺序。“有索引但没用”可能来自统计信息、低选择性、隐式转换、表达式、排序/分组成本等,不要立刻强制索引。
rows / filtered估算扫描行数和过滤后保留比例;多表 JOIN 要关注中间结果集膨胀。估算与实际可能有偏差,数据倾斜、统计信息过期和参数分布都会影响优化器决策。
Extra理解 Using index(覆盖索引)、Using index condition(ICP)以及临时表、排序相关提示。Using filesort 不等于必然发生磁盘排序;要结合数据规模、执行时间与资源使用分析。
EXPLAIN ANALYZE在支持的 MySQL 8.0 版本上观察实际执行、实际行数和时间信息,验证估算是否偏离。它会实际执行语句;对高成本查询、写语句或生产数据应先评估影响,不应无条件在高峰期执行。
  • 诊断顺序:确认慢查询样本和绑定参数 → 看执行计划与实际耗时 → 检查扫描行数、过滤率、JOIN 顺序和回表 → 验证索引/SQL 改动 → 对比 P95/P99、锁等待、CPU 与磁盘 I/O。
  • 修复策略优先级:消除不必要查询和返回列、调整谓词与联合索引、优化 JOIN 与分页、更新统计信息或重写 SQL;只有证据支持时才考虑提示或强制索引。
  • 版本提示:EXPLAIN ANALYZE 的可用性、输出格式和语义依 MySQL 具体版本而定,阅读执行计划时应使用目标环境的官方手册。

4.1.9 InnoDB Buffer Pool:LRU Old/Young 与刷脏页抖动

Buffer Pool 缓存数据页和索引页。InnoDB 使用带有 old/new 子列表的 LRU 变体来降低扫描污染。默认 old 子列表大约占 3/8,new/young 约占 5/8,不要把两者比例写反或当作固定不变的所有版本常量。

表 122:InnoDB Buffer Pool LRU 与刷脏页诊断
机制/指标怎么理解排查与调优方向
Old/Young 子列表新读入的页先进入 old 区;满足访问频率/时间条件后再晋升到 young 区,避免全表扫描短时间将热点页挤出。innodb_old_blocks_pct 控制 old 子列表比例(常见默认 37%);innodb_old_blocks_time 控制新页首次访问后进入 young 前的时间窗口(常见默认 1000ms,需按版本核验)。
扫描污染报表/备份/批量扫描会把大量一次性页面读入缓存,可能降低 OLTP 热点页命中率。结合 Buffer Pool 命中、逻辑读/物理读、扫描 SQL、批处理时段和缓存工作集判断;优先减少无边界扫描并分批执行。
Dirty Pages 与 Page Cleaner更新页先变脏,再由后台刷脏线程写回数据文件;Redo/刷盘能力和脏页积压影响检查点推进与写入尾延迟。观察脏页比例、checkpoint age、待刷页、磁盘 await/IOPS、redo 生成速率和 page cleaner 活动;不要仅靠增大线程数或 I/O capacity 盲调。
突发刷盘与 P99 毛刺后台刷脏不足时可能积累压力,后续出现突发刷盘、前台等待或更频繁的刷盘调节。同步分析磁盘吞吐、fsync 延迟、redo 容量、数据写入速率和存储 QoS;把缓解措施与写入限速、批量大小及容量规划一起评估。

4.1.10 InnoDB 死锁日志:从锁等待到 SQL 证据链

  1. 采集:立即执行 SHOW ENGINE INNODB STATUS\G,查看 LATEST DETECTED DEADLOCK;频繁发生时在授权与日志容量评估后开启 innodb_print_all_deadlocks 收集更多样本。
  2. 定位两个事务:分别提取 TRANSACTION、持有锁(HOLDS THE LOCK(S))、等待锁(WAITING FOR THIS LOCK TO BE GRANTED)、SQL 文本和回滚受害者。
  3. 回到索引:判断使用的是聚簇主键、普通二级索引还是唯一二级索引;检查扫描范围、间隙/Next-Key 锁、唯一性检查、外键以及是否按不同顺序更新多行。
  4. 构造时间线:事务 A 已持有锁 X 等待 Y,事务 B 已持有 Y 等待 X,形成等待环。非主键唯一索引的插入/更新可能涉及唯一性检查和相关索引记录锁,但死锁成因必须按具体锁模式与 SQL 还原,不能简单归因于“二级索引必然 Next-Key 锁”。
  5. 整改:缩短事务、按一致顺序访问资源、补齐过滤列索引、避免在事务中做远程调用;应用端对死锁回滚做有边界的重试,保证业务幂等并记录重试率。
SHOW ENGINE INNODB STATUS\G
SHOW VARIABLES LIKE 'innodb_print_all_deadlocks';
-- MySQL 8.0/8.4 可结合 Performance Schema 的 data_locks / data_lock_waits 分析当前等待

死锁与锁等待超时不是同一种错误;InnoDB 通常会检测死锁并回滚一个事务,但事务被选为 victim 后,应用仍需处理失败与重试。官方文档建议保持事务短小,并对涉及多行/多表的操作采用一致访问顺序。

4.1.11 主从延迟下的因果读与 Read-Your-Writes

需求不是“从库永远无延迟”,而是同一用户写入后读取该写入时,不能读到明显旧版本。可采用主库读、复制位点/GTID 等待、会话级一致性路由等策略。

  1. 写路径记录因果标识:在提交写事务后获取该事务的 GTID(可评估 MySQL 的 session tracking 能力);不要随手读取一个全局 GTID 集就误认为它严格只代表当前会话的事务。
  2. 读副本前等待:在支持 GTID 的拓扑下,副本侧可用 WAIT_FOR_EXECUTED_GTID_SET(gtid_set, timeout) 等待目标事务已执行;传统 binlog-file/position 模式可用相应位置等待函数。
  3. 超时策略:副本在预算内追平则从副本读;超时后按业务选择回源主库、返回显式重试/稍后刷新,或允许旧读。不得无限等待占满连接池。
  4. 会话而非全局承诺:把写事务的 GTID/位点与用户会话或请求上下文关联,设置过期和跨服务传递规则。跨库、多个事务或跨地域写入可能需要多个因果标识,而不是单一 GTID。
  5. 可观测性:记录副本延迟、等待耗时、超时比例、回源主库比例和读一致性命中率;在容量规划中计入等待占用与主库回退流量。

4.1.12 MySQL 8.0 优化器深水区:Hash Join、倒序索引、不可见索引与 JOIN 顺序

MySQL 优化器的行为必须和具体版本绑定。MySQL 8.0.18 引入 Hash Join;从 8.0.20 起不再使用传统 Block Nested-Loop 算法,并在原本会使用 BNL 的场景采用 Hash Join。Hash Join 的内存受 join buffer 相关预算约束,超出内存时可能使用磁盘文件,不能把它理解成“无索引关联一定很快”。

表 135:MySQL 8.0 优化器能力与生产风险
主题机制与版本边界排查与上线策略
Hash Join适用于优化器判断可用的连接场景,常见于连接条件无法利用索引时;从 8.0.20 起 BNL 移除。先用 EXPLAIN FORMAT=TREE 或 EXPLAIN ANALYZE 看实际计划、估算/实际行数和耗时;关注 join buffer、临时文件与磁盘 I/O。
Descending IndexMySQL 8.0 支持真正存储倒序键值;多列索引可以混合 ASC/DESC,帮助匹配混合排序方向。例如 INDEX ix (a ASC, b DESC) 可能匹配 ORDER BY a ASC, b DESC;仍需核对筛选条件、覆盖列、选择性和实际执行计划。
Invisible Index不可见索引仍由 DML 维护,但默认不参与优化器索引选择;可以先隐藏来评估删除后的计划变化。执行 ALTER TABLE t ALTER INDEX idx INVISIBLE 后观察真实查询;需要时用 use_invisible_indexes 测试。它不是免费操作,索引仍占空间与写维护成本。
驱动表/连接顺序优化器依赖统计信息、基数估计、谓词选择性和成本模型选 join order;“小表驱动大表”只是常见经验,不是无条件规律。对比估算与实际行数,必要时刷新统计信息;STRAIGHT_JOIN 作为有证据的诊断/特定优化手段,不应代替统计信息修复。
Explain Analyze 的副作用EXPLAIN ANALYZE 会实际执行被分析的 SELECT,长查询或重查询可能消耗线上资源。优先在影子/压测环境运行;若在生产执行,要预估扫描规模、锁/IO 影响并设置明确的变更窗口。

版本核验:Hash Join 的适用条件、BNL 移除与内存/磁盘行为请以 MySQL 8.0 对应小版本官方手册为准。不要将 MySQL 5.7 的优化器行为直接套用到 8.0。

4.2 Redis 与缓存栈

表 14:Redis 栈复习条目

技术项 需掌握到的深度
数据结构 底层编码(listpack/ziplist、skiplist、intset)与对象内存优化
高可用与持久化 RDB/AOF 混合持久化选型、哨兵与 Cluster(16384 槽)治理
分布式锁 Watchdog 自动续期、Lua 原子防误删、fencing token 与 DB 兜底防线
一致性与防护 Cache Aside、Canal 异步删缓存;穿透、击穿、雪崩防护体系;String big key 异步边界

4.2.1 两组必须给出结论的选型

  • 持久化选型:纯 RDB 易丢数据,纯 AOF 恢复慢且文件大。生产首选 RDB + AOF 混合持久化。
  • 高可用选型:哨兵解决主从单点故障(提供自动故障转移);Cluster 解决单机容量与写吞吐上限(16384 槽分片)。两者解决不同维度,超大规模为分片集群每分片做主从。

4.2.2 分布式锁边界:续期不等于安全

Redisson Watchdog 解决业务未执行完锁过期问题;Lua 比对 UUID 保证不误删他人的锁。但分布式锁本质是降低冲突的性能优化手段,绝不是资金级正确性的唯一保障;客户端长时间 GC 停顿或网络分区仍会导致锁失效。强一致业务必须依赖数据库唯一约束、版本号 CAS 条件更新作为最终正确性兜底。

4.2.2.1 Fencing Token 如何在持久层真正生效

分布式锁服务只告诉客户端“曾经获得锁”,不能阻止租约过期后的旧持有者继续运行。Fencing Token 必须由最终资源端校验,且每次成功授予锁时单调递增;随机 UUID 不具备这个属性。

-- 示意:资源行保存已接受的最大 token;具体 SQL 要结合业务更新条件与并发事务设计
UPDATE resource_record
SET payload = :payload, fencing_token = :token
WHERE resource_id = :id
  AND fencing_token <= :token;
  • 影响行数为 1:token 为当前最高值或更高值时,更新获准;影响 0 行:通常表示 token 已过旧或记录不存在,需区分处理。允许同一个租约 token 执行该租约内的多个合法写操作(示例用 <=),但一旦更高 token 被资源端接受,旧 token 必须被拒绝。
  • 若一次业务跨多行/多表,所有相关写入必须处于同一事务,且不能先执行不可撤销的外部副作用再做 token 校验。
  • token 的生成方必须保证对同一资源严格单调;发生锁服务恢复、主从切换或计数器回滚时,需要明确 epoch/持久化语义。
  • 如果资源端无法存储或原子比较 token,就不能宣称获得真正 fencing 保护;只能说明该方案提供租约式互斥,并保留失效持有者的风险。

4.2.3 缓存一致性:四种方案的适用边界(表 15)

方案 机制 适用与代价
Cache Aside 先更新库再删缓存,基准方案 极端并发仍有脏读,需设置合理 TTL 兜底
延迟双删 更新库后延时再删一次 降低主从延迟脏读,但延迟时间难以精准估算
删除失败进 MQ 重试 保证缓存最终删除成功 引入 MQ 依赖,需处理幂等重试
Canal 订阅 Binlog 异步删除 对业务主链路侵入通常较小,但增加 CDC 链路、延迟与运维成本;性能及时效取决于 Binlog 消费延迟、队列积压、顺序保证和故障恢复设计 架构链路长,需监控 Canal 延迟与顺序性

4.2.4 淘汰策略、过期删除与 big key/热 key 治理(表 16)

  • 近似 LRU 与 LFU:LFU 采用 24 bit 存储(高 16 位记录上次衰减时间,低 8 位存储基于概率对数递增的访问计数)。
  • String big key 的 lazyfree 边界:UNLINK 命令对集合型 Big Key 能在后台异步释放,但对几 MB 乃至几十 MB 的 String 大对象,Redis 仍可能在主线程直接释放物理内存块引发短暂卡顿。治理方案必须前置拆分或压缩。

4.2.5 Redis Sentinel、Cluster 与故障切换深挖

现有 Redis 小节已列出哨兵、Cluster、持久化与分布式锁,本节把常见面试追问落到判定条件、数据丢失窗口和客户端行为,避免只记住“哨兵高可用、Cluster 分片”两句口号。

表 85:Redis 高可用、复制与集群边界

主题关键机制容易答错的边界
Sentinel 检测与切换监控主从节点;主观下线(SDOWN)不等于客观下线(ODOWN);达到配置 quorum 后进入故障判断,Sentinel 之间会选出执行故障转移的领导者。quorum 是判定 ODOWN 的票数门槛之一,不等于“有 quorum 就必然切换成功”;还要看可用 Sentinel、可晋升副本与网络分区。
主从复制与数据窗口Redis 复制通常是异步的;主节点故障时,已确认但尚未复制到被提升副本的写入可能丢失。关键业务需要评估丢写窗口、复制延迟、min-replicas-to-write 等策略,并以数据库/业务幂等作最终正确性兜底。
Cluster 哈希槽与多键操作Redis Cluster 将 key 映射到 16384 个槽;客户端按 MOVED/ASK 重定向路由,槽迁移期间可能出现 ASK。多 key 命令、Lua 和事务需要满足同槽约束;可用 hash tag 将相关 key 映射到同一槽,但会带来热点风险。
RDB / AOF 与恢复RDB 是快照;AOF 记录写命令并可选 fsync 策略;混合持久化结合快照基线与后续增量。恢复目标取决于 fsync、快照间隔、复制延迟与磁盘可靠性;恢复时间和数据丢失窗口需实测,而非只看配置名。
单线程与多线程边界Redis 命令执行路径以单线程串行处理为核心,但后台持久化、惰性释放、网络 I/O 线程等版本和配置会引入其他线程。不要把“Redis 单线程”解释为整个进程只有一个线程;慢命令、大 key、主线程阻塞仍会影响所有客户端。
客户端与故障恢复客户端必须理解 Sentinel/Cluster 拓扑、连接失败、重定向、超时与重试;连接池中断或故障切换后需重建/刷新拓扑。重试要有预算与抖动;写命令重试前确认幂等性,避免超时后“服务端成功但客户端未收到”造成重复业务。

4.2.6 缓存穿透、击穿、雪崩、预热与降级的完整处置

上传 PDF 第 24 章(目录标注页 257–258)专门列出缓存雪崩、穿透、预热、更新与降级。现有章节已经覆盖 Cache Aside、延迟双删、MQ/CDC 删缓存与 big key;本节把“故障现象—缓解机制—代价”串起来,避免不同问题共用一个答案。

表 98:分布式缓存常见故障与缓解手段

问题典型机制方案与代价
缓存穿透大量查询不存在的 key,缓存无法命中,持续打到存储层。参数/权限校验、合理的空结果短 TTL、Bloom Filter 或本地负缓存;需注意 Bloom Filter 假阳性,且缓存空结果要防止掩盖新创建的数据。
缓存击穿/热 key某个高频 key 在到期/失效瞬间大量并发回源。互斥重建、请求合并(singleflight)、逻辑过期/异步刷新、热点副本;锁要设超时并避免让所有请求同步等待。
缓存雪崩大量 key 同时失效,或缓存集群整体故障。TTL 加随机抖动、分批预热、限流/舱壁、备用数据或降级响应;恢复时控制回填速率,防止重启后回源洪峰。
缓存预热与刷新在流量到来前加载热点集合,或按 TTL/消息变化刷新。预热要限速、分页、可中断与幂等;热度随时间变化,应以访问指标调整,而不是无界加载全部数据。
缓存更新与降级Cache Aside、延迟双删、消息重试、CDC/Binlog 驱动失效;故障时返回缓存旧值或简化结果。删除失败需可观测和可重试;降级必须定义最大可接受陈旧度、敏感数据边界与恢复策略。缓存不是最终一致性的唯一保障。
4.2.6.1 Bloom/Cuckoo Filter、SingleFlight 与平滑预热
表 123:Bloom/Cuckoo Filter 与缓存并发重建策略
技术优势必须说明的边界
Bloom Filter以紧凑位数组和多个哈希函数判断元素“可能存在/一定不存在”,适合拦截大量不存在的 key。允许假阳性、不允许标准实现假阴性(在未发生错误/删除语义变更前提下);预期误判率由位数与哈希数决定。标准 Bloom 不支持直接删除;扩容通常需分层/重建或使用 scalable Bloom 设计,不能原地假定位数组可安全扩充。
Cuckoo Filter以指纹存储,常见实现支持删除,适合需要删除能力的成员测试。插入可能因桶满/搬迁上限失败;指纹碰撞仍可能假阳性;扩容和重新散列要设计数据重建窗口。
空值缓存短 TTL 缓存“不存在”结果,压制重复穿透。TTL 太长会让刚创建的记录仍被判断不存在;需要写入时主动失效、版本校验或短期 TTL。
SingleFlight / 互斥重建相同 key 的并发 miss 合并成一个回源任务,其他请求等待同一结果或返回旧值。等待应有超时与取消策略;同一进程内 SingleFlight 不保护多实例,需要分布式协调或接受各实例各自重建。
逻辑过期保留旧值并后台刷新,避免热点 key 到期时所有请求阻塞。允许在约定窗口返回旧值;后台失败需要退避、告警和并发保护,不能无限返回过期数据。

预热按热点清单分页限速、支持中断和幂等;恢复时逐步增加回填并观察 DB QPS、连接池等待、缓存命中和延迟。降级开关需要动态配置、权限、审计、TTL/自动回收及演练,避免永久降级。

4.2.7 Redis 数据结构、持久化与生产命令治理(表 112)

原报告已细化缓存一致性、淘汰策略、big key、哨兵和 Cluster;本节参考 JavaGuide Redis 面试专题,将数据结构选型、持久化窗口与生产命令风险放在同一张核对表里。来源:JavaGuide Redis 面试题总结。

结构/机制典型用途必须说明的边界
String / Hash简单 KV、计数器;对象字段、用户画像或配置片段。注意大 Value 与字段更新粒度;原子计数与业务幂等不是同一问题。
List / StreamList 可做简单队列;Stream 提供消费组、消息 ID、Pending Entries 与 ACK 等消息流能力。Redis 队列不是专业 MQ 的无条件替代;需设计保留长度、积压、重放、消费确认和故障恢复。
Set / Sorted Set去重、交并差集合;排行榜、延迟任务索引、按分数范围查询。要看集合规模与 O(N) 操作;排行榜热点与大集合操作可能造成单线程命令执行延迟。
Bitmap / HyperLogLog / GEO有限整数域状态位图、基数近似统计、地理位置范围查询。Bitmap 的空间与 ID 范围相关;HyperLogLog 以近似误差换空间,不提供精确元素集合。
RDB / AOF / 混合持久化RDB 提供快照;AOF 记录写命令;混合持久化以快照基线结合增量日志。持久化策略影响丢失窗口、恢复时间、磁盘 I/O 与文件体积;持久化不等于异地备份,也不自动等于强一致。
过期与淘汰惰性过期 + 周期性主动过期;内存压力下按配置淘汰。过期时间不是准点定时器;业务正确性不能依赖 key 到期事件准时触发。
批处理与扫描Pipeline 减少网络往返;Lua 脚本提供服务端原子执行;SCAN 系列适合渐进式遍历。KEYS * 等全量扫描可能阻塞;SCAN 不是快照遍历,可能重复返回,调用方需要允许重复并控制 COUNT/节奏。
线程与性能命令执行核心路径以事件循环串行处理为主;较新版本可以多线程处理部分网络 I/O。“Redis 全部单线程”和“Redis 命令执行全面多线程”都不准确;热点 key、慢命令、fork/COW 与网络 I/O 应分别定位。

生产自检:避免高峰期执行未知复杂度的大命令;通过 SLOWLOG、延迟监控、INFO、内存采样和 key 级分析定位问题;任何 Redis 分布式锁、计数器或队列设计都要说明客户端重试、主从切换和数据丢失窗口。


4.2.7.1 Redis 内部编码演进与生产命令审计
表 124:Redis 内部编码、持久化与生产命令治理
结构/机制内部实现要点生产核对点
String / SDSSDS 保存长度、可用空间和字节数组;扩容策略可减少频繁 realloc,并支持二进制安全。关注大 Value、复制/返回完整值的成本、内存碎片与淘汰影响;不要把所有 String 操作都视为 O(1)——命令复杂度与 Value 长度有关。
Hash / Set / ZSet 紧凑编码满足大小/元素阈值时可采用 listpack 等紧凑表示;Hash/Set/ZSet 在条件变化后可能升级编码。Set 还可能使用 intset 存储小型整数集合。ziplist 是历史实现;Redis 7 及现代版本中应按具体类型和阈值确认 listpack/intset 等编码,不要把旧版本细节硬套到当前版本。
List现代 Redis 的 List 典型采用 quicklist,由多个紧凑节点组织;节点可用 listpack 表示。大列表 range、扫描与存储结构会影响延迟;控制元素长度、节点参数和批量读取。
ZSet常见编码包括紧凑 listpack 与 dict + skiplist;跳表通过多层索引加速按分数范围查找,层高由概率机制决定。范围查询的成本与返回元素数量有关;高频全量排名/大范围返回可能成为延迟来源。
高危命令与大结果KEYS *、FLUSHALL、大范围 HGETALL 或无界 LRANGE 可能阻塞主命令执行路径或导致大响应。在生产通过 ACL/权限审计限制危险命令;迭代使用 SCAN、HSCAN 等游标接口并处理重复/遍历期间变更;SCAN 不是事务快照。
慢命令治理使用 SLOWLOG、延迟监控、INFO、内存采样和 key 级热点/大对象分析。慢查询阈值和保留数量应基于版本与负载设置;审计命令、慢查询数据应避免泄露敏感 key/值。

4.2.8 Redis 6/7 深水区:网络 I/O 多线程与 Multi-Part AOF

Redis 6 引入可配置的网络 I/O 多线程能力,但它并不意味着 Redis 命令执行整体变成多线程并行:请求解析/读取与响应写回可在配置允许时借助 I/O 线程,数据结构命令执行的核心路径仍以主事件循环串行为主。Redis 7 的 Multi-Part AOF 则把重写基线与增量变更拆分为多个文件,并由 manifest 跟踪。

表 136:Redis 6/7 版本差异与生产治理
主题实现要点工程边界
Redis 6 I/O Threads用于分担网络读取/协议处理及响应写回等 I/O 工作;命令执行不应被理解成任意多线程并发修改同一数据集。先确认 Redis 版本、io-threads 和读取线程配置,再用目标网络负载验证;I/O 线程不是修复慢命令的方案。
慢命令与单线程核心一次耗时较长的 O(N) 命令、Lua 脚本或大范围遍历仍可能堵住后续请求。结合 SLOWLOG、latency monitor、命令复杂度、key 基数和客户端往返次数定位;优先使用分页/SCAN、聚合命令和 Pipeline。
Redis 7 Multi-Part AOFBase 文件保存重写基线,Incremental 文件保存基线之后的变化,Manifest 管理文件集合。它改善了传统单 AOF 文件的组织和重写切换行为,但不会消除磁盘饱和、fork/COW、fsync、后台重写 I/O 对延迟的影响。
持久化与延迟预算AOF fsync 策略影响持久性与延迟;RDB/AOF 重写需考虑 fork、页复制、磁盘带宽和恢复时间。将写入 QPS、AOF 增量增长、重写频率、fsync 延迟和磁盘剩余空间纳入监控;在压测中验证故障恢复时间。

不要把“Redis 单线程”解读为所有后台工作都是单线程;也不要把“Redis 6 多线程 I/O”解读为普通命令在多个线程并行执行。版本、配置与负载决定具体效果。

4.3 搜索引擎、文档库与向量库栈

  • Elasticsearch:倒排索引与 Segment 不可变性;分片路由;写入通过 Translog 与 Refresh 保证近实时;脑裂通过 Quorum 仲裁避免。
  • MongoDB:文档型灵活建模;支持 4.0+ 跨文档多表事务(有性能开销);分片集群与副本集。
  • 向量数据库(Milvus / Pinecone):在高维空间构建 HNSW 索引,支撑 RAG 与语义检索。

4.3.1 MongoDB、HBase 与 Cassandra:模型、存储路径和选型

上传 PDF 第 14–16 章(目录标注页 183–200)分开介绍 HBase、MongoDB 与 Cassandra。当前报告只在数据存储总览中提及部分产品,因此这里补齐适合 Java 后端面试的模型与读写路径;2018 年资料中的旧数据模型叫法不直接作为现代版本结论。

表 99:文档型与宽列型数据库对照

数据库核心模型/读写路径适用场景与主要追问
MongoDBBSON 文档、集合、索引;Replica Set 提供复制/选主;分片集群按 shard key 路由。适合文档聚合和结构变化较多的业务;需解释嵌入/引用建模、索引覆盖、分片键热点、事务成本与一致性读取选项。事务能力取决于部署与版本配置,不应概括为“所有场景都与关系库一样”。
HBase宽列存储;RowKey、Column Family、Region;典型写路径涉及 WAL、MemStore、Flush/StoreFile 与 Compaction,底层常使用 HDFS。适合大规模稀疏数据、按 RowKey/范围读取和高吞吐写入;RowKey 设计决定分布与扫描效率,避免单调递增 key 造成热点;随机查询/复杂 JOIN 不是优势。
Cassandra分布式宽列模型;Partition Key 决定数据分布,Clustering Columns 决定分区内排序;CommitLog、Memtable、SSTable 与 Compaction 构成典型写路径。以去中心化复制和可调一致性级别换取规模与可用性;需要理解协调节点、复制因子、Consistency Level、Gossip、Hinted Handoff/修复与 Tombstone/Compaction。
共同设计问题数据模型、访问模式、复制与一致性、分区键、索引、压缩/合并、备份恢复、Schema 演进。选型应从查询模式和 SLA 出发,而不是“某类数据库更先进”;跨分区查询、二级索引与事务能力通常有显著成本。
4.3.1.1 MongoDB、HBase、Cassandra 的存储读写路径与放大效应
表 125:MongoDB/HBase/Cassandra 存储读写路径对比
系统写入/存储机制读取/维护机制生产追问
MongoDB / WiredTiger文档经存储引擎写入并由 journal/checkpoint 等机制保障持久性;WiredTiger 使用内存缓存、页组织与并发控制。索引定位文档,缓存命中可减少存储读取;checkpoint 将一段时间内的脏数据状态推进到持久存储,后台 eviction 与存储 I/O 会影响延迟。检查 working set 是否装入 WiredTiger cache、cache eviction、checkpoint/Journal、索引命中、文档大小、锁/冲突指标与磁盘延迟。checkpoint 不是每个事务提交的唯一持久性机制。
HBase / HFile(LSM 风格)典型路径:客户端定位 Region → WAL 追加 → MemStore 更新 → 达阈值或触发条件时 Flush 为 HFile/StoreFile。读取会合并检查 MemStore 与多个 HFile,借助 BlockCache、Bloom Filter、索引降低 I/O;Compaction 合并 StoreFile 并清理过期/删除标记。RowKey 决定 Region 分布;单调递增键可能造成热点。Region split/merge、Compaction 和 Flush 会带来读写放大与磁盘压力;需看 StoreFile 数、队列、BlockCache 命中、WAL 和 Region 热点。
Cassandra任意节点可充当 coordinator;按 Partition Key 经 partitioner 映射 token/ring 范围,写入 CommitLog 与 Memtable,后续 Flush 为 SSTable。读取根据一致性级别从所需副本读取,合并 Memtable/SSTable 版本;后台 Compaction 合并文件并清理符合规则的 tombstone。复制策略与 consistency level(ONE、QUORUM、LOCAL_QUORUM、ALL 等)决定延迟和可用性取舍;需关注热点分区、SSTable 数、tombstone、repair、hinted handoff、compaction backlog 与跨数据中心流量。

不要把 HBase、Cassandra 的 LSM/追加写模型等同于“写入没有成本”:它们通常以后台 Flush/Compaction 换取顺序写与规模扩展;读放大、空间放大、修复和数据模型约束仍是核心成本。MongoDB 的事务/读写关注点则要按部署模式、读写 concern、索引和具体版本判断。

4.3.2 Elasticsearch/Lucene:倒排索引、Segment、分片与深分页

表 126:Elasticsearch/Lucene 索引、Segment 与分页
机制核心模型面试/生产落点
倒排索引Term Dictionary 映射词项,Posting List 存储包含该词的文档与位置/频率等信息;具体索引结构由 Lucene 版本和字段类型决定。分析器决定 tokenization;keyword/text 字段、分词、BM25、doc values、字段映射和索引基数共同影响检索与聚合成本。
FST 与词典压缩Lucene 可使用 FST 等结构压缩并快速定位词项;数值/地理空间等字段也可能使用 BKD Tree 等结构。不要把所有倒排索引都简化成一个 FST;不同字段类型和 Lucene 版本会采用不同索引结构。
Immutable Segment 与 Merge写入先经过内存缓冲/事务日志,Refresh 后形成可搜索 Segment;段不可原地改写,更新常体现为新版本与删除标记,后台 Merge 合并段。Refresh 间隔影响近实时可见性;Merge 会带来磁盘 I/O、CPU、临时空间和写放大。bulk 规模、refresh、replica 和磁盘容量要协同设计。
Shard Allocation 与集群稳定性主分片/副本的放置由分配器根据节点、磁盘水位、分配规则与集群状态决定。排查 unassigned shards、磁盘水位、分配 explain、节点失联和版本兼容;脑裂治理应以现代 Elasticsearch 的 quorum/cluster coordination 机制理解,不能照搬旧版 Zen Discovery 参数。
深分页from/size 会令各分片保留并排序大量候选命中;Scroll 更适合固定视图下的批量遍历,search_after 结合稳定排序更适合深分页。跨页排序要有稳定 tie-breaker;需要一致快照时结合 PIT(Point in Time)与目标版本能力;Scroll/PIT 都需清理上下文并控制保留时间。

定位慢查询时先检查 query profile、命中数、聚合基数、分片数、缓存、segment 数与 merge/refresh 压力;不要仅通过增加分片或副本解决查询慢。

4.3.3 向量检索索引:HNSW 与 IVFFlat 的构建、召回和内存取舍

向量检索的近似索引通常用速度和资源换取一定的召回率。HNSW 通过多层邻近图进行导航;IVFFlat 先将向量划分到若干聚类列表,查询时只探测部分列表。二者的构建流程、内存、查询延迟和过滤后的有效召回不同,必须以目标语料、维度、过滤条件与召回目标做实验。

表 137:HNSW 与 IVFFlat 的参数、代价与选择
维度HNSWIVFFlat
索引结构多层近邻图,从高层快速导航到底层候选邻居。粗聚类/倒排列表;将向量分配到 lists,查询探测其中一部分。
构建与内存通常构建较慢、索引内存较高;参数 m、ef_construction 会影响图规模、构建成本与质量。通常建索引更快、内存开销较低;需要先有数据以训练分区,列表数与数据分布影响效果。
查询与召回ef_search 等参数提高搜索广度,往往提升召回并增加延迟/CPU。probes 越多,检索列表越多,通常提高召回但增加查询成本。
过滤与多租户近似扫描后的过滤可能使返回结果不足,需要迭代扫描、合理的预过滤/分区和权限约束。同样需评估过滤选择性与分桶分布;不能只看未过滤基准的 Recall@K。
验证方法对真实查询集计算 Recall@K、P95/P99、内存、构建时间和更新开销。先跑精确检索基线,再对照不同 lists/probes 组合;评估增量写入、重建窗口和数据漂移。

HNSW 不是“跳表”;它是多层图导航结构。索引参数与名称会随向量数据库实现不同而不同,表中的参数以 pgvector 为代表,其他产品应查对应版本文档。

4.4 ORM 与 SQL 执行层(MyBatis / MyBatis-Plus)

表 29:MyBatis 核心机制与资深岗位追问落点

技术项 需掌握到的深度
执行链路 SqlSession \(\to\) Executor \(\to\) StatementHandler \(\to\) ParameterHandler \(\to\) ResultSetHandler;Mapper 接口通过 MapperProxy 动态代理绑定
#{} vs ${} #{} 走 JDBC PreparedStatement 参数化预编译占位符,防御 SQL 注入;${} 是单纯字符串拼接,仅限动态表名/列名且必须强制白名单过滤
一级与二级缓存 一级缓存为 SqlSession 级别,任意更新操作均清空;二级缓存为 Mapper 命名空间级别,在多表关联查询或分布式环境下极易读到脏数据,生产环境通常强制禁用
批量插入优化 BatchExecutor 只对增删改生效,遇到 SELECT 会强制刷盘;高吞吐批量插入推荐利用分批拼接多 VALUES SQL 或原生 JDBC Batch

4.4.1 JPA/Hibernate 与 MyBatis 的边界比较

《成神之路》明确包含 ORM、Hibernate 缓存与懒加载,并比较 Hibernate/iBatis/MyBatis。本节补充到现有 MyBatis 执行链专题之后,重点解释 ORM 的实体状态、缓存和查询副作用。

表 86:ORM 框架机制与选型边界

主题核心机制面试与生产落点
ORM 思想与对象状态JPA/Hibernate 将实体状态映射到关系数据;Persistence Context/Session 跟踪实体,事务提交/flush 时可能通过脏检查生成 SQL。区分瞬时、托管、游离、删除状态;flush 不等于 commit,SQL 发出时点也不一定是业务代码调用 save 的时点。
一级/二级缓存Hibernate 一级缓存通常以 Session/Persistence Context 为范围;二级缓存需配置 Provider 与实体缓存策略。MyBatis 一级缓存通常是 SqlSession 级,二级缓存以 Mapper namespace 为边界。缓存失效、事务隔离、多实例一致性与关联表更新要分别考虑;跨服务/分布式场景不要假设本地 ORM 缓存自动一致。
懒加载与 N+1懒加载可减少不必要查询,但在 Session 关闭后访问可能失败;遍历关联集合可能触发 N+1 SQL。用 fetch join、EntityGraph、批量抓取或 DTO 查询按场景解决;检查生成 SQL 与查询数量,避免一律把所有关联改成 eager。
MyBatis 的适用边界MyBatis 更显式地管理 SQL 与映射,适合复杂 SQL、报表、性能敏感场景;Hibernate/JPA 提供较强对象状态与关系映射抽象。选择取决于领域模型、查询复杂度、性能可预测性、团队经验与可观测性;不是 ORM 越自动就越高级。
事务与批量写入ORM 的批处理、flush/clear、JDBC batch 与数据库参数限制影响吞吐和内存;长 Session 会积累实体与快照。批量导入需分批、控制事务大小和持久化上下文;对关键路径检查 SQL、执行计划、锁持有时间及连接占用。

4.4.2 MyBatis 执行器、插件拦截点与缓存边界深挖

表 127:MyBatis 执行器、插件与缓存边界
组件职责追问边界
SqlSessionFactory / SqlSession工厂构建 Session;SqlSession 代表一次数据库交互会话,封装映射调用与事务操作。Spring 集成后常由事务同步管理实际 Session 生命周期;不要把“一个 Mapper 对象”等同于“一个数据库连接”。
ExecutorSimple 每次执行创建 Statement;Reuse 尝试复用 Statement;Batch 累积批量更新并在 flush/查询等边界执行。BatchExecutor 不会让所有操作自动批量化;获取更新结果、执行查询、异常或提交时都可能触发 flush,需在目标版本核实边界。
四类主要拦截对象MyBatis 插件可拦截 Executor、StatementHandler、ParameterHandler、ResultSetHandler 的指定方法。插件代理有顺序和递归包装影响;分页/租户插件必须验证 SQL 改写、参数映射、COUNT 查询和与其他插件的组合。
#{} vs ${}#{} 使用参数占位符;${} 将字符串插入 SQL 文本。表名/列名不能通过 JDBC 参数占位符传递时,仍需白名单映射;绝不能把任意用户输入直接放进 ${}。
一级/二级缓存默认一级缓存围绕 SqlSession;二级缓存以 Mapper namespace 为边界,需显式配置。一级缓存的脏读讨论必须区分同一 Session 内的事务/隔离语义;二级缓存跨 namespace、多表关联、外部写入与多实例同步可能不一致,除非能证明失效协议正确,不要默认启用。
JPA/Hibernate 的额外成本Persistence Context 追踪实体,flush 时脏检查并生成 SQL;懒加载可以延迟关联查询。N+1 应用 fetch join、EntityGraph、批量抓取等诊断;OSIV 可能使 Session 与数据库资源生命周期延伸到 Web 响应阶段,尤其流式输出/远程调用时要检查连接池占用。

5. 架构设计与方法论栈

5.1 DDD 栈

表 17:DDD 栈复习条目

层级 技术项与核心认知
战略设计 限界上下文(Bounded Context)划分、统一语言、上下文映射(防腐层 ACL、共享内核、客户-供应商)
战术设计 聚合根(Aggregate Root,维护一致性边界)、实体(唯一标识)、值对象(不可变)、领域事件
架构演进 六边形整洁架构、CQRS 读写分离模型、Event Sourcing 事件溯源

5.1.1 DDD 战略设计、战术模型与架构依赖方向

表 128:DDD 战略/战术模型与架构依赖方向
层次核心概念落地规则与反模式
战略设计统一语言、限界上下文、上下文映射、共享内核、客户-供应商、防腐层(ACL)。上下文按业务语言、不变量、模型变化原因与团队责任边界划分;不要仅按数据库表或技术层切微服务。
战术设计实体、值对象、聚合根、领域服务、仓储、领域事件。聚合根维护局部一致性边界;事务内只修改聚合能保证的不变量;跨聚合协作用领域事件/Saga 等表达最终一致,不要把整个系统建成巨大聚合。
Repository vs DAORepository 在领域语言中表达聚合的持久化集合语义;DAO 更偏数据访问与 SQL 封装。二者可以由同一实现承载,但接口语义不同。领域层不应泄漏 JDBC ResultSet、ORM Session 或数据库分页细节。
六边形 / Onion / Clean ArchitecturePorts & Adapters、领域核心、应用用例与外部基础设施分层。依赖箭头指向稳定的内层;外部数据库、消息和 Web 框架通过端口适配。抽象不应为了抽象而抽象,应由独立业务规则/测试替换需求驱动。

面试深问:一个规则放在 Entity、Domain Service 还是 Application Service?先看规则是否围绕单个实体/聚合不变量、是否涉及多个领域对象、是否属于用例编排。不要把所有逻辑塞进 Service,也不要为了“充血”把 I/O 与框架生命周期写进领域实体。

5.2 高并发高可用与分布式可靠性保障

表 18:分布式组件栈复习条目

技术项 可选方案与权衡
限流 单机令牌桶(Guava)、Sentinel 滑动窗口、Redis+Lua 分布式流控
熔断降级 Resilience4j、Sentinel;线程池隔离 vs 信号量隔离
事务与共识 Seata AT/TCC/Saga、本地消息表(Outbox)、Raft 强 Leader 复制
跨机房多活 单元化架构(Cell-based Architecture)、流量闭环、回环复制阻断、多机房冲突裁决

表 37:单机 vs 分布式限流方案对比

方案 实现方式 优点 缺点 适用场景
Guava RateLimiter 单机令牌桶,synchronized 简单直观、允许突发 仅限单机,高并发竞争大 单实例防刷、简单后台调用
Sentinel 单机流控 滑动窗口 + LongAdder 高吞吐、极低延迟开销 仅限单机 微服务单机保护基线
Sentinel 集群流控 Token Server 统一配额 全局统一流控 依赖独立 Token Server 运维 微服务网关全局限流
Redis + Lua 集中式原子脚本计数 配额跨实例共享 Redis 容易成为单点与延迟瓶颈 中小型分布式接口防刷

5.2.1 分布式事务四模式选型表(表 19)

模式 一致性 业务侵入 关键机制与权衡 适用场景
XA 强一致 无 传统 2PC,资源全程锁定,吞吐量极低 跨表跨库单体金融级强一致要求
AT (Seata) 最终一致 低 自动生成反向补偿 SQL,释放本地锁;但一阶段提交前必须获取 TC 全局锁 常规关系型数据库微服务
TCC 最终一致 高 业务显式实现 Try(预留)、Confirm(确认)、Cancel(释放),需防空回滚与悬挂 核心高并发资金流转链路
SAGA 最终一致 高 长事务事件链逆向补偿,适合异构外部长流程 跨外部异构系统流程编排
Seata 四模式落地失败矩阵
表 129:Seata 四模式失败场景与工程约束
模式需要验证的失败场景设计底线
AT全局锁冲突、undo log 不可用、脏写保护、SQL 不支持/复杂 SQL、事务超时。适用于受支持的关系库 SQL 与明确的代理/元数据条件;补偿依赖前后镜像与反向 SQL,不等同于任意业务补偿。检查 TC/Server 可用性、全局锁竞争与回滚恢复。
TCCTry 后 Confirm/Cancel 超时;空回滚;悬挂;同一 Confirm/Cancel 重复抵达。每个参与资源要有状态表或等价幂等状态;Confirm/Cancel 可重入;Cancel 不能覆盖已 Confirm 的成功结果。
Saga长事务中途失败、补偿失败、业务状态已被后续流程修改。补偿动作本身必须幂等、可重试并保留审计;明确哪些动作无法真正反向撤销,需用补偿业务动作而非“恢复原值”。
XA/2PC协调者/资源管理器故障、prepared 状态持锁、网络分区与恢复。一致性更强但可用性/锁持有时间代价明显;根据资源管理器支持、恢复流程和业务吞吐验证,不把 XA 当成无成本的跨微服务事务。

5.2.1.1 表 19 之外的两个轻量工程方案

  • 本地消息表(Outbox):业务数据与消息记录在同一个本地数据库事务中写入,通过定时任务或 CDC 异步投递到 MQ,解耦服务且无需引入重型事务框架。
  • 最大努力通知:适用于支付回调等场景,通过带梯度的重试策略通知下游,下游提供主动对账反查接口兜底。

5.2.2 共识算法谱系速查(表 30)

算法 解决问题 代价/限制 典型系统
Paxos 单值共识理论基石 工程实现极其复杂;多轮交互延迟高 Google Chubby 理论基础
Multi-Paxos 稳定 Leader 摊薄多轮协商 Leader 恢复过程复杂 分布式数据库元数据
Raft 强 Leader + 日志连续性 Leader 为单点性能瓶颈 etcd、Nacos JRaft、Kafka KRaft
ZAB 保持主备顺序一致性 与 Raft 类似,状态机紧耦合 ZooKeeper
Gossip 去中心化节点状态传播 仅保证最终一致,收敛随规模增长 Redis Cluster、Consul
5.2.2.1 Paxos、Raft 与 ZAB:选主、日志与安全性要点
  • Paxos:理解 proposer/acceptor/learner 与 prepare/promise/accept 交互;Multi-Paxos 可在稳定领导者条件下摊薄重复选主成本。它解决共识问题,不等于自动提供数据库事务或任意线性一致 API。
  • Raft:围绕 term、Leader Election、日志复制、commitIndex/lastApplied 理解安全性;多数派复制与日志匹配属性是核心。领导者变化后,不能把“日志已发送给某个副本”等同于“已提交”。
  • ZAB:面向 ZooKeeper 的原子广播与崩溃恢复,包含 epoch/ZXID 等概念;与 Raft 解决的问题相近,但具体选举、恢复和提交流程不同,不能把两个协议的状态机细节混写。
  • 复习方法:用同一故障时序比较:Leader 在发出日志后、收到多数派前崩溃;网络分区导致双候选;旧 Leader 恢复;少数派节点落后如何追日志。先回答安全性,再回答可用性和恢复时间。

5.2.3 业务幂等性深度设计方案

  1. 客户端在发起请求前生成全局唯一的 idempotency-key 并随 Header 传递;
  2. 服务端在网关或业务前置过滤器校验幂等键;
  3. 原子防重防穿透机制:严禁仅依赖 Redis SETNX 做唯一防线。Redis 仅用于拦截毫秒级并发重复点击;真正的防重必须依托数据库唯一索引约束;
  4. 将幂等记录写入与业务更新置于同一本地事务;
  5. 保存执行结果,重复请求直接返回历史快照结果或返回 409 Conflict;
  6. 结合合理的 TTL 过期清理策略治理历史幂等记录。
5.2.3.1 多层幂等防线:业务键、状态机与版本 CAS
  1. 传输层请求键:客户端生成唯一 Idempotency-Key,定义作用域、过期时间、并发相同键时的响应和结果缓存。
  2. 数据库最终约束:在业务表或幂等表上建立业务唯一索引;将防重记录、业务变更和返回结果快照置于合适的本地事务中。
  3. 状态机条件:使用“当前状态必须为 X”或版本号 CAS 的条件更新,拒绝过期/重复转换。
  4. 外部副作用:MQ 消费端用业务事件 ID + 唯一约束/Inbox,外部支付/配送等依赖对方幂等键或查询对账;不能只靠 Redis SETNX。
  5. 冲突响应:区分同键同参数、同键不同参数、处理中与失败可重试状态;对于已成功请求应返回保存的原结果或明确冲突语义。

5.2.4 重试机制、退避算法与重试风暴治理

  • 重试风暴根因:当下游微服务因过载变慢,上游超时盲目重试会将流量放大数倍,形成雪崩正反馈。
  • 治理规范:
    1. 仅对幂等操作且明确为偶发网络抖动的异常重试,业务失败(如余额不足)绝不重试;
    2. 采用指数退避(Exponential Backoff)配合随机抖动(Jitter)打散脉冲流量;
    3. 全链路纳入重试预算(Retry Budget):根据服务 SLO、错误预算、下游剩余容量和实测基线设定阈值;可用 10% 作为某些系统的初始试验值,但它不是通用标准。超预算时优先限制额外重试、快速失败或按策略降级,不应不加区分地对所有流量直接熔断。

5.2.5 分布式定时任务与状态流转治理

  • 设计解耦:调度平台(XXL-Job / ShedLock)仅负责触发与租约协调,严禁承载业务逻辑;任务执行器负责实际运算。
  • 防重与断点续跑:任务执行前必须检查业务状态机;长任务必须设计为分片批处理并保存游标进度,支持节点崩溃重启后断点续跑。
5.2.5.1 分布式调度:分片、漏调度、重叠与补跑策略
  • 调度器与执行器分离:调度层负责任务触发、路由、租约/选主和状态观察;执行器负责业务计算。任务状态必须可持久化查询,不能只存在进程内存。
  • 任务语义:明确 at-most-once、at-least-once 或近似语义;宕机恢复时是否补跑、跳过错过的触发、合并连续触发,需要按业务选择。
  • 分片与广播:分片任务有稳定分片键和幂等游标,节点缩容后能重新分配;广播任务要避免每个节点重复执行不可重复副作用。
  • 防重叠:短任务可用租约/分布式锁加 fencing token 或数据库唯一任务实例;长任务支持心跳、超时接管、断点续跑和人工恢复。
  • 框架对照:XXL-Job、Elastic-Job、Quartz 集群、Spring Scheduler/ShedLock 的能力不同;按目标版本核对注册发现、选主、失败重试、分片广播和运维 UI,不把框架自带触发器当成业务幂等保证。

5.2.6 分布式 ID 与业务流水号选型决策(表 56)

方案 优势 痛点与风险 适用场景
Snowflake (雪花算法) 趋势递增、高性能、不依赖外部组件 强依赖系统时钟,NTP 时钟回拨导致重复 ID 或宕机 大多数分布式系统内部主键
号段模式 (Leaf / Tinyid) 每次从 DB 批量取号段内存自增,抗压高 依赖集中式数据库可用性,ID 严格连续递增可能泄露商业机密 订单号、账单号、核心业务主键
业务复合单号 业务语义清晰(如:业务前缀+时间戳+用户哈希+序列) 生成逻辑复杂,需要兼顾唯一性与并发防重 面向用户的订单编号、支付流水号
5.2.6.1 Snowflake 时钟回拨与 Leaf 号段双 Buffer
  • Snowflake 时间回拨:发现当前时间小于上次时间时,不能继续无条件拼接时间戳。常见处理包括短暂等待小幅回拨、拒绝生成并告警、使用备用 worker/epoch 策略或切换号段方案;策略须保证同一 worker/时间段不复用序列空间。
  • WorkerId 唯一性:实例重启、自动扩缩容、网络分区和租约失效可能导致两个进程使用相同 WorkerId;分配需要租约/持久化登记和 fencing/代际机制,而不只是启动时随机取值。
  • Leaf 号段模式:数据库按批获取号段后本地递增;双 Buffer 可在使用当前号段时异步申请下一号段,降低请求路径延迟。要验证预取失败、切换边界、进程崩溃后的号段空洞、数据库主从故障和机器时间变化。
  • 业务流水号:唯一、趋势递增、可排序、不可猜测与连续性是不同要求;面向用户的编号不应意外暴露交易量或敏感业务规模。

5.2.7 分布式状态机建模与异常补偿机制

  • 显式状态机设计:针对订单、支付等业务必须明确定义有限状态机(FSM)。状态更新强制携带前置状态条件:
UPDATE orders SET status = 'PAID' WHERE order_id = :id AND status = 'UNPAID';
  • 异常对账补偿:针对超时未决状态,后台异步巡检对账任务定期捞取未终态记录,主动向第三方渠道查询反哺,必要时转入人工审核工单池。
5.2.7.1 分布式状态机与补偿闭环

状态机应显式列出状态、合法事件、前置条件、状态迁移、超时规则、重试规则、补偿动作与人工介入条件。更新状态用条件 SQL 或版本号 CAS 保证并发下只发生合法迁移。对于“处理中”超时状态,后台对账需要查询权威外部状态,而不是直接把超时等同于失败;补偿失败要转入可观测的重试队列和人工工单,保留触发原因、请求/响应摘要、尝试次数及责任人。

5.2.8 异地多活单元化(Cell-based)架构与数据冲突裁决

单机房架构存在物理可用性上限。大型互联网金融与电商系统必须走向单元化多活(Cell-based Architecture)。核心考察点不在于部署多套系统,而在于流量路由闭环与跨地域数据防回环同步与冲突裁决。

表 60:单元化多活关键设计与冲突裁决机制

架构维度 核心机制与工程实现 面试追问与失分点
单元化路由闭环 按用户 ID 取模或哈希,在入口 DNS / 七层网关层将流量分发至对应单元(Unit)。单元内部尽量由“Web \(\to\) 微服务 \(\to\) 数据库/缓存”形成自包含闭环,避免把同步跨地域 RPC 放在核心请求链路。跨地域调用并非一律禁止;全局数据、控制面或冲突裁决等场景如确有需要,应显式设计超时预算、重试上限、降级、隔离与一致性策略。 必须明确区分单元化数据(如个人订单、账单,可按用户分片闭环)与全局/中心数据(如商品总库存、资金总账,必须集中在中心单元或采用分布式强共识数据库同步)
跨单元防回环死循环同步 A 机房写入的数据通过 CDC(如 Canal / Otter / DRS)同步到 B 机房,B 机房回放写入后又会生成新的 Binlog。如果不加控制,B 机房的 CDC 会把该数据重新同步回 A 机房,形成无限死循环风暴 防回环方案:在数据同步写入目标库时,必须向 Session 会话变量或 Binlog 注入特殊的事务标记(Server-ID 过滤或自定义标记 origin_dc)。CDC 采集端若发现数据来源就是当前同步程序写入的,直接丢弃过滤,阻断回环
数据冲突裁决(Conflict Resolution) 在极端网络分区或故障逃生切流瞬间,可能发生同一主键在两个机房并发写入,产生数据冲突 ① LWW(Last-Write-Wins):依赖高精度时钟源(如 Google TrueTime 或 HLC 混合逻辑时钟),时间戳晚的覆盖早的;② 业务状态机裁决:如果已经是“终态”(如已支付),则“取消”操作无效;③ CRDT(无冲突复制数据类型):用于计数器或集合类场景的自动数学合并;④ 事后人工对账与补偿(金融底线)

5.2.8.1 单元封闭率、跨机房数据仲裁与 CRDT 边界
  • 单元封闭率:统计请求主路径中不跨单元的比例、跨单元调用次数和跨单元数据写入率;高封闭率能降低跨地域依赖,但无法替代全局一致性设计。
  • 数据防回环:CDC 事件携带来源单元、事件 ID、版本/因果标记;目标写入应保留可检索的来源元数据,过滤回流事件并做去重。过滤规则要经故障演练验证,避免错误过滤合法变更。
  • 脑裂与仲裁:区分控制平面选主与业务数据冲突。LWW 用时间戳胜者可能丢失并发更新且依赖时钟质量;CRDT 只适用于能满足其合并代数条件的数据类型,并非任意订单、余额、库存都可自动冲突合并。
  • 资金/库存类数据:通常需要唯一权威写入、强约束或显式预留/补偿,不应以“多活 + LWW”作为资金正确性方案。

5.2.9 一致性哈希、Gossip 与 N/W/R 读写法定人数

上传 PDF 第 20 章(目录标注页 225–231)把 Paxos、ZAB、Raft、N/W/R、Gossip 和一致性哈希并列。当前报告已有共识算法谱系,但还应区分“决定一致的状态机日志”与“数据副本读写/节点成员传播”的问题。

表 100:共识、复制与分片三类问题的边界

机制解决的问题关键边界
Paxos / Raft / ZAB在故障与网络延迟下,协调参与者就日志/状态更新顺序达成共识。需要满足协议规定的多数派与安全性条件;不同协议的消息、恢复和日志提交规则不等价。
N/W/RN 为副本数,W 为写入确认副本数,R 为读需要接触的副本数。在常见 quorum 复制模型中,若 R+W>N,可保证读写集合有交集;但交集本身不自动保证线性一致性,仍取决于版本比较、写冲突解决、修复与系统协议。
Gossip节点间传播成员状态/心跳/元数据,最终使状态在网络恢复后逐步收敛。一般提供最终收敛,不等同于强一致共识;需考虑陈旧信息、分区恢复、误判故障和传播成本。
一致性哈希与虚拟节点将数据 key 与节点映射到哈希环;节点变更时主要迁移相邻区间数据。虚拟节点改善分布均匀性;扩缩容仍需迁移、限流、双读/校验与失败重试。哈希分布不能替代副本一致性和故障恢复。
选型时的提问要解决的是选主/提交顺序、可调读写一致性、集群成员传播,还是数据分片/缓存亲和?先确定问题类型,再比较协议;不要把一致性哈希称作“共识算法”,也不要把 Gossip 的最终一致说成强一致。

5.2.10 高可用机制协同:限流、隔离、降级与恢复(表 113)

JavaGuide 的高可用专题将 SLA、限流、熔断、重试、幂等、冗余和故障演练放在同一套系统设计问题里。这里把常见机制整理成“入口保护—依赖保护—业务兜底—恢复验证”的工程闭环。来源:JavaGuide 高可用系统设计面试题。

机制解决什么问题选型/关键边界要观测什么
固定窗口简单控制单位时间请求量。实现简单,但窗口边界可能在极短时间内形成双倍突发。放行/拒绝量、窗口边界突发。
滑动窗口更平滑地统计时间窗口内流量。比固定窗口准确;实现与存储成本取决于按桶近似还是逐请求记录。当前窗口流量、限流比例、时间桶误差。
令牌桶限制平均速率并允许有上限的短时突发。桶容量决定突发额度;单机令牌桶不能天然提供跨实例全局配额。令牌耗尽、突发流量、排队延迟。
漏桶 / 排队整形以近似固定的出队速率平滑下游流量。队列必须有界;无限排队只是把过载变成更长延迟和内存风险。队列长度、等待时间、丢弃和过期任务数量。
舱壁隔离限制单个下游或业务故障影响全服务。线程池隔离开销更高但边界更清晰;信号量隔离轻量但不隔离调用线程本身。活跃线程、队列深度、拒绝数、隔离池利用率。
超时、重试与熔断释放等待资源、处理瞬态故障、阻断持续异常依赖。重试必须限次、退避加 Jitter、预算受控,且写操作应幂等;熔断与限流不是一回事。首次成功率、重试率、超时、熔断状态、下游错误率。
降级与故障恢复保护核心链路并缩短恢复时间。预先定义核心/非核心功能、人工开关、回滚、补偿与恢复条件;避免 Fallback 再调用同一故障依赖。SLO、错误预算、恢复耗时、数据修复进度。
  • 面试时区分 SLA(对外服务承诺)、SLI(用于衡量的指标)和 SLO(目标值);先说明服务级目标,再据此设计超时、重试和故障预算。
  • 可用性不等于“部署多份”。还需要消除单点、容量验证、数据库/缓存/MQ 依赖保护、备份恢复演练、监控告警和可执行的止损预案。
  • 恢复演练的验证指标包括故障检测时间、切换时间、恢复后数据差异、RPO/RTO 是否达标,以及恢复流量是否导致二次过载。

5.2.11 TCC 空回滚、悬挂与幂等:分支控制表落地范式

TCC 的 Try/Confirm/Cancel 是业务级协议,不能仅靠“Cancel 方法写成幂等”解决所有竞态。空回滚发生于 Try 未成功执行或请求超时未落库,但协调器已发来 Cancel;悬挂发生于 Cancel 先到并结束后,迟到的 Try 仍试图预留资源。持久化的分支状态与唯一约束可以将这些边界显式化。

表 138:TCC 分支状态与空回滚/悬挂防线
场景推荐状态/事务处理必须验证的边界
Try 正常到达以 (xid, branch_id) 为幂等键,在本地事务中插入/更新 TRYING 或 TRIED 状态,同时预留业务资源。Try 重试不得重复扣减/预占;唯一约束冲突要读取已有状态而非重复执行业务。
Cancel 先于 Try(空回滚/悬挂)若分支记录不存在,Cancel 在一个本地事务中插入 CANCELED/TOMBSTONE 标记;同一事务键下的迟到 Try 先查标记并拒绝预留。必须通过唯一索引和事务隔离处理并发插入竞争;不能只依赖应用层“先查再插”。
Try 已预留,收到 Cancel用条件状态更新确认当前状态仍可取消,释放资源并转换为 CANCELED;重复 Cancel 读到终态后返回幂等结果。释放动作必须是可重试且幂等的;释放与状态更新应在同一本地事务中尽量原子化。
Confirm 重复/乱序只允许从正确的已预留状态转为 CONFIRMED;终态重复请求返回同一业务结果。设置唯一键、状态机条件更新、处理超时重试;记录 xid/branchId、调用次数、耗时与失败分类。
-- 示意结构;字段、长度和索引需按事务协调器及业务数据库调整
CREATE TABLE tcc_branch_guard (
  xid        VARCHAR(128) NOT NULL,
  branch_id  VARCHAR(128) NOT NULL,
  state      VARCHAR(16)  NOT NULL,
  updated_at TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP
                          ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (xid, branch_id)
);

-- 关键原则:状态迁移使用带旧状态条件的 UPDATE,
-- 并在同一本地事务中完成资源预留/释放与状态记录。

这是工程模式示意,不是可直接复制到所有 Seata 版本的完整实现。实际接入要确认分支注册/回调时序、事务 ID 唯一性、异常补偿和历史记录清理策略。

5.2.12 Seata AT 脏写、全局锁绕过与补偿修复闭环

Seata AT 在受代理的数据源操作中记录 undo_log,并进行全局锁相关检查。若某个外部写入路径绕过 Seata 代理/全局锁直接修改同一行,AT 回滚时可能发现当前镜像与回滚所需镜像不一致,导致回滚失败或全局事务长期阻塞。这类故障不能通过随意删锁或删 undo_log 解决。

表 139:Seata AT 回滚冲突的证据与安全处置
步骤检查与动作禁止事项
止血与确认范围暂停或限制绕过代理的写入路径;确认业务是否仍有并发修改、受影响的全局事务和分支事务。不要在根因未明时直接批量重放或重启后假设数据自动一致。
收集证据记录 XID、Branch ID、全局/分支状态、相关 undo_log、before/current image、SQL 与时间线,核对是否存在外部 SQL、人工脚本或非 Seata 应用写同一行。不要直接删除 global lock、branch record 或 undo_log 来“解除阻塞”。
决定恢复路径若可安全重试,优先按协调器状态和框架恢复流程继续;若镜像冲突影响业务正确性,先冻结该数据域写入并开展数据对账。不要对同一行盲目执行回滚 SQL;可能覆盖后续有效业务写入。
人工/自动修复闭环由业务负责人审批补偿/修复 SQL;建立前后值审计、幂等执行键、修复后校验、复盘与告警。必要时通过正式运维流程修复事务状态。不得无审计地人工篡改事务状态;修复要可重复验证、可追溯和可回滚。
预防统一数据源代理、禁止绕过事务代理修改托管数据;建立写路径治理、回滚冲突告警与演练。把“技术上有 AT”当作数据库所有写路径都自动加入全局锁保护。

Seata 版本、数据库类型和具体模式会影响回滚细节。排障时以目标版本官方文档、事务表状态和实际日志为准;业务补偿应优先保持可审计,而不是依赖手工清理元数据。

5.2.13 Cell-based 单元化中的全局共享数据与单写策略

单元化将按用户、租户或业务路由键可分片的数据尽量封闭在一个 Cell 内,以缩小故障爆炸半径。但商品元数据、全局权限配置、账户目录等无法自然按业务键隔离的共享数据,会引入跨单元复制与仲裁问题。架构上必须明确数据的权威写单元、复制方向、版本语义与故障切主协议。

表 140:单元化中分片数据与全局共享数据的边界
数据类型/问题推荐策略风险与校验
可按路由键封闭的数据请求由路由键稳定落到主 Cell;本单元拥有数据写入与事务处理权,尽量避免跨 Cell 同步调用。指标看单元封闭率、跨单元调用比例、故障时局部可用性;缓存、定时任务和异步消费也要遵守单元路由。
全局共享、冲突代价高的数据定义权威写单元或独立的全局元数据服务;其他 Cell 只读异步复制,携带来源、版本/epoch 与事件 ID。主写切换需有租约/仲裁和 fencing epoch,避免旧主恢复后继续写;复制消费者需幂等、防回环并能对账。
全局唯一 ID使用具备明确分配边界的独立发号器、分片号段或可证明不重叠的分配空间。故障切主时确认 ID 段不会重叠;不能只依赖“机器时间不冲突”或靠最后写入者获胜保证唯一性。
可合并的多写数据只有当业务操作满足相应合并语义时,才考虑 CRDT 或冲突无损合并策略。金额、库存扣减、权限撤销等强业务不变量不能默认用 LWW;若采用 LWW,需明确时钟/版本排序、丢更新接受度与审计。
跨机房分区与恢复设计单元自治能力、主写仲裁、异步复制延迟阈值、过载降级、故障恢复与数据对账 Runbook。演练网络分区、旧主复活、复制回环、消息重复和恢复期间的双写;同步复制越强越可能牺牲分区期间可用性。

多活不是“每个机房都可以写同一份数据”。关键是逐类定义写权、冲突语义、单元封闭率和故障时的业务降级方式。CRDT 只适用于其数学合并规则与业务语义匹配的数据类型。

5.2.14 CQRS / Event Sourcing:投影延迟、读己之写与重放对账

CQRS 将命令写模型与查询读模型分离,Event Sourcing 进一步把事件序列作为业务状态演进的事实来源。读模型投影通常异步生成,因此必然存在 Projection Lag;“命令已成功”不代表所有查询视图已经看到新状态。架构要为读己之写、重放、事件版本演进和投影修复定义显式协议。

表 141:CQRS/事件溯源的读一致性与重放策略
问题推荐方案工程验证点
命令成功但查询暂未更新命令响应返回已提交的业务结果/聚合版本;页面可做乐观更新,后续由读模型版本追平。返回的是命令事实还是最终查询视图需在 API 契约中明确;UI 乐观状态要能在失败时回滚。
Read-Your-Writes给用户会话回传版本号/事件位置,查询端识别该版本尚未投影时,短暂等待、读写同源或回退到权威写模型。等待必须有超时和容量上限;不能让查询线程无限等待投影,也不能向客户端暴露不受控内部 offset。
事件发布可靠性用本地事务 + Outbox/CDC 保证业务状态与事件记录不发生无法恢复的双写缺口。消费者按事件 ID/聚合版本幂等处理;重复事件不会重复产生副作用。
投影重放与修复投影可从检查点重放;新投影版本使用独立读模型或影子表验证,再切换读流量。记录消费位点、事件 schema 版本、失败事件与 DLQ;对账聚合业务总量、金额/库存不变量及随机抽样明细。
事件模式演进事件需有显式 schema/version 和向后兼容策略,必要时使用 upcaster 或新事件类型。回放整个历史数据集,不能只通过最新事件的单元测试;保留快照与事件日志时要规划存储、脱敏和保留期限。

“Exactly-once”通常是系统局部或处理语义,不会自动跨越数据库、事件代理、外部 HTTP 和邮件等副作用。端到端可靠性仍依赖幂等键、Outbox/Inbox、状态机、重放和对账。

5.3 架构演进与设计题场景栈

  • 四段式答题框架:
    1. 需求澄清:明确 QPS、读写比、数据规模、可用性与延迟 SLA。
    2. 容量估算:信封背面计算(如:1000 万日增 \(\times\) 500B \(\approx\) 5GB/天,推算存储与峰值 QPS)。
    3. 架构与数据流:画出链路、分层模型、存储选型。
    4. 瓶颈、容灾与演进:讨论降级、熔断、多活与演进路径。

5.3.1 绞杀者模式的落地四问

  1. 双写一致性:新老表写入如何防丢?(CDC 增量捕获比应用双写更安全)。
  2. 数据所有权:过渡期明确单向数据源头。
  3. 流量灰度切分:按租户/用户维度从小比例向 100% 渐进切换,随时具备一键回滚开关。
  4. 旧系统退役清单:设立明确的下线指标与 Checklist,避免两套系统长期双轨消耗成本。
5.3.1.1 单体到微服务的绞杀者迁移执行单
  1. 按业务能力确定边界与单一数据所有者,先建立 API/事件契约与观测基线。
  2. 优先把读路径切到新服务或建立 CDC 镜像,在影子流量下对比结果;敏感写路径不要无控制地双写。
  3. 灰度以租户/用户/业务键分流,明确每阶段成功率、差异率、延迟和回滚阈值;准备一键回退流量与数据修复方案。
  4. 数据割接后执行对账、补偿和旧链路冻结;在指标达标且观察窗结束后才移除旧代码/表。

5.3.2 API 设计与版本管理(表 52)

  • RESTful 设计原则:资源使用名词复数(/api/v1/orders);正确使用 HTTP 谓词;状态码语义精准;全局统一响应体 {code, message, data, traceId}。
  • 版本管理对比:URI 路径版本(简单直观、推荐)、Header 版本(灵活性高、调试稍复杂)。

5.3.2.1 API/数据库兼容演进:Expand–Migrate–Contract
  • Expand:先新增可选字段、兼容列或新接口,老客户端仍能运行;保证默认值和写入者行为明确。
  • Migrate:部署兼容版本,回填数据,双读/单写或按阶段切换;监控新旧字段差异与消费者版本。
  • Contract:确认所有旧消费者已迁移、回滚窗口关闭且数据校验通过后,才删除旧字段/接口。
  • 兼容检查:不仅比较 JSON 字段是否存在,还要检查语义、默认值、分页/排序稳定性、错误码、幂等键与重试行为;对破坏性变更设置弃用通知和迁移窗口。

5.3.3 系统设计场景题案例库:订单、秒杀、短链与大数据导出(表 114)

JavaGuide 的系统设计专题强调先澄清需求和质量目标,再围绕数据模型、核心链路、失败处理与验证方案设计;高性能专题也使用订单系统作为综合案例。这里补充一组可复用的面试案例框架。系统设计与场景题 · 高性能系统。

场景主链路与关键设计面试必答的失败边界验证指标
高并发订单系统入口限流、幂等创建订单、数据库条件更新、消息异步处理通知/积分等非核心动作。订单状态机、支付回调重复、库存扣减竞争、Outbox/CDC、超时后的结果查询。下单成功率、库存差异、P99、数据库锁等待、消息积压。
秒杀与限购活动预热、CDN、验证码/限购、原子库存预扣、有界排队、异步建单。防超卖、防重复下单、Redis 与 DB 状态对账、消息失败补偿、队列满时拒绝策略。有效请求比例、超卖数、排队时长、下单转化、库存回滚数。
短链服务短码生成、唯一索引、读缓存、跳转、过期与封禁、统计异步化。哈希碰撞、热点短码、恶意链接、短码枚举、301/302 对缓存和统计的影响。跳转成功率、P99、缓存命中、创建冲突、滥用拦截量。
大数据导出异步任务、稳定游标分页、流式写文件、对象存储、短期签名下载 URL。快照一致性、内存与数据库连接占用、任务幂等、取消/重试、租户和字段脱敏。任务时长、失败率、峰值内存、数据库负载、下载成功率。
不停机数据库迁移兼容 Schema、全量分批回填、CDC 增量同步、校验、影子读、分批切流。双写不一致、增量回放顺序、回滚窗口、旧新系统的权威来源切换。数据差异、CDC Lag、切流错误率、回滚耗时。

统一答题流程:需求澄清 → 规模与容量估算 → 数据模型/状态机 → 核心读写链路 → 并发与一致性 → 过载及故障处理 → 监控、压测、灰度和回滚。不要为了显得复杂而默认引入 Redis、MQ、ES、分库分表或微服务;组件应由瓶颈和业务约束驱动。


5.4 架构决策记录(ADR)与技术治理

  • 架构决策记录(ADR)要素:上下文背景、技术约束、被否决的备选方案、最终决策理由、引入的潜在风险与妥协、后续效果验证路径。
  • 技术债治理:建立技术债健康度看板,将版本升级、框架解耦、慢 SQL 治理等非功能性工作纳入产品迭代排期。15%~20% 可作为部分团队的初始讨论值,而非通用硬指标;应结合线上风险、合规要求、交付周期和技术债利息定期调整资源比例。

6. 云原生、DevOps、大数据与 AI 栈

6.1 云原生与可观测性栈

表 20:云原生栈复习条目

子域 技术项
容器化与高级调度 Docker 多阶段构建、Distroless;K8s Ingress、NetworkPolicy、HPA、PDB、ResourceQuota
排障对齐 OOMKilled 内存对齐公式、ActiveProcessorCount 与 CPU limit 对齐
可观测性 Prometheus+Grafana 指标体系、OTel、eBPF 内核态动态观测

6.1.1 Kubernetes 高级特性与生产排障

  • OOMKilled 排查与堆外对齐公式: Exit Code 137 表示容器被 Linux 内核 cgroup OOM-Killer 发送 SIGKILL 强杀。Pod 内存配额对齐公式:

$\(\text{Container Limit} \ge \text{MaxHeap(-Xmx)} + \text{Metaspace} + \text{DirectMemory} + (\text{ThreadCount} \times 1\text{MB}) + \text{JIT CodeCache} + \text{安全留白}(20\%)\)$

  • ActiveProcessorCount 陷阱:JVM 在容器内必须正确感知 CPU limit,显式设置 -XX:ActiveProcessorCount=N,否则将按宿主机核数分配 GC 线程与 ForkJoinPool,引发灾难性线程上下文切换与 CPU throttling。
  • eBPF 与 Agent 分工:Java Agent 负责业务层方法级耗时剖析;eBPF 负责内核态 TCP 重传、网络丢包与调度延迟诊断,两者互补。

6.1.1.1 Kubernetes 故障证据链:OOMKilled、CrashLoopBackOff 与网络策略
  • OOMKilled / Exit 137:137 通常表示被 SIGKILL 终止,不能仅凭退出码断定是 cgroup OOM;检查 Pod lastState、Events、容器/节点内存、cgroup memory.events、内核日志与 JVM heap/Native/Direct/线程栈指标。
  • CrashLoopBackOff:先看 kubectl describe pod、上一次容器日志 kubectl logs --previous、探针失败与退出码,再区分应用启动失败、配置/密钥、依赖不可用、OOM 或 liveness 误杀。
  • Service / CNI:核对 EndpointSlice/Ready 状态、kube-proxy 的 iptables/IPVS 模式或集群实际数据面实现、NetworkPolicy、CNI 路由、MTU、DNS 和节点 conntrack。iptables vs IPVS 并非所有现代集群的唯一比较;eBPF 数据面也可能存在。
  • NetworkPolicy:只有在所用 CNI 支持并启用策略执行时才生效;检查 ingress/egress 两个方向及 DNS、健康检查和跨 namespace 访问。

6.1.2 Docker/容器内部机制:Namespaces、cgroups、镜像层与网络

上传 PDF 第 30 章(目录标注页 279–283)包含 SaaS/PaaS/IaaS、Docker、Namespaces、cgroups、网络隔离、UnionFS/存储驱动和 OpenStack。报告已有 Kubernetes 生产排障,本节补齐容器底层概念,重点关注 Java 服务为什么会在容器内发生 CPU/内存与宿主机认知不一致。

表 101:容器基础设施与 Java 服务运行边界

主题机制与 Java 生产问题的关联
NamespacePID、Mount、Network、IPC、UTS、User 等命名空间提供资源视图隔离。容器内进程号、网络接口、主机名与宿主机视角不同;排障时要区分容器 PID 与 host PID、容器网络和宿主网络。
cgroups 与资源限制限制/统计 CPU、内存、PIDs 等资源;容器的请求/限制影响调度与可用资源。内存限制覆盖堆外内存、线程栈、Metaspace、直接内存、代码缓存和本机分配;CPU quota 会造成 throttling,即使宿主机 CPU 看起来不满。
镜像层与 OverlayFS镜像通常由只读层组成,容器写入落在可写层;Union/Overlay 文件系统提供层叠视图。容器可写层不适合承载需要持久保留的数据;镜像层数、依赖缓存和大文件复制会影响构建时间与镜像体积。
网络与存储网络命名空间、veth/bridge/NAT/端口映射;Volume/Bind Mount 用于持久化或共享数据。区分进程监听地址、容器端口、宿主端口和 Service/Ingress;容器删除与挂载卷的生命周期不同。
SaaS/PaaS/IaaS按用户管理责任划分应用交付、托管运行平台与基础计算/网络/存储资源。用于解释团队负责的层级与故障边界;具体产品可能跨越多个抽象层,不要只按厂商营销名词分类。
6.1.2.1 cgroups、CPU 限额与容器安全落地

Namespaces 提供进程、挂载、网络等隔离视图;cgroups 限制与统计 CPU、内存和 I/O。容器不是独立内核,资源限制、权限、Capabilities、seccomp、AppArmor/SELinux 和宿主机共享内核共同决定安全边界。

  • CPU limit 导致 throttling 时,即使宿主机总体 CPU 看起来有空闲,容器也可能受到配额限制;结合 cpu.stat、throttled periods 与应用 P99 看。
  • 内存限制需要包含 heap、Metaspace、线程栈、Direct Buffer、JNI/native、页缓存等;仅设置 -Xmx 不足以保证容器不被 OOMKill。
  • 生产镜像优先非 root、只读根文件系统、最小 Capability、固定/扫描依赖、可信来源和及时补丁;写目录显式挂载临时卷。

6.1.3 日志门面、日志实现与 ELK/集中式日志治理

上传 PDF 第 10 章(目录标注页 169–170)罗列 SLF4J、Log4j、Logback 与 ELK。现代复习需要区分 API 门面、具体日志实现、采集/索引平台,并把日志作为可观测性证据链而不是单纯文本输出。

表 102:日志生态与生产治理

层面常见组件/能力面试与工程落点
门面与实现SLF4J 是日志 API 门面;Logback、Log4j 2 等是实现。历史 Log4j 1.x 不应与 Log4j 2 混同。避免多个实现同时进入 classpath;检查日志绑定冲突、依赖版本、配置文件加载优先级和容器环境差异。
日志结构与上下文结构化 JSON、MDC/Trace ID/Request ID、租户与业务流水号等上下文。跨线程/异步任务需要显式传播或清理上下文;不可把密码、Token、身份证件、支付敏感字段直接写入日志。
采集与检索Filebeat/Fluent Bit 等采集器、Logstash/处理管道、Elasticsearch/OpenSearch 与 Kibana/Grafana 等查询展示。日志平台的索引生命周期、保留期、采样、字段基数和存储成本都需要治理;平台不可用时应用日志不能无限占满磁盘。
异步与滚动异步 Appender/队列、按时间/大小滚动、压缩、保留和丢弃策略。异步队列满时应明确阻塞、丢弃或降级策略;日志 I/O 也会成为尾延迟与磁盘使用的瓶颈。
日志与指标/链路日志给事件细节,指标呈现聚合趋势,分布式追踪连接跨服务调用。Trace ID 可串起请求链路,但不要用高基数的请求 ID 作为指标标签;三个信号应有统一时间基线和关联字段。
6.1.3.1 异步日志队列、MDC 与 OpenTelemetry 统一观测
  • 日志门面:SLF4J 定义 API,Logback/Log4j2 等提供实现;排查依赖冲突时检查重复 binding/provider,避免桥接环造成循环依赖。
  • 异步日志:队列满时策略可能是阻塞、丢弃或回退到同步写;要根据日志等级/类别明确策略,观测队列深度、丢弃计数、磁盘延迟和滚动失败。
  • 关联上下文:MDC/traceId 需要在执行线程、异步任务与消息消费边界传播并在 finally 清理,避免线程池复用导致上下文污染;不要记录密码、Token、密钥或整段敏感请求体。
  • OpenTelemetry:统一 traces/metrics/logs 的语义与上下文关联;控制高基数标签、采样率与保留期,避免可观测成本和指标基数失控。

6.2 CI/CD、GitOps 与现代发布工程

表 46:GitOps 深入与现代发布模式对比

维度 传统 CI/CD 流水线 GitOps (ArgoCD / Flux)
真相源 状态分散在 Jenkins 脚本与集群中 Git 仓库为唯一声明式真相源
回滚机制 重新触发旧流水线构建部署 git revert 提交,控制器自动同步分钟级回滚
漂移检测 无法感知集群手动 kubectl edit 修改 控制器持续对比,自动告警并自我修复(Self-heal)
  • 扩展—迁移—收缩(Expand-Contract)发布模式: 解决发布回滚中“代码可回滚,但已执行的破坏性数据库变更不可回滚”的问题:
    1. Expand(扩展):新增列或表,但旧列保持原样,应用发布新版本兼顾双写;
    2. Migrate(迁移):历史数据后台批量回填;
    3. Contract(收缩):确认旧版本完全下线无依赖后,另起迭代删除废弃列。

6.2.1 GitOps、金丝雀发布与自动回滚闭环

GitOps 以版本控制中的声明式期望状态为变更入口;控制器持续对账并执行部署。CI 负责构建、测试、供应链验证和制品签名,CD/GitOps 负责将已批准的制品按环境逐步交付,二者边界需要清晰。

  • 发布策略:蓝绿关注两套环境切换;金丝雀按比例/标签逐步放量;滚动发布控制新旧副本替换节奏。策略选择由兼容性、状态迁移、会话和数据层约束决定。
  • 自动分析:定义错误率、P95/P99、资源使用、业务转化、队列积压等指标阈值和最短观察窗;避免流量太少或业务周期不同造成误判。
  • 回滚约束:应用镜像可回滚不代表数据库可回滚。Schema 变更使用 Expand–Contract,消息格式向后兼容;对不可逆数据变化准备向前修复脚本与快照。
  • Git 分支:Trunk-Based 可减少长期分支集成成本;GitFlow 适合某些版本发布节奏,但会增加分支同步负担。不能只凭流行度决定,需匹配团队交付频率。

6.3 大数据栈

表 21:大数据栈复习条目

子域 技术项 关键考点
实时计算 Flink on K8s、Spark RocksDB 状态后端、增量 Checkpointing、端到端 Exactly-Once
数据湖与存储 Kafka 管道、HBase、Alluxio、OSS 存算分离、冷热分层、对象存储读加速

6.3.1 Hadoop:HDFS、MapReduce 与 YARN 的职责划分

上传 PDF 第 25、28 章(目录标注页 259–262、275–277)介绍 HDFS、MapReduce 和 YARN。需要特别纠正一个常见的年代混淆:JobTracker/TaskTracker 属于 Hadoop 1.x 的经典架构;在 Hadoop 2.x 及后续 YARN 架构中,资源管理拆分为 ResourceManager、NodeManager 与每个应用的 ApplicationMaster。

表 103:Hadoop 组件与现代架构边界

组件/概念职责常见追问与误区
HDFS NameNode / DataNodeNameNode 管理文件系统命名空间与块元数据;DataNode 存储实际数据块并执行读写/复制。NameNode 元数据高可用与 DataNode 数据块副本是不同问题;SecondaryNameNode 的经典职责是 checkpoint,并不等价于热备 NameNode。
HDFS 读写路径客户端向 NameNode 查询块位置;数据流通常由客户端与 DataNode 直接传输;写入通过流水线写多个副本。元数据控制路径和实际数据路径要区分;要理解副本放置、机架感知、故障重试与块损坏校验。
MapReduceMap 生成中间 key/value;Shuffle/Sort 按 key 分组并搬运数据;Reduce 聚合/输出。Shuffle 常是网络、磁盘和排序成本的主要来源;数据倾斜、分区器、Combiner 的语义约束会显著影响性能和正确性。
YARNResourceManager 负责集群级资源调度;NodeManager 管理节点容器;ApplicationMaster 为具体应用申请和协调资源。YARN Container 是资源分配单元,不等同于 Docker 容器;资源调度、任务执行和作业状态管理分属不同组件。
Hadoop 1.x vs YARN经典 JobTracker/TaskTracker 合并了调度与任务管理;YARN 将集群资源管理和应用调度职责拆分。旧资料中的 JobTracker/TaskTracker 可用于理解历史架构,但不应写成当前 YARN 的核心组件。
6.3.1.1 HDFS 检查点、MapReduce 与 YARN 调度链
  • HDFS:NameNode 管理文件系统元数据,DataNode 存储 Block;FSImage 保存元数据快照、EditLog 记录后续修改,Checkpoint 合并两者以控制恢复时的重放长度。Checkpoint 不是简单等同于 NameNode 高可用。
  • 块与副本:副本放置、Rack Awareness、DataNode 心跳/块报告和重新复制共同影响容错;需区分单个 Block 丢失与整个节点/机架故障。
  • MapReduce:Map 输出按分区排序并经 Shuffle/Reduce 聚合;数据倾斜、spill、合并和网络读写可能成为瓶颈。
  • YARN:ResourceManager 负责资源调度,NodeManager 管理节点容器,ApplicationMaster 管理单个应用执行;Container 表示资源分配,不等同于 Docker 容器。

6.3.2 Spark:RDD、DAG、Stage、Task 与 Shuffle

上传 PDF 第 26 章(目录标注页 263–268)重点介绍 Spark 组件、运行流程与 RDD。补充时以可用于面试和排障的计算模型为中心,并区分早期 DStream API 与当前更常见的 Structured Streaming。

表 104:Spark 计算模型与性能诊断

主题核心语义面试/排障关注点
RDD 与惰性执行RDD 表示可分区的分布式数据集;Transformation 通常构建 lineage,Action 触发实际执行。区分转换和行动操作;不必要的 Action 可能重复计算,缓存应基于复用频率与内存预算。
DAG / Stage / TaskDAGScheduler 根据依赖关系切分 Stage;宽依赖通常形成 Shuffle 边界;Task 是对分区执行的工作单元。Stage 数、Task 数、分区大小与依赖类型影响并行度和调度开销;“Executor 数越多越快”并非普遍结论。
Shuffle 与倾斜跨分区重分布数据,涉及序列化、网络传输、排序/聚合与磁盘 spill。关注 skew key、分区器、数据量、spill、GC、网络与磁盘;必要时重分区、局部聚合或对热点 key 单独处理。
缓存与 Checkpointcache/persist 复用计算结果;checkpoint 用于截断 lineage 并持久化恢复点。缓存级别要结合内存/磁盘与容错成本;checkpoint 与缓存不是同一个概念,也不是所有作业都应无差别使用。
组件职责Driver 组织应用与任务;Executor 在 Worker/节点资源上执行 Task;Cluster Manager 分配资源。应用执行、资源管理、数据源读取与 shuffle 服务之间的故障点不同,排查时结合 Spark UI、日志和集群指标。
6.3.2.1 Spark 数据倾斜、Shuffle 与状态诊断
  • 窄依赖可在同一 Stage 内流水化;宽依赖通常需要 Shuffle,产生网络传输、排序/聚合、磁盘 spill 和序列化开销。
  • 定位倾斜先看各 Task 输入行数、运行时长、Shuffle Read/Write、spill、GC 与 executor lost;一个长尾 Task 经常比增加 Executor 数更重要。
  • 缓解方法包括 key salting、局部聚合、倾斜 join 优化、合理分区、广播小表与 AQE(能力需按 Spark 版本/SQL 执行模式确认)。
  • RDD cache/persist 与 checkpoint 作用不同:缓存可减少重复计算;checkpoint 截断 lineage 并持久化恢复边界,代价是额外存储与物化过程。

6.3.3 Storm、Spark Streaming 与 Flink:流处理模型和选型

上传 PDF 第 27 章(目录标注页 269–274)整理 Storm 的 Nimbus、Supervisor、Worker、Spout/Bolt 与 Stream Grouping;报告已有 Flink 与 Spark 概览。本节将历史流处理模型放在同一张表中,避免把不同引擎的“实时”定义混为一谈。

表 105:流处理引擎的模型对照

引擎/模型执行抽象复习与选型边界
Apache StormTopology 由 Spout 产生流、Bolt 处理 Tuple;Grouping 决定 Tuple 的分发方式。适合理解经典逐条事件处理模型、ack/fail 与重放;旧资料中的 Nimbus/Supervisor 架构应结合目标版本官方文档理解,作为新项目选型前应核对维护状态和生态。
Spark Streaming / DStream传统 Spark Streaming 以微批方式处理流;基于批次调度的思路与批计算衔接紧密。需理解批次间隔、端到端延迟与 checkpoint;不要把 DStream 的所有行为直接套用到 Structured Streaming。
Spark Structured Streaming以 DataFrame/Dataset 和增量执行模型表达流处理,支持事件时间、水位线与状态操作(能力取决于源/汇和模式)。检查 output mode、watermark、状态清理、sink 语义和重放;“Exactly-Once”取决于 source、checkpoint、sink 协议,不是只开一个配置项。
Apache Flink面向有状态流处理,提供事件时间、水位线、Checkpoint/Savepoint 与状态后端等机制。评估状态大小、checkpoint 成本、反压、窗口触发、迟到事件与 sink 事务;需要按版本与 connector 核对端到端保证。
Kafka Streams嵌入应用进程的流处理库,利用 Kafka 的分区、状态存储与 changelog 机制。适合 Kafka 中心的拓扑与轻量部署;与独立集群型处理引擎相比,资源隔离和复杂 ETL 生态不同。
  • Checkpoint:Flink 在 Source/算子状态中建立一致性快照;Barrier 与算子状态协调,具体对齐/非对齐模式取决于配置与版本。
  • Exactly-once 边界:Checkpoint 保证状态恢复语义,不自动保证任意外部 Sink 的 exactly-once。外部系统需事务提交、幂等写、两阶段提交或可恢复提交协议。
  • 状态后端:内存/文件/嵌入式 RocksDB 等实现的延迟、内存、磁盘与恢复性能不同;调优需看状态大小、访问模式、增量 checkpoint、写放大和恢复时间。
  • 事件时间:Watermark 表示系统对事件时间进度的估计;延迟事件、allowed lateness、窗口清理与状态 TTL 会影响结果正确性与资源占用。

6.4 Java AI 栈与企业级落地工程化

表 22:Java AI 栈复习条目

子域 技术项
开发框架 Spring AI、LangChain4j
协议与中枢 模型上下文协议(MCP:Host / Client / Server;Resources / Prompts / Tools 三类服务端原语)
性能与降本 向量语义缓存(Semantic Caching)、余弦相似度匹配、冷热分级缓存
应用架构 RAG(切分/召回/重排/权限预过滤)、Agent 工具调用与安全审计
生产治理 Token 成本控制、输入输出截断、降级兜底、基准评测集回归

6.4.1 Spring AI 的三层抽象与 Advisor 执行顺序(表 32)

层次 关键概念 管道执行顺序 面试追问落点
应用层 ChatClient / @ChatClient 流式调用 — 类似 WebClient 的声明式流式 API;装饰器模式
抽象层 ChatModel / VectorStore / ToolCallback — 业务与底层具体大模型厂商解耦,提供通用统一抽象
MemoryAdvisor 捞取会话历史上下文 1(最先) 必须先加载历史记忆,后续日志才能观测完整上下文
RetrievalAdvisor 执行 RAG 向量检索并将结果拼接 Prompt 2 位于 Memory 后、PromptTemplate 动态装配前
PromptTemplateAdvisor 组装提示词模板与元数据变量 3 将上下文合并进系统提示词
LoggingAdvisor 审计记录输入输出与 Token 消耗 4 记录完整装配后的提示词和模型返回结果
FunctionCallingAdvisor 响应工具调用返回并执行内部回调 5(模型返回后) 模型识别参数后触发外部 Java 工具执行

6.4.2 企业级大模型 API 接入治理与成本控制

  • 设置连接超时与首包读取超时;流式传输(SSE)结合客户端断开信号主动 cancel 上游模型请求。
  • 输入输出设置 max_tokens 强上限;结构化输出校验(JSON Schema),输出非法时走规则引擎降级,绝不盲目重试。
6.4.2.1 SSE 背压、配额预算与模型路由策略
  • 客户端断开时传播 cancellation,关闭上游流并释放连接;设置首 Token 超时、总超时、空闲流超时和最大输出 Token,不将每次流式请求当成无限长连接。
  • 对供应商按并发、RPM/TPM、模型上下文长度和成本做限额;以 tenant/user/model 维度控制配额,避免单租户耗尽共享预算。
  • 模型路由要使用经过评测的能力/成本/延迟矩阵,并处理不支持的参数、JSON 模式差异、内容策略和工具调用格式;降级模型应有质量门槛。
  • 重试仅限可安全重试的失败,并对已发出部分输出的流式响应谨慎处理;重试前必须确认不会重复执行工具副作用。

6.4.3 RAG 检索增强系统架构与数据治理

  • 采用父子文档切块(Parent-Document Retriever);混合检索(BM25 关键词 + 向量 Dense);后置 Reranker 模型重排。
  • 权限安全预过滤(Pre-filtering):必须在向量检索阶段前置过滤权限,严禁全量召回后再到内存过滤,防止模型上下文被越权注入未授权数据。
6.4.3.1 RAG 文档版本、权限过滤与评测边界
  • 数据流水线需记录原文来源、版本、租户、权限、时间戳、解析器/分块配置和 Embedding 模型版本;变更后按版本增量重建向量并可回滚。
  • 权限过滤尽量在检索前/检索阶段执行,模型上下文中只应包含当前调用主体有权访问的片段;检索后仍要执行授权检查,不能依赖 Prompt 告诉模型“不要泄露”。
  • 同时评估检索 Recall@k、nDCG、上下文 Precision、答案正确性/忠实度、拒答质量、延迟与 Token 成本;LLM-as-judge 需要人工标注样本校准,不能当作绝对真值。
  • 对抗测试覆盖越权召回、文档内 Prompt Injection、过期文档、引用不存在、检索空结果与恶意超长输入。

6.4.4 Agent 工具调用与安全边界防范

  • 工具白名单 + 参数强制 Bean Validation,严禁模型输出直接拼装为 SQL 或 Shell;
  • 用户输入与系统指令严格隔离,高危操作(转账、删除)必须引入人工确认机制(Human-in-the-loop)。
6.4.4.1 Agent 工具调用的权限、沙箱与副作用治理
  • 工具 schema 负责结构约束,服务端仍需验证用户身份、租户、对象级权限和业务不变量;模型生成的参数不得被视为可信输入。
  • 将只读查询和有副作用的写操作分离,按最小权限授权;删除、付款、发布、外发数据等高风险动作采用人工确认或二次授权。
  • 工具执行使用超时、资源限制、命令/URL 白名单、网络出口控制、审计 ID 和幂等键;Shell/SQL 不直接拼接模型字符串。
  • Prompt Injection 防护是分层的:检索来源标识、指令与数据分离、工具权限、输出校验、沙箱和人工审批不可由单一 Prompt 规则替代。

6.4.5 AI 应用评测指标与质量回归闭环

建立专属固定基准评测集,围绕事实正确性、上下文相关性、无幻觉率(Faithfulness)、答案完整性四大维度自动化回归。

6.4.5.1 AI 应用评测集、回归与可复现性

建立固定基准集与真实失败样本集,记录输入、检索上下文、Prompt/工具版本、模型供应商与参数、输出、人工标签和评测器版本。每次更改分块、Embedding、Reranker、Prompt、工具定义或模型路由后进行回归,报告质量、延迟、失败率及成本。安全测试集需覆盖越权、提示注入、工具滥用、PII 泄露和不安全输出。评测分数必须结合人工抽检、业务指标和置信区间解读;不能仅凭一项“Faithfulness”分数声称质量达标。

6.4.6 模型上下文协议(MCP)架构规范

截至 2026-10-27,MCP(Model Context Protocol,模型上下文协议)的当前公开规范版本为 2026-07-28。该版本强调无状态协议核心和按请求携带元数据的自描述请求,移除旧版协议级 initialize/initialized 握手与 Mcp-Session-Id;协议版本、客户端身份和客户端能力通过请求元数据携带,客户端如需预先查询服务端能力,可调用 server/discover,该发现调用并非每次请求的强制前置步骤。变更通知改用客户端按类型选择订阅的 subscriptions/listen 流机制,Tasks 位于可选扩展中。客户端与 SDK 的实际支持情况仍需按协议版本/兼容矩阵核对,不能把旧版会话模型写成所有实现的固定前提。

表 61:MCP 协议架构与通信机制

架构角色 / 原语 定义与核心职责 企业落地示例
MCP Host 发起模型交互的宿主应用或协作中枢(协调安全管控、用户会话与权限分配) Spring Boot 业务中枢、Claude Desktop、企业级智能客服系统
MCP Client 驻留在 Host 内部的协议客户端,负责发起与 MCP Server 的交互;不得假设必须维持 1:1 的有状态长连接。2026-07-28 核心支持按请求无状态处理,行为取决于双方协议/SDK 版本与所用传输能力。 Spring AI MCP Client 等客户端实现;应核对实际依赖版本与协议兼容性
MCP Server 暴露 Resources、Prompts、Tools 等能力的服务端;当前规范要求实现 server/discover,用于声明支持的协议版本、身份与能力。 数据库查询、GitLab 操作、内部 ERP 服务;每个工具执行仍需业务层授权与审计
原语 ①:Resources 以 URI 标识的上下文资源,可被客户端读取。若需监听变化,2026-07-28 规范通过 subscriptions/listen 订阅指定通知类型;不要将旧版 resources/subscribe 与 resources/unsubscribe 当作当前通用接口。 用户订单详情、企业知识库 Markdown 文件、系统监控 Metrics 数据
原语 ②:Prompts 预定义的交互模板,由 Server 暴露并引导用户输入 “代码审查模板”、“SQL 优化向导”、“财务报表分析提示词”
原语 ③:Tools 可执行操作的工具调用接口,可能产生业务副作用。模型可提出调用,但权限判定必须由 Host/服务端业务逻辑执行;退款、删除、发布等高危动作应有额外确认、幂等与审计。 execute_refund(orderId)、deploy_k8s_service(name)
传输与部署stdio 适用于本地进程集成;Streamable HTTP 适用于网络服务。网络场景需核验 TLS、身份认证、授权、超时、请求大小与审计策略;MCP 协议本身不替代业务对象级权限校验。本地开发工具、企业内网工具服务、受控的业务工具网关
6.4.6.1 MCP 能力发现、授权与审计边界
  • 区分 Host 的策略与会话编排、Client 的协议调用和 Server 暴露的工具/资源/提示能力;协议能力发现并不等于获准调用所有工具。
  • 服务端每次工具执行都要重新验证权限、租户、参数和业务状态;工具列表/描述不能作为授权机制。
  • 传输层认证、授权范围、工具级审计、超时、幂等、速率限制、输出大小限制和错误脱敏需要由系统实施。对执行命令、写库、发消息等副作用工具,必须提供明确审批和回滚设计。
  • 协议版本和 SDK 功能演进快;实现前应锁定兼容版本并核对对应官方规范,不把某一日期的协议细节当成永久不变。

6.4.7 向量语义缓存(Semantic Caching)降本提速架构

传统 String Key 缓存只能命中规范化后完全相同的键;问题改写、同义表达可能降低命中率,但不能据此说它对大模型调用“几乎失效”。语义缓存(Semantic Cache)通过向量相似度等方式复用语义接近的请求,实际收益取决于重复问题比例、相似度阈值、Embedding 与向量检索成本、模型价格及误命中风险,不应预设固定的 50%~70% 降本比例。

用户提问
  → 文本规范化/权限上下文提取
  → Embedding 向量化
  → 按 tenant_id / 数据权限前置过滤后检索向量缓存
  → 依据离线标注集、误命中风险与在线反馈校准的阈值判断
      ├── 命中:返回历史应答(仍有 Embedding、向量检索与网络开销)
      └── 未命中:调用大模型 API → 校验结果 → 异步写入缓存

说明:相似度阈值是示意策略,不是固定标准;命中率、延迟与降本效果必须按真实问题分布实测。

适用边界: 对实时余额、订单状态、权限敏感与强时效数据跳过语义缓存。多租户检索必须在向量查询阶段前置 tenant_id/权限过滤;Prompt 指令不能替代授权。

  • 核心治理边界:对于高时效性业务(如查询实时账户余额)必须跳过语义缓存;对多租户数据必须在向量检索中前置强制过滤 tenant_id,防止越权读取他人的问答缓存。

6.4.8 经典机器学习算法地图:Java 工程师需要掌握到什么程度

上传 PDF 第 29 章(目录标注页 278)列出决策树、随机森林、逻辑回归、SVM、朴素贝叶斯、KNN、K-Means、AdaBoost、神经网络与马尔可夫模型。对于以企业应用为主的 Java 工程师,这部分通常属于 P2:理解任务类型、数据需求和结果评估,比手写训练算法更重要,除非目标岗位明确要求算法研发。

表 106:经典模型家族的任务与边界

算法/家族常见任务理解重点
决策树 / 随机森林 / AdaBoost分类与回归;集成多个树模型降低部分方差或增强拟合能力。解释特征、过拟合、类别不平衡、特征泄漏与验证集;集成模型仍需关注训练/推理成本和可解释性。
逻辑回归 / 朴素贝叶斯分类;逻辑回归建模概率边界,朴素贝叶斯依赖条件独立假设。理解标签、特征编码、概率阈值与校准;模型选择应与基线和业务指标对比。
SVM / KNNSVM 利用间隔/核函数做分类或回归;KNN 根据近邻样本做预测。SVM 关注特征缩放与核参数;KNN 关注距离度量、维度灾难、推理耗时和索引方式。
K-Means无监督聚类,将样本分配到 K 个簇中心附近。需要选择 K、处理尺度与离群点;聚类标签本身没有业务语义,须通过轮廓/稳定性与领域解释评估。
神经网络 / 马尔可夫模型神经网络学习非线性表示;马尔可夫类模型描述特定状态转移或序列依赖。知道任务适用范围、训练/推理差别、数据规模和评估指标即可;不要把“模型复杂”误认为业务效果必然更好。

6.4.9 Prompt Caching、Structured Outputs 与有状态 Graph Workflow

生产级 AI 应用除了模型调用本身,还要控制可重复输入的成本、输出契约与多步工作流状态。三者分别解决“重复前缀是否可复用”“模型结果能否按契约被下游安全消费”“多步工具执行如何可控恢复”的问题,不应混为一类缓存或一个 Agent 循环。

表 145:AI 应用三项工程能力与落地边界
能力实现模式工程落地要点风险与验证
Prompt Caching / Prefix Cache将稳定的系统提示词、工具定义和固定背景放在消息前缀;使用模型服务商提供的前缀缓存/提示缓存能力。遵循提供商对最小前缀长度、顺序、缓存有效期和模型版本的要求;把用户变化内容放后面。把命中率、缓存读 token、TTFT 和实际账单作为指标。不是应用语义缓存;支持范围、命中条件、缓存 token 折扣和时延收益都由服务商/模型决定,不能保证固定 50%–80% 节省。不要把租户私密内容放入跨租户共享前缀。
Structured Outputs用 JSON Schema 或 provider-native constrained output 将结果约束为 Java Record/DTO;Spring AI 可通过 ChatClient.entity(...) 转换到目标类型。正确性敏感场景优先使用服务商原生 schema 约束(如支持)并启用 schema 校验/有限重试;保留业务规则校验和拒答/截断/超时处理。普通提示“请返回 JSON”不等于严格约束;即使框架反序列化成功,也不代表业务值合法。流式响应和 typed entity 的支持方式可能不同,按所用版本确认。
有状态 Graph Workflow使用显式状态图定义节点、边、条件路由、循环、人工审批和 checkpoint,而不是只用无上限的 ReAct 循环。状态要可序列化且带版本;为每次工具副作用设幂等键;限制最大步数、时间、token/成本和并发;持久化 checkpoint,恢复时先检查外部操作是否已提交。LangGraph4j、Spring AI Alibaba Graph 等框架能力与 API 随版本变化。检查断点语义、重试语义和许可证;高风险操作保留 human-in-the-loop 与可审计授权。

AI 的成本优化必须以真实账单与评测集为证据。Prompt Cache 命中不代表语义正确;结构化输出不代表业务正确;状态图能提高流程可控性,但不替代幂等、权限校验和补偿设计。

6.5 SRE、全链路压测与生产事故闭环

表 35:监控指标设计与告警策略

方法论 指标维度 适用场景
RED 方法 Rate(速率)、Errors(错误率)、Duration(持续耗时) API、微服务请求级监控
USE 方法 Utilization(使用率)、Saturation(饱和度)、Errors(错误) CPU、内存、磁盘、连接池资源监控
SLO 燃烧率告警 错误预算消耗速度告警 区分突发消耗与慢性消耗,有效防止告警疲劳

6.5.1 性能调优方法论四步法(表 54)

1. 建立基线(Baseline) :量化压测下的 QPS、TPS、P50/P99 延迟及系统资源饱和度指标。
2. 全链路剖析(Profile) :利用 SkyWalking、Arthas、JFR、iostat 定位瓶颈,拒绝盲目猜测。
3. 优化实施(Optimize)   :算法改善、锁细化、批量化、读写分离、参数收敛。
4. 验证回归(Verify)     :对比优化前后指标,确保 P99 改善且系统无内存或连接泄漏。

6.5.2 Linux 生产环境资源排查矩阵与工具链(表 57)

瓶颈领域 核心排查工具 关键指标与判据
CPU 性能 top、htop、pidstat -u 1 us(用户态高看死循环/加解密)、sy(内核态高看系统调用/上下文切换)
内存状况 free -m、vmstat 1 available 真实可用内存;si/so 发生 swap 交换意味着物理内存耗尽
磁盘与 I/O iostat -xz 1、df -h %util 饱和度接近 100%、await 远远大于 r_await/w_await 意味着 I/O 堆积
网络与连接 ss -s、ss -antp、netstat TIME_WAIT 过多看短连接复用;CLOSE_WAIT 激增意味着应用未正常 close 连接
系统调用跟踪 strace -p <pid> -c 统计最耗时的系统调用(如 futex 锁、epoll_wait)

6.5.3 生产事故应急响应与复盘准则

  • 事故处理原则:先止血后根因(降级、切流、熔断、重启回滚优先);
  • 事故复盘:24~72 小时内组织复盘,产出系统性改进项(Action Items),落实负责人与完成期限。

6.5.3.1 生产事故复盘:时间线、根因与可验证行动项
  1. 先止血:明确影响用户、影响功能和业务损失;同步当前状态、下一次更新时间和负责人。
  2. 时间线:统一时区与时间源,串联发布、告警、流量、依赖、资源与变更记录;区分触发事件、放大因素和未能阻断故障的控制缺口。
  3. 根因分析:不要把“人操作失误”作为终点,继续追问为什么流程允许错误动作、为何监控没提前暴露、为何演练/权限/回滚不能防住。
  4. 行动项:每项要有负责人、截止日期、验证指标与复查时间;按风险优先级处理架构、测试、告警和手册,不把所有问题都变成“增加监控”。

6.5.4 Linux 操作系统经典面试题与排障

PDai 与《成神之路》的知识图谱都把 Linux 命令、进程/线程、虚拟内存和性能定位视为 Java 工程师的底层能力。本节与 6.5.2 的工具矩阵配合,补齐常见操作系统语义与生产误区。

表 88:Linux/操作系统基础与生产排障

主题核心知识点排障判据与实践
进程、线程与上下文切换进程拥有独立虚拟地址空间与资源视图;线程共享进程地址空间,但有独立栈和调度状态。频繁切换会产生调度与缓存开销。Java 线程数过多可能导致上下文切换、栈内存和调度开销上涨;结合线程转储、pidstat、vmstat 验证。
Load Average 与 CPU 利用率Load Average 粗略反映可运行任务与不可中断睡眠任务的负载,不等同于 CPU 百分比。I/O 堵塞也可能推高 load。联合看 us/sy/id/wa、运行队列、CPU quota/throttling、磁盘 await 与 D 状态进程。
虚拟内存、页缓存与 Swap进程虚拟地址空间、RSS、页缓存、匿名页、直接内存和 cgroup 内存限制并非同一口径;Swap 活动可能带来延迟抖动。区分 JVM heap 与进程 RSS;容器 OOM 需要同时查看 cgroup limit、page cache、线程栈、Metaspace、Direct Memory 和本机分配。
文件描述符与删除中的文件Socket、文件和管道都消耗文件描述符;删除已打开文件通常只是移除目录项,直到最后一个 fd 关闭才释放磁盘空间。检查 /proc/<pid>/fd、lsof +L1、ulimit 与进程 fd 上限,排查“磁盘满但 du 看不到文件”。
信号与进程终止SIGTERM 允许程序执行清理和优雅停机;SIGKILL(kill -9)不能被捕获或处理。先发送 TERM、等待并收集日志/线程栈,再评估 KILL;容器编排平台的终止宽限期要与应用关停时间协调。
IPC 与系统工具常见 IPC 包括管道、命名管道、共享内存、消息队列、信号量、Unix Domain Socket、TCP Socket。熟悉 ps/top/pidstat/vmstat/iostat/ss/lsof/strace/perf 等工具解决“进程在哪里、等什么、资源是否饱和”。

6.6 混沌工程(表 47)

  • 核心原则:建立稳态假设,在生产或预发环境主动注入故障验证系统弹性(如随机 Kill 实例、注入网络丢包延迟、时钟回拨),检验容灾自愈与熔断配置的有效性。工具采用 Chaos Mesh 或 Chaos Blade。

6.6.1 混沌工程:假设、爆炸半径与停止条件

  • 先定义稳态假设和可观测指标,例如成功率、P99、错误预算消耗、复制延迟和恢复时间;演练开始前建立基线。
  • 从预发/小流量/单实例开始,逐步扩大 blast radius;使用明确的自动中止条件和负责人,避免为了演练伤害真实业务。
  • 故障注入覆盖实例宕机、网络延迟/丢包、依赖限流、磁盘/内存压力、时钟漂移等,但一次只改变有限变量以便归因。
  • 通过演练验证检测时间、切换时间、数据一致性、恢复过程是否引起二次过载,以及 Runbook 是否真正可执行。

7. 安全合规、工程质量与跨领域补漏

7.1 构建、依赖与软件供应链治理(表 31)

  • Maven 依赖仲裁三大规则:路径最近者优先 \(\to\) 第一声明者优先。排查使用 mvn dependency:tree -Dverbose,版本收敛采用 <dependencyManagement> 或引入标准 BOM。
  • 软件供应链安全(SBOM):CI 流水线强制集成 Trivy/OWASP Dependency-Check 扫描第三方依赖 CVE 漏洞;制品库禁止拉取公网不可信包,禁止 SNAPSHOT 版本上生产。

7.1.1 Git、构建工具、常用库与源码阅读

在已有 Maven 依赖仲裁与供应链治理基础上,补齐经典题库中的 Git 工作流、Maven/Gradle、JSON 库、Lombok/MapStruct 与编译产物排查。这些知识点在资深岗位中常作为工程习惯和线上问题定位的追问。

表 87:开发工具与常用库核心边界

主题核心知识点面试与工程落点
Git 状态与回退理解工作区、暂存区、本地仓库和远端仓库;merge 保留分支汇合历史,rebase 重写提交基线;cherry-pick 迁移特定提交。revert 生成反向提交,reset 移动本地引用;公共分支慎用重写历史,回滚代码不等于回滚数据库状态。
定位构建与依赖问题Maven 依赖传递、nearest-wins 仲裁、dependencyManagement/BOM、scope 与生命周期;Gradle configurations、插件任务和锁定文件。用 dependency:tree / dependencyInsight 看真实图;依赖版本、插件版本、JDK toolchain 与构建镜像应可复现。
Lombok 与 MapStructLombok 主要通过注解处理生成样板代码;MapStruct 通常在编译期生成类型安全的映射代码。关注 IDE/CI 的注解处理器一致性、生成源码可诊断性、DTO 字段变更和隐式映射;不要把 MapStruct 与运行期反射映射混为一谈。
JSON 库与反序列化安全Jackson、Gson 等库在配置、类型处理、日期格式、循环引用与性能上存在差异;Fastjson 等实现也需按版本和安全公告评估。禁止不可信输入触发任意多态类型反序列化;严格定义 DTO、字段白名单、大小/深度限制,保留可复现的兼容性测试。
源码与字节码工具javac/javap -c -v 用于查看编译产物与常量池;IDE debugger、Maven/Gradle 插件、静态分析和代码格式化用于形成工程闭环。对反射、桥接方法、泛型擦除、注解处理、依赖冲突与 NoSuchMethodError,尽可能从编译产物和依赖树取证。
7.1.1.1 SBOM、制品签名与依赖治理闭环
  • 依赖锁定与版本收敛:使用 BOM/dependencyManagement、构建锁文件或固定插件版本;通过 dependency tree/SBOM 识别传递依赖和重复版本。
  • 漏洞扫描不是全部供应链安全:还应验证来源、制品摘要、签名/证明、构建可复现性、仓库访问控制和发布审批;对例外项记录风险接受人和到期日。
  • 应急升级要走兼容性测试、SBOM 差异、集成测试和灰度验证;不要仅因扫描工具报出 CVE 就忽略可达性/修复版本,也不要因“暂不可达”而无限期忽略。

7.2 应用高危漏洞深度防御(SSRF/注入/上传/反序列化)

  • SSRF 深度防护体系:严禁仅过滤 localhost。防护必须包含:协议白名单(仅允许 HTTP/HTTPS)、目标 IP 白名单机制、解析 DNS 后校验是否落在回环地址、内网网段(RFC 1918)或云厂商元数据服务(169.254.169.254)、请求重定向二次校验、设置严格读取超时。
  • 注入漏洞防御:SQL 全参数化预编译;文件上传严格限制后缀与 MIME-Type,并存储于独立隔离的对象存储(OSS)。

7.2.1 加密、哈希、签名与校验:密码学基础边界

上传 PDF 第 23 章(目录标注页 255–256)列出 AES、RSA、CRC 与 MD5。该列表反映的是经典概念入门,不等于现代安全建议;必须区分加密、完整性校验、消息认证、数字签名与密码存储。

表 107:常见密码学原语及其用途

原语适用用途重要边界
对称加密(如 AES-GCM)使用同一密钥加解密;AEAD 模式同时提供机密性与完整性保护。Nonce/IV 不能在同一密钥下错误复用;密钥生成、存储、轮换与访问权限比随意选择模式更关键。
非对称加密/密钥交换(RSA、ECC 家族)公私钥机制可用于加密/密钥封装、密钥协商或签名,具体算法用途不同。“RSA”不是一种通用的所有场景算法;优先使用成熟 TLS/密码库的标准配置,不要自行设计协议。
哈希(SHA-256 等)将任意长度输入映射为摘要,用于内容标识、完整性指纹等。普通哈希不加密,也不提供密钥认证;MD5 与 SHA-1 不应用于新的抗碰撞安全场景。
HMAC 与数字签名HMAC 以共享密钥认证消息;数字签名使用私钥签名、公钥验签,支持来源真实性与完整性验证。共享密钥与私钥泄露风险不同;密钥管理、轮换、可信公钥分发和重放防护不可省略。
CRC / 校验和发现传输或存储中的意外比特错误。CRC 不具备密码学抗攻击能力,攻击者可以构造碰撞;不能替代 HMAC、AEAD 或数字签名。
密码存储使用 Argon2id、scrypt、bcrypt 或合适配置的 PBKDF2 等专用密码哈希,结合独立随机盐与成本参数。不要使用可快速计算的 MD5/SHA-256 直接保存密码;不要自行发明“加盐方案”。遵从组织合规标准与安全库建议。
TLS 与密钥管理TLS 保护传输链路;KMS/HSM 或专用秘密管理系统管理密钥与凭据。HTTPS 不自动解决应用授权、日志泄密、密钥轮换或端点安全;开发中避免硬编码密钥与把密钥提交到 Git。

7.2.2 Web 安全补漏:XXE、命令注入、路径遍历与浏览器安全(表 115)

原报告已覆盖 SSRF、SQL 注入、上传与反序列化。本节结合 JavaGuide Web 安全与认证授权主题,补齐几类常见遗漏;防护应分层执行,不能把输入过滤或 CORS 配置误当作完整授权机制。Web 安全面试题 · 认证与授权面试题。

风险常见根因核心防护与面试边界
XXE(XML 外部实体)XML 解析器允许解析外部实体或外部 DTD。按解析器和版本禁用外部实体/外部 DTD,限制外部资源访问;用负向测试验证,而非只依赖 WAF。
命令注入将用户输入拼接到 shell 命令或解释器语句。优先使用语言 API 代替 shell;必须调用进程时使用固定可执行程序与参数列表、白名单校验、最小权限和超时控制。
路径遍历把用户传入的文件名直接拼接成文件系统路径。采用服务端生成的文件标识,规范化路径并验证最终路径位于授权根目录内;拒绝符号链接逃逸和不受控解压路径。
XSS把不可信文本作为 HTML、属性、URL 或脚本上下文输出。按输出上下文编码,优先安全模板 API,必要时采用严格 CSP;不能把输入过滤当作唯一防线。
CSRF浏览器自动携带会话凭据,攻击站点诱导用户提交请求。根据认证方式设置 SameSite、Secure、HttpOnly,使用 CSRF Token/Origin 校验等措施;Cookie 属性不能替代所有服务端校验。
CORS错误理解跨域响应共享策略。CORS 不是身份认证,也不是 API 授权;避免对凭据请求使用宽泛 Origin 通配,准确配置允许的源、方法、请求头和凭据策略。
IDOR / 对象级越权只校验是否登录或角色,不校验当前主体能否访问具体对象。每次请求按主体、租户、资源归属和动作做后端授权;客户端传来的 userId/tenantId 不能直接信任。
不安全文件上传只看扩展名,或把上传文件直接放在可执行/可公开访问目录。校验内容类型与签名、限制大小和解压比例、使用随机文件名、隔离存储、禁止执行并控制下载权限。
不安全反序列化对不可信输入进行通用对象反序列化或信任类型信息。优先使用明确 DTO 与数据格式;限制类型/类白名单、版本和大小,并对依赖链升级。不要把签名校验等同于解析器安全。

认证授权补充:Session/Cookie 与 JWT 的状态管理有不同代价;JWT 的 Base64Url 编码不等于加密,签名也不防重放。OAuth 2.0 解决授权,OIDC 叠加身份层;授权码流程应按安全最佳实践使用 PKCE,并严格校验 redirect URI、state、issuer、audience、过期时间与签名算法。


7.3 细粒度权限控制与操作审计(RBAC/ABAC/对象级鉴权)

  • 对象级权限校验(BOLA/IDOR 防御):用户具有访问接口的角色,绝不代表他有权读取任意 orderId。数据访问层必须显式追加当前登录租户与用户维度的属主约束:
SELECT * FROM orders WHERE order_id = :orderId AND user_id = :currentUserId;
  • 关键合规审计:对用户敏感数据访问、特权管理员操作全量记录不可篡改的安全审计日志。

7.3.1 数据行级鉴权与审计证据链

  • 鉴权至少包含身份、功能权限、对象/数据范围、租户边界和当前业务状态;列表接口、导出、批量操作、异步任务和缓存路径都必须执行同一授权规则。
  • 审计记录操作者、对象、动作、授权上下文、结果、traceId、时间与来源;按数据分级做脱敏并限制审计日志自身的读取权限。
  • 不可篡改可以通过 append-only 权限、独立存储、哈希链/签名与外部归档组合实现;哈希链只增加篡改可检测性,仍需保护密钥和日志写入主体。

7.4 企业级测试分层与工程防线(表 58)

测试层级 核心工具 验证目标 运行频率与成本
单元测试 JUnit 5、Mockito、AssertJ 核心业务算法、值对象与复杂状态流转 高频,每次 commit 执行,秒级返回
架构约束测试 ArchUnit 保证分层依赖单向性(如 DAO 不得反向依赖 Controller) 每次编译构建必跑,防止架构腐化
集成测试 Testcontainers 结合真实 Docker 运行 MySQL/Redis/Kafka,杜绝内存伪测试 持续集成流水线跑批,分钟级
契约测试 Pact 消费者驱动契约测试,保证上下游 API 字段兼容性 服务发版前验证契约无破坏性变更
全链路压测 JMeter、Wrk、Gatling 流量染色与影子库压测,评估系统容量拐点 重大活动前夕及定期演练

7.4.1 测试开发进阶:测试替身、属性测试、变异测试与 Flaky Test(表 116)

现有测试章节已有 JUnit 5、Mockito、Testcontainers、ArchUnit、Pact 和压测工具。本节补充面试中容易被忽略的测试策略:测试是否隔离、是否稳定、是否真的能发现缺陷,以及怎样让测试与发布门禁形成闭环。JavaGuide 首页将“测试开发”列为独立面试领域;本节是面向资深后端岗位的通用补充,而不是对无法访问的单篇测试子页作逐字转述。

测试类型/实践适合验证常见陷阱与工程要求
单元测试纯业务规则、边界条件、状态机和失败分支。避免测试实现细节;用确定性输入,依赖可注入的 Clock、随机数或 ID 生成器控制时间与随机性。
Mock / Stub / FakeMock 验证交互;Stub 提供预定响应;Fake 用简化实现替代真实依赖。不要把所有依赖都 Mock 掉,否则测试可能只证明 Mock 按预期工作;关键数据库/中间件语义需集成测试验证。
集成测试Spring 容器、数据库事务、Redis、MQ、序列化与真实协议行为。优先用 Testcontainers 等方式验证真实依赖;隔离测试数据、端口和资源,避免环境偶然性。
契约与架构测试上下游 DTO/API 兼容、模块依赖方向和分层约束。契约测试不等于端到端测试;契约应纳入消费者/提供者的版本与发布流程。
属性测试 / 模糊测试大量输入下的不变量、边界和解析器健壮性。定义可验证的性质和种子复现机制;不能只依赖随机跑数而没有失败样本保留。
变异测试评估测试是否能检测逻辑被改变,例如边界条件或比较符号被替换。变异分数是信号而非唯一质量指标;处理等价变异和执行成本。
Flaky Test 治理发现时间依赖、共享状态、并发竞争、外部网络和执行顺序导致的偶发失败。禁止用随意重跑掩盖问题;记录失败种子/日志,消除 sleep 依赖,隔离共享资源并区分产品缺陷与测试缺陷。
性能与韧性测试容量拐点、尾延迟、队列积压、长时间资源增长和故障恢复。明确基线、负载模型、数据规模和环境;分别做基准、负载、压力、稳定性与故障注入测试。

测试门禁建议:提交阶段运行快速单元/架构测试;合并阶段运行集成与契约测试;发布前运行关键链路回归和性能基线;重大变更前安排压力、容量或故障演练。测试金字塔是成本和反馈速度的指导原则,不代表每个系统必须套用固定比例。


7.4.1.1 属性测试、变异测试与 Flaky Test 治理
  • 测试替身:Stub 返回预设结果,Mock 验证交互,Fake 提供可运行的轻量实现;优先验证业务结果与边界,不把内部调用顺序全部锁死。
  • 属性测试:定义对大量输入应成立的不变量(例如序列化往返、金额守恒、排序性质、幂等重复调用),由工具生成输入并缩减失败样本。
  • 变异测试:故意改变条件/运算符/返回值,验证测试是否能发现真实逻辑破坏;变异存活可能意味着测试断言不足,但也可能是等价变异。
  • Flaky Test:分类为时序竞态、共享状态、测试顺序依赖、时钟/随机数、外部网络和资源竞争;重试只能帮助识别,不应把重试通过当成修复。记录失败率、重试命中、耗时和责任人,隔离后设置修复 SLA。

7.5 高频遗漏知识点补充核对(本轮增补)

本报告已覆盖 Java/JVM、并发、Spring、微服务、消息、数据库、缓存、架构、云原生、安全、测试与 AI 等主干。以下内容不代表每个岗位都必须精通,而是对资深 Java 后端岗位常见盲区的补充核对。按目标岗位与生产环境选择深度,避免把技术清单误当成必须全部落地的技术选型。

7.5.1 API 契约、身份认证与授权

  • API 契约:OpenAPI/Swagger、请求与响应模型、错误码规范、幂等键、分页约定、兼容性策略、弃用与迁移窗口;区分向后兼容和语义兼容。
  • 认证与授权:Cookie/Session、JWT 的签名与过期、OAuth 2.0、OpenID Connect、服务间身份、刷新令牌轮换、密钥轮换、注销与令牌撤销;JWT 不是加密,也不能替代服务端授权。
  • 授权模型:RBAC/ABAC 与租户、资源、操作三级校验;防止越权访问、IDOR/BOLA;批量接口、导出接口和异步任务同样需要授权校验。
  • 限流与滥用防护:按用户、租户、接口和下游维度设置配额;区分限流、并发隔离、熔断与负载 shedding,明确 429/Retry-After 行为。

7.5.2 构建、交付与代码维护

  • Maven/Gradle:依赖传递、依赖仲裁、BOM、插件生命周期、可重复构建、版本锁定、私服与离线构建;能通过 dependency tree 定位版本冲突。
  • Git 工程:rebase/merge、冲突解决、cherry-pick、revert、bisect、tag 与发布分支;理解回滚提交与回滚数据库变更不是一回事。
  • 代码质量:静态分析、格式化、覆盖率、复杂度、重复代码、架构测试、代码评审清单;测试覆盖率不能单独代表测试有效性。
  • 制品与发布:制品不可变、镜像标签与摘要、SBOM、签名与来源证明、依赖漏洞扫描、配置与密钥分离、发布审批与审计记录。

7.5.3 数据库与数据工程的边界能力

  • SQL 进阶:窗口函数、CTE、执行计划估算误差、统计信息、锁等待与死锁诊断、批量写入、在线 DDL、字符集与排序规则;能结合实际数据库版本解释差异。
  • 数据库多样性:若目标公司使用 Oracle/PostgreSQL,补齐其事务、索引、执行计划、序列/自增、锁、JSON 能力和迁移工具差异;不要把 MySQL 的行为直接套用到其他数据库。
  • 数据一致性:CDC、增量同步、全量校验、数据修复、重复与乱序事件处理、删除传播、对账任务和数据血缘;同步链路必须设计断点续传与可观测性。
  • 对象存储与文件:预签名 URL、分片上传、断点续传、内容哈希、病毒扫描、文件元数据、生命周期策略、访问控制及大文件下载的带宽治理。

7.5.4 分布式系统的工程细节

  • 时间与顺序:墙上时钟与单调时钟区别、时钟漂移、时区、时间戳精度、事件时间与处理时间;不要仅凭客户端时间戳判定全局顺序。
  • 租约与 fencing token:分布式锁过期后旧持有者可能继续执行;对关键写入使用递增 fencing token 或由数据库条件更新等机制阻止过期持有者覆盖新结果。
  • 一致性与读写路径:读己之写、单调读、最终一致性、缓存/副本延迟、故障切换后的陈旧数据;为关键业务定义可接受的一致性等级。
  • 容量与背压:队列长度、最大并发、连接池、线程池、数据库连接和下游配额要联合估算;队列不是无限缓冲,积压必须有上限、告警与降级策略。
  • 数据修复:对账、补偿、重放、死信处理、人工介入和审计轨迹要形成闭环;重放必须具备幂等与速率控制。

7.5.5 可观测性与生产运维

  • 日志、指标、链路:统一 traceId/correlationId、结构化日志、指标标签基数治理、采样策略、敏感字段脱敏和跨服务上下文传播。
  • 告警工程:基于用户影响与 SLO 的告警、告警分级、抑制与聚合、值班升级;避免只监控 CPU/内存而忽略错误率、延迟和饱和度。
  • SLO/SLI/Error Budget:定义可量化的可用性与延迟目标,区分平均值与 P95/P99;用错误预算影响发布节奏与稳定性投入。
  • 容量规划:压测模型、峰值与突发系数、冷热路径、资源利用率、扩容提前量和成本;压测数据应记录版本、数据规模、硬件、流量模型与瓶颈。

7.5.6 安全与合规的补充项

  • 密码学基础:TLS、证书链、证书轮换、哈希与 HMAC、对称/非对称加密、随机数、密码存储与密钥管理;不自行设计密码算法。
  • 常见 Web 风险:CSRF、XSS、CORS 误配、请求走私、路径穿越、开放重定向、SSRF、依赖供应链风险;CORS 不是服务端授权机制。
  • 隐私与数据治理:数据分级、最小化采集、脱敏、保留期限、删除请求、审计、备份中的敏感数据和跨境/行业合规要求;具体义务以适用法律和公司政策为准。
  • 密钥与配置:禁止把密码、Token、私钥写入代码仓库或日志;支持轮换、最小权限、短期凭证和泄露后的吊销流程。

7.5.7 资深岗位的系统设计与沟通交付

  • 需求与非功能指标:先澄清业务边界、流量、数据规模、延迟、可用性、RPO/RTO、合规、预算与团队能力,再提出方案。
  • 架构决策:明确备选方案、约束、风险、迁移成本、回滚策略与验证指标;用 ADR 记录决策及重新评估触发条件。
  • 技术债治理:债务登记、风险分级、业务影响、偿还成本、负责人和验收标准;避免只用“重构更优雅”作为投入理由。
  • 项目交付:拆分里程碑、跨团队依赖、上线准入、灰度指标、回滚演练、运行手册、交接与复盘;将个人贡献与团队成果区分清楚。
补充后的复习方法

先检查目标职位 JD,再把上述内容标记为“必须讲清 / 有项目经验 / 了解概念”。每项至少能说明:解决什么问题、机制是什么、适用边界、失败模式、监控指标和替代方案。对没有实际使用过的技术,应明确说明是原理理解或实验经验,不要包装成生产经验。

7.6 第二轮遗漏点与生产落地核对

本节是面向资深后端岗位的横向补漏,不要求把所有方案都引入项目。复习时应能解释适用条件、失败模式、观测指标、回滚办法,并用真实项目案例说明取舍。

7.6.1 服务治理与故障隔离

  • 超时预算:为入口、业务服务、数据库、缓存和下游 RPC 分配总耗时预算;超时应向下游传播,避免每一层都设置独立且过长的超时。
  • 隔离与降级:区分连接池隔离、线程池隔离、舱壁、限流、熔断与降级;明确熔断恢复探测、半开状态、降级数据时效和恢复策略。
  • 优雅停机:先摘除流量,再停止接收新请求,等待在途请求和消息处理完成,最后关闭线程池、连接池与客户端;要处理容器终止宽限期和强杀边界。
  • 配置与功能开关:区分静态配置、动态配置、密钥与 Feature Flag;配置变更需校验、审计、灰度、回滚,功能开关要有负责人和清理期限。

7.6.2 数据演进与后台任务

  • 在线 Schema 变更:掌握 expand–migrate–contract:先兼容性扩展,再双读/双写或回填验证,最后移除旧字段;应用发布与数据库变更必须能错峰兼容。
  • 批处理与回填:设计可暂停、可续跑、可限速、可幂等的批任务;记录游标/检查点,控制锁与数据库负载,支持失败重试、差异核对和人工纠偏。
  • 数据对账与修复:区分在线事务正确性和离线对账兜底;为订单、支付、库存、账务等关键链路定义不变量、差异发现时限、修复权限与审计记录。
  • 文件与对象存储:理解分片上传、断点续传、校验和、临时凭证、对象生命周期、病毒扫描、下载授权和删除一致性;不要把大文件直接塞入应用内存或数据库事务。

7.6.3 多租户与数据边界

  • 租户隔离:比较独立实例/独立数据库/共享库共享表等模式,明确 tenant_id 的强制注入、唯一约束、缓存键、异步消息上下文与后台任务隔离。
  • 对象级授权:不只验证“用户有某个角色”,还要验证其对当前租户、当前资源和当前操作的权限;防止通过猜测 ID 访问其他用户数据。
  • 数据生命周期:定义数据分类、保留期限、归档、删除、导出、脱敏、审计与备份中的敏感数据处理;删除请求需考虑缓存、搜索索引、对象存储和下游副本。

7.6.4 容量、成本与发布治理

  • 容量估算:从峰值 QPS、请求放大倍数、平均/尾延迟、并发数、单请求 CPU/内存、连接数和数据增长推算容量,并通过压测校准假设。
  • 成本可观测性:除 CPU/内存外,跟踪数据库连接、缓存内存、消息积压、日志/链路采样、对象存储、跨区流量和 AI Token 等主要成本驱动因素。
  • 发布兼容性:验证滚动发布期间新旧版本共存时的 API、消息格式、缓存结构和数据库 Schema 兼容性;明确灰度指标、自动停止条件、回滚限制与回滚后数据处理。
  • 供应链完整性:将依赖锁定、制品不可变、构建来源、SBOM、漏洞扫描、制品签名与部署身份串成可审计链路;生产环境尽量只部署经过验证的构建产物。

7.6.5 架构选型与领域建模

  • 模块化单体与微服务:能说明什么时候先用模块化单体、什么时候拆分服务;拆分依据应包括团队边界、独立扩缩容、发布频率、故障隔离和数据所有权,而非只看代码规模。
  • 读写模型与查询边界:了解 CQRS 的收益与复杂度,识别跨聚合查询、报表、搜索索引和缓存是否应走独立读模型;不要为“使用 DDD”而机械引入 CQRS/Event Sourcing。
  • 外部系统集成:为第三方 API 设计连接/读取超时、限流、幂等、签名验签、重放保护、错误分类、对账补偿和供应商故障降级。
本轮复核结论

补齐上述横向主题后,报告的知识覆盖已较为完整,适合作为资深 Java 后端复习地图;但“完整”不等于每项都要精通,也不意味着覆盖每个行业的全部要求。应优先围绕目标岗位 JD、自己做过的系统和可量化的生产案例深入准备。

8. 非技术栈要求(简要)

资深岗位通常对标工程师、架构师、技术专家或研发负责人。技术判断必须能转化为业务结果,同时具备清晰沟通、跨团队协作和交付闭环能力:

  1. 商业洞察与 ROI: 用业务语言说明技术改造对成本、转化率、风险、交付周期或服务器资源的影响;区分可测量结果与估算假设。
  2. 需求澄清与非功能指标: 在方案设计前确认业务边界、用户影响、峰值流量、延迟、可用性、数据保留、合规、预算与团队能力;将模糊目标转化为可验证的验收指标。
  3. 技术沟通与跨团队推动: 用 ADR、设计评审、RFC、接口契约和风险清单达成共识;能够解释技术债与取舍,而非只推动个人偏好的技术方案。
  4. 人才培养与团队梯队: 通过代码评审、导师机制、故障复盘与技术分享提升团队能力。70/20/10 等比例只能作为特定团队讨论资源投入的起点,不是普适管理公式。
  5. 技术攻坚与事故沟通: 重大故障中先同步影响面、止血动作、责任人与下一次更新时间;事后形成可验证的改进项,避免只归因于个人失误。
  6. 技术影响力与交付责任: 主导 ADR 落地、疑难故障闭环、技术路线图和技术债治理;用上线质量、SLO、成本与业务结果证明影响力。

9. 可执行复习清单

表 24:P0 栈打勾清单(26 项)

完成 序 复习条目 完成标准
1 JVM 内存结构与 JMM happens-before 脱离资料画全内存模型,讲清 volatile 屏障语义与三大特性(表 55)
2 G1/ZGC 对比与全量十款回收器 熟知十款 GC 机制对比(表 63),讲出停顿调优反例、ZGC 染色指针与读屏障;熟练运用 GC 选型表(表 36)
3 三色标记漏标充要条件与并发屏障 熟练画出漏标两条件图,讲透增量更新(写后屏障)、SATB(写前屏障)与读屏障自愈的深层哲学
4 TTSP 诊断与可数循环陷阱 能看懂安全点日志中的 spin 耗时,解释 C2 可数循环为何无轮询指令及条带化解决方案
5 Glibc ptmalloc 膨胀与 jemalloc 根据 RSS、NMT、pmap/ smaps 与分配器指标解释 Arena、内存映射和碎片造成的进程内存差异;说明 MALLOC_ARENA_MAX 调整与 jemalloc 替换的适用条件(表 62)
6 类加载体系与打破双亲委派 讲透 SPI、Tomcat、热部署机制及类卸载三条件与 Metaspace OOM 排查
7 线上排查工具链证据闭环 熟练通过 top-Hp、jstack、Arthas、MAT 定位 CPU 100%、内存泄漏与死锁
8 AQS 模式与三组件源码级差异 画出加锁唤醒流程,讲透 CountDownLatch、CyclicBarrier、Semaphore 区别(表 39)
9 CPU 伪共享与 Disruptor 架构 讲清 64 字节 Cache Line 命中失效的 CPU MESI 机制,说明 @Contended 内存填充与环形队列
10 ThreadPoolExecutor 与 ForkJoinPool 讲清 7 参数、任务队列、拒绝策略;掌握监控饱和度指标清单
11 ConcurrentHashMap 源码与扩容 讲清 JDK 7 到 8 的重构原理及多线程协作 transfer 迁移扩容
12 核心集合底层实现与算法寻址 掌握 HashMap 扰动函数与高低位扩容、泊松分布阈值、LinkedHashMap LRU、跳表并发删除、subList 泄漏等(表 64)
13 虚拟线程与新并发演变 掌握适用边界、Pinning 现状、ScopedValue 替代 ThreadLocal 及迁移三问
14 Bean 生命周期与三级缓存 讲清为什么二级缓存不够,ObjectFactory 提前暴露 AOP 代理的精确时机
15 BFPP 与 BPP 扩展点与事务失效 讲清元数据修改与实例包装差异(表 40),熟练定位事务失效根因
16 Spring Boot 启动与配置就绪治理 讲清配置覆盖优先级、自动装配导入机制,区分存活探针与就绪探针
17 泛型、擦除、桥接方法与标准库边界 讲透 PECS、编译器桥接方法合成、equals/hashCode 对象契约、BigDecimal 比较
18 集合视图、fail-fast 与异常资源规范 说明 ConcurrentModificationException 局限、只读视图陷阱、try-with-resources
19 时间时区、金额规范与安全序列化 掌握 Instant/ZonedDateTime、BigDecimal 规范、序列化跨版本兼容原则
20 中断、取消与超时预算传递 讲清协作式中断处理、取消信号下发、RPC/Client 逐层递减的超时体系
21 死锁、活锁排查与连接池级联耗尽 熟练分析 jstack 死锁日志,阐述 Tomcat 线程池与 HikariCP 级联枯竭风险
22 微服务治理组件核心原理 讲清 Nacos (Distro/Raft)、Sentinel SlotChain 流控、Dubbo SPI @Adaptive
23 网络 IO 演进与 HTTP/2/3 深入 讲透二进制分帧多路复用与 QUIC 特性(表 51),熟知请求分阶段耗时排查
24 DDD 战略建模与战术聚合根设计 讲透业务复杂度拆分、限界上下文划分、防腐层与聚合根一致性边界
25 业务幂等性深度设计方案 讲清客户端幂等键、Redis 防并发与数据库唯一约束的防穿透原子兜底
26 系统设计题标准化答题步骤 严格遵循“需求澄清 \(\to\) 容量估算 \(\to\) 架构设计 \(\to\) 容灾演进”输出指标

P0 清单:已完成 0 / 26 项。勾选状态仅保存在当前浏览器。


表 25:P1 栈打勾清单(24 项)

完成 序 复习条目 完成标准
1 MySQL 索引底层与调优 解释最左前缀、覆盖索引、索引下推、EXPLAIN 执行计划各字段深度含义
2 MVCC 与 Next-Key Lock 解决幻读 区分快照读与当前读两条避免幻读的路径(表 13),讲清间隙锁原理
3 MySQL 日志体系与两阶段提交 熟练画出 Undo、Redo(Prepare/Commit)、Binlog 写入过程与崩溃恢复判断
4 分库分表、不停机迁移与数据归档 阐明冷热分离、双写对账迁移方案;规避 ShardingSphere Full Route 陷阱
5 分区表与大表在线 DDL 方案 讲透分区表边界;熟练运用 gh-ost/pt-osc 流程,防范 MDL 锁阻塞(表 41)
6 数据库备份恢复与业务不变量防护 阐述 RPO/RTO/PITR 恢复;给出防止库存超卖的数据库原子条件更新语句
7 Redis 底层编码与持久化选型 讲透跳表/listpack、RDB+AOF 混合持久化、哨兵与 Cluster 16384 槽机制
8 缓存雪崩/击穿/穿透与双写一致性 阐明互斥重建、随机抖动、布隆过滤器;讲透 Canal 异步 Binlog 删除
9 Redis 分布式锁边界与 Big Key 讲清 Watchdog 续期、fencing token、DB 兜底及 String big key 的 lazyfree 限制
10 MyBatis 执行链路与注入边界 讲清从 Mapper 到 JDBC 路径;指出 #{} vs ${} 注入风险与二级缓存禁用原因
11 分布式事务选型与轻量方案 讲清 XA/AT/TCC/Saga 区别(表 19);重点掌握 Outbox 本地消息表模式
12 异地多活单元化架构 讲清用户路由闭环、全局数据分离、Binlog 来源标签防回环死循环与多机房冲突裁决(表 60)
13 HTTPS 下 sendfile 零拷贝失效与 kTLS 解释开启 TLS 导致传统 sendfile 失效原因,阐述 Linux 内核 kTLS 加密下沉(表 59)
14 重试机制与重试风暴治理 阐述指数退避加 Jitter 算法原理,说明全链路重试预算设计
15 分布式定时任务与状态机补偿 讲透调度与执行解耦、任务分片断点续跑,以及有限状态机防并发流转
16 分布式 ID 方案综合对比 对比雪花算法(含时钟回拨处理)、号段模式与业务流水号优缺点(表 56)
17 消息队列高级特性横向对比 讲清 RocketMQ 事务/延迟消息、RabbitMQ Quorum Queue、Pulsar 存算分离
18 K8s 资源调度与 OOMKilled 治理 掌握容器内存 limit 对齐公式、CPU limit 与 ActiveProcessorCount 配置
19 现代发布工程与回滚兼容性 熟练阐述 GitOps (ArgoCD) 同步机制,运用 Expand-Contract 保证数据回滚兼容
20 Linux 生产资源排障矩阵 熟练运用 top, iostat, vmstat, ss, pidstat 排查系统瓶颈(表 57)
21 SRE 指标体系与事故闭环复盘 讲透 RED/USE 方法论、SLO 错误预算燃烧率告警与故障复盘行动项闭环
22 供应链依赖安全与 SBOM 讲透 Maven 仲裁规则、BOM 管控、依赖冲突定位与 CVE 自动化检测流水线
23 Web 应用高危漏洞深度防御 详细阐述 SSRF 校验闭环、SQL 参数化、文件安全上传与反序列化防御
24 细粒度对象鉴权与测试工程防线 讲透 BOLA 对象级水平越权校验;阐明测试金字塔、ArchUnit 与 Testcontainers

P1 清单:已完成 0 / 24 项。勾选状态仅保存在当前浏览器。


表 26:P2 栈打勾清单(13 项)

完成 序 复习条目 完成标准
1 Spring AI 与 LangChain4j 讲清 Java AI 定位,掌握三层抽象、Advisor 执行顺序与选型考量
2 模型上下文协议(MCP)架构 讲清 Host、Client、Server 三角色及 Resources、Prompts、Tools 三原语交互(表 61)
3 向量语义缓存(Semantic Cache) 阐述基于余弦相似度的问答缓存架构,掌握前置租户隔离与时效性穿透策略
4 RAG 检索增强架构与数据治理 讲清切分策略、混合检索、重排与权限前置预过滤的必要性
5 大模型 API 接入治理与成本控制 给出包含首包超时、输入输出截断、Token 监控与结构化输出校验方案
6 Agent 工具调用安全与防注入 讲清白名单、参数校验、Prompt Injection 防御与人工确认兜底机制
7 Java 8 \(\to\) 25 LTS 特性演变 掌握 Records、模式匹配、虚拟线程、紧凑对象头等生产评估标准
8 GraalVM AOT 与 Project Panama 讲透 AOT 反射代价与选型 ROI,说明 Panama FFM API 替代 JNI 机制
9 Flink on K8s 与流计算管道 讲清 RocksDB 状态后端、端到端 Exactly-Once 语义与 Checkpoint 调优
10 国密算法与金融合规安全 掌握 SM2/SM3/SM4 应用、等保 2.0 三级要求、数据分类分级合规落点
11 技术路线图规划与 ROI 评估 能用量化数据说明一项架构改造的商业收益与投资回报周期
12 研发效能与团队梯队建设 能设计适合本团队阶段的导师制、代码评审、复盘与知识共享机制;如借用 7-2-1 等比例,需说明它仅是讨论起点,并用实际团队目标验证。
13 复杂技术选型决策树模型 给出一次基于性能压测、维护成本、团队能力加权评估的真实选型过程

P2 清单:已完成 0 / 13 项。勾选状态仅保存在当前浏览器。


10. Java 面试技术栈总清单(最终核对版)

10.1 P0:核心必备

表 27:P0 核心栈总清单与必须讲清的问题

技术域 详细技术栈 面试必须讲清的问题/证明材料
Java 语言核心与集合 集合全量体系原理(HashMap/LinkedHashMap/TreeMap/ConcurrentSkipListMap/WeakHashMap/IdentityHashMap/ArrayList/LinkedList/CopyOnWriteArrayList/ArrayDeque/PriorityQueue)、泛型/擦除/桥接、equals/hashCode 对象契约、集合只读视图、fail-fast、异常链与 AutoCloseable、时间时区、BigDecimal、序列化兼容 为什么泛型不能 new T;HashMap 扰动函数数学依据;(e.hash & oldCap) == 0 判定原理;泊松分布与树化阈值 8;LinkedHashMap LRU 钩子;跳表无锁并发删除;可变 Key 对 HashMap 破坏;subList 内存泄漏;BigDecimal 的 equals 与 compareTo 区别;受检 vs 非受检异常设计;时间存储统一规范;跨版本序列化演进原则(表 64)
JVM 机制 运行时内存、JMM、happens-before、全量十款 GC(Serial/ParNew/Parallel/CMS/G1/ZGC/Shenandoah/Epsilon)、三色标记机制与漏标充要条件、TTSP 与可数循环安全点陷阱、Glibc Arena 膨胀与 jemalloc、类卸载、Metaspace OOM、JIT 内联与去优化 脱手画 JMM 与内存模型;讲清十款 GC 对比(表 63);CMS 增量更新 vs G1 SATB vs ZGC 读屏障自愈的深层区别;结合 Safepoint 统计定位 TTSP;使用 pmap/smaps 对照 RSS、映射区和分配器指标,排查 Arena/内存碎片造成的差异;类卸载三大条件;去优化导致 CPU 瞬时打满排查;GC 选型决策逻辑(表 36)
并发与 JUC volatile 屏障、CPU 伪共享与 Disruptor 环形队列、CAS 与 ABA、AQS、三组件区别、线程池参数与饱和度监控、中断与超时传播、死锁与资源饥饿、虚拟线程与 ScopedValue volatile 为什么不能保证复合操作原子性;MESI 协议缓存行颠簸与 @Contended 内存填充;CountDownLatch 与 CyclicBarrier 区别(表 39);线程池无界队列风险;协作式中断处理原则;避免父子任务共用线程池死锁;虚拟线程迁移准则
Spring 生态Bean 生命周期、依赖解析与三级缓存、BFPP/BPP、AOP 代理、事务传播/回滚/隔离、Boot 自动配置与配置绑定、MVC 请求链、Security 认证授权、Cache、异步/定时、测试分层与主流生态模块为什么二级缓存不够;AOP 代理在 BPP 哪一步创建(表 40);事务自调用/受检异常/跨线程为什么失效;自动配置如何条件生效;Filter 与 Interceptor 区别;JWT 认证与对象级授权边界;长事务如何耗尽连接池;启动/就绪探针区别
网络与 IO TCP/HTTP/HTTPS、HTTP/2 二进制分帧、HTTP/3 QUIC、HTTPS 下 sendfile 零拷贝失效悖论与 Linux kTLS、HikariCP 并发与泄漏检测、全链路超时预算传递、全链路分阶段排查链路 HTTP/2 多路复用如何解决应用层队头阻塞;QUIC 为什么用 UDP;为什么开启 TLS 传统 sendfile 会失效,kTLS 如何在内核直接加密恢复零拷贝(表 59);HikariCP 泄漏检测机制;请求分阶段排查流程
微服务与中间件Nacos (Distro/Raft)、Sentinel SlotChain、Dubbo SPI 与 @Adaptive、Sidecar vs Proxyless Mesh;Kafka、RocketMQ、RabbitMQ、Pulsar 核心机制;Spring Kafka/AMQP/Cloud Stream、JMS 与可靠消息模式Nacos AP/CP 边界;Dubbo SPI 扩展机制;Kafka 零拷贝与 ISR/位点;MQ 防丢、防重、顺序、ACK/offset、重试/DLQ、Outbox/CDC/幂等;区分 Broker、客户端、集成框架与流处理工具
系统设计与架构 DDD 战略战术建模、业务幂等性深度设计、架构决策记录(ADR)、系统设计题标准化流程 DDD 聚合根与事务边界;全局幂等键与数据库唯一约束原子兜底;ADR 模板要素;秒杀/订单系统信封背面容量估算与容灾降级路径

10.2 P1:资深岗位常见的进阶栈

表 28:P1 进阶栈与建议掌握深度

技术域 详细技术栈 建议掌握深度
分布式多活与容灾 异地多活单元化架构(Cell-based)、跨中心流量闭环、Binlog 防回环死循环、跨地域冲突裁决 能讲清路由闭环、全局数据与单元数据划分;掌握 CDC 来源打标防死循环同步;掌握 LWW、向量时钟与状态机冲突裁决(表 60)
分布式事务 本地事务、Outbox 本地消息表、事务消息、TCC、XA、Seata、最大努力通知 能按一致性、侵入性、吞吐量和成本选型;讲清 AT 模式全局锁与 Outbox 优势
数据架构与治理 分库分表、冷热分离、双写对账迁移、分区表代价、大表 DDL 四层方案(表 41) 讲清迁移步骤与回滚路径;掌握 gh-ost 流程与防范 MDL 锁链式阻塞
缓存架构 Redis 混合持久化、Cluster 16384 槽、Canal 异步删缓存、String big key 异步边界 给出持久化与高可用选型结论;讲透锁续期与 DB 约束兜底;掌握大 Key 治理
可观测性与 SRE RED/USE 指标设计、Prometheus、SkyWalking、OTel、SLO 燃烧率告警、事故复盘 RCA 能从指标到链路定位根因;讲清 eBPF 与 Agent 分工;熟练设计降噪告警
云原生容器平台 K8s 资源调度、OOMKilled 排查四步、堆外对齐公式、ActiveProcessorCount 对齐 能排查容器 Crash 与 137 退出码;掌握 CPU/内存配额与 JVM 参数对齐
现代发布与供应链 GitOps (ArgoCD)、Expand-Contract 模式、Maven 仲裁、BOM 治理、CVE/SBOM 扫描 保证发布可回滚与数据库变更兼容;定位依赖冲突并建立安全准入防线
生产系统排障 Linux 14 大核心诊断工具(top/iostat/vmstat/ss/strace)、JFR、MAT 堆转储 能通过系统级证据链排查 CPU 100%、I/O 阻塞、CLOSE_WAIT 与死锁

10.3 P2:按行业与岗位选择

  • AI 企业应用:大模型 API 接入治理、Spring AI 三层抽象与 Advisor 执行顺序、模型上下文协议(MCP 架构:Host/Client/Server 与 Resources/Prompts/Tools 三类服务端原语)、向量语义缓存(Semantic Cache 降本提速架构)、RAG 权限预过滤、Agent 工具调用白名单与 Prompt Injection 防御。
  • 大数据与实时计算:Flink on K8s、增量 Checkpointing、RocksDB 状态后端、端到端 Exactly-Once。
  • 金融/政企/信创:国密 SM2/SM3/SM4、等保 2.0 三级、敏感数据审计、BOLA 对象级鉴权。

10.4 资深岗位候选人建议准备的面试题型

  • 源码与机制题:AQS 三组件模式与 state 差异?Spring 三级缓存为什么二级不够?MySQL MVCC 与幻读两条路径?ZGC 染色指针与读屏障?泛型类型擦除与桥接方法?可数循环为什么没有安全点?CPU 伪共享是如何让多核心并行退化的?HashMap 为什么用扰动函数,高低位指针分流判定条件是什么?三色标记漏标充要条件与并发屏障如何破解?
  • 故障诊断题:CPU 100% 排查步骤?Tomcat 线程打满与 HikariCP 级联枯竭?K8s OOMKilled 退出码 137 排查?Metaspace OOM 怎么排查?NMT 统计正常但容器 RSS 持续飙升如何用 pmap 诊断 Glibc Arena 空洞?ArrayList subList 引发内存泄漏与 CME 怎么排查?
  • 系统设计题:订单支付中心设计?秒杀库存一致性保证?短链系统?先做容量估算,再讨论幂等、状态机、容灾降级。
  • 架构演进与治理题:遗留系统重构绞杀者模式落地四问?数据库跨版本变更 Expand-Contract 模式?多模块依赖腐化治理与 ADR 落地?异地多活单元化如何防止跨机房回环同步死循环?

10.5 复习优先级与节奏建议

  • 第 1—2 周(P0 原理深度与硬件级底层):Java 核心与集合底层源码剖析(HashMap/LinkedHashMap/跳表/subList/ArrayDeque)、JMM 与并发正确性、全量十款 JVM 调优与三色标记、TTSP 与可数循环、Glibc Arena 排查、Spring 源码机制、CPU 伪共享与 Disruptor。
  • 第 3—4 周(分布式高可用、单元化与数据架构):MySQL 调优(MVCC、日志、大表 DDL、备份恢复)、异地多活单元化设计与防回环同步、Redis 缓存一致性、消息队列可靠性、分布式事务、网络超时预算体系、HTTPS 零拷贝 kTLS、分布式幂等与状态机。
  • 第 5 周(生产实战与项目复盘):打磨 11 个核心生产实战案例(0.5);演练 Linux 性能排查工具链矩阵;复练系统设计黄金九步法(0.4)。
  • 第 6 周(目标岗位定制与前沿 AI 冲刺):按投递岗位深入云原生 K8s、AI 大模型工程化(MCP 协议与语义缓存)或金融安全;对照 10.6 自检表逐项闭卷自测。

10.6 投递前自检标准

投递前自检:已完成 0 / 28 项。状态保存在当前浏览器。

  • 能用 3 分钟清晰阐述个人技术定位、技术专长及目标岗位匹配度。
  • 能用 10 分钟按照“黄金九步法”(0.4)深入复盘一个主导的复杂系统架构。
  • 能背诵并默写 11 个生产实战案例库(0.5)中的核心参数、监控指标与调优数据。
  • 能讲透并发三大特性底层根因、happens-before 规则,以及 volatile 内存屏障语义。
  • 能讲清 CPU 缓存行伪共享机制、MESI 颠簸原理,以及 Disruptor 如何利用填充消除锁争用。
  • 能完整讲透全量十款垃圾收集器工作机制(表 63),熟练说出三色标记漏标充要条件及三大并发屏障破局方案。
  • 能讲透 TTSP 概念,说明可数循环为什么导致全局超长 STW,以及条带化优化的作用。
  • 能讲清 Glibc ptmalloc 的 Arena 机制如何导致堆外内存虚高,并给出 jemalloc 替换方案。
  • 能深入讲透 HashMap 扰动函数数学原理、高低位指针扩容 (e.hash & oldCap) == 0,以及泊松分布推导树化阈值 8。
  • 能讲清 LinkedHashMap LRU 实现、跳表并发无锁删除、WeakHashMap 懒清理、subList 内存泄漏及 ArrayDeque 位运算。
  • 能讲清泛型擦除、编译器桥接方法,以及可变 Key 对 HashMap 的破坏性影响。
  • 能讲清 CountDownLatch / CyclicBarrier / Semaphore 的 AQS 模式与 state 差异(表 39)。
  • 能讲清 BFPP 与 BPP 区别(表 40),指出 AOP 动态代理是在哪一步生成的。
  • 能讲清 Spring 事务自调用失效原因,以及长事务如何引发 Tomcat 与连接池级联崩溃。
  • 能讲清为什么开启 HTTPS 会导致传统 sendfile 零拷贝失效,以及 Linux kTLS 如何恢复零拷贝。
  • 能讲清一条 SQL 从 MyBatis Mapper 到 JDBC 的完整路径,以及二级缓存禁用原因。
  • 能讲清 MySQL MVCC、两阶段提交、崩溃恢复判定,以及防止库存超卖的数据库原子条件更新。
  • 能讲清异地多活单元化架构的流量闭环设计,以及如何通过来源打标阻断 CDC 回环死循环同步。
  • 能讲清分布式锁为什么只是性能优化,核心正确性如何通过 DB 唯一键/CAS 兜底。
  • 能讲清业务幂等性如何设计,说明为什么仅靠 Redis SETNX 无法保证绝对原子性。
  • 能讲清重试风暴成因,并阐述指数退避加 Jitter 算法与全链路重试预算。
  • 能讲清 K8s OOMKilled (Exit Code 137) 排查链路、容器内存对齐公式与 CPU 核数限制。
  • 能讲清 Expand-Contract 模式如何解决跨版本数据迁移与发布回滚兼容性。
  • 能熟练运用 Linux 性能诊断矩阵工具(top/iostat/vmstat/ss)定位系统瓶颈。
  • 能讲透 SSRF 漏洞的内网 IP 深度校验闭环,以及 BOLA/IDOR 对象级水平越权防御。
  • 能讲清测试金字塔结构,说明 ArchUnit 架构单测与 Testcontainers 集成测试的价值。
  • 能讲清模型上下文协议(MCP)的三大角色与三原语,说明向量语义缓存如何为企业 LLM 降本。
  • 能说清本报告涉及的两套口径:表 2 是技术域复习优先级,第 10 章是面试必备清单,避免口径混淆。

10.7 数据结构、算法与海量数据题型核对

两份参考资料都把数据结构、排序/搜索和海量数据处理列为独立能力域。资深业务后端不一定每天手写复杂算法,但应能估算复杂度、选择结构、识别内存边界,并给出可扩展的分布式处理思路。

表 89:常见数据结构的复杂度与适用边界

结构/算法复杂度与适用场景面试/工程落点
数组 / 动态数组按下标访问 O(1),中间插入/删除通常 O(n);连续内存局部性好但扩容可能复制。ArrayList、容量预估、批量添加、拷贝和 subList 视图边界。
链表 / 栈 / 队列 / 双端队列链表按节点定位 O(n);已知节点的局部插入可 O(1)。栈/队列是访问语义,底层可由数组或链表实现。用 ArrayDeque 实现普通栈/队列通常优先于遗留 Stack/LinkedList,但根据 null 语义和实际负载选择。
哈希表 / 集合理想分布下查找插入平均 O(1),极端冲突、哈希质量和扩容会改变成本。equals/hashCode 契约、可变 key、容量/负载因子、碰撞治理与并发安全。
平衡树 / B 树 / B+ 树红黑树等平衡搜索树通常 O(log n);B+ 树通过页式节点与有序叶子链更适合数据库磁盘/页访问模式。比较树高、范围查询、磁盘页、缓存局部性;别只用“大 O 一样”判断数据结构性能。
堆 / 优先队列堆顶读 O(1),插入/删除堆顶 O(log n),构建堆可 O(n)。Top-K、合并有序流、调度优先级;区分最大堆/最小堆与“保留最大的 K 个”时堆顶应是谁。
Trie / Bloom Filter / BitmapTrie 面向前缀;Bloom Filter 节省空间但存在假阳性;Bitmap 对有限整数域的成员关系和计数高效。说明内存估算、数据域上限、删除限制、假阳性成本和精确性要求。
图与搜索DFS/BFS 通常 O(V+E);拓扑排序适合 DAG 依赖;Dijkstra 适用于非负边权的最短路径。处理访问标记、环检测、断连图、路径还原与复杂度;无权最短路通常用 BFS。

表 90:排序、搜索与海量数据题型

题型推荐思路关键陷阱
排序算法对比记住冒泡/插入/选择、归并、快速、堆、计数/基数排序的平均/最坏复杂度、额外空间与稳定性。归并通常稳定但需要额外空间;快速排序平均 O(n log n)、最坏 O(n²);堆排序 O(n log n) 且一般不稳定。按输入分布与内存限制选。
二分查找先定义区间不变量(左闭右闭或左闭右开),再确定循环终止、边界返回和中点计算。大量 Bug 来自边界定义不一致、重复元素、溢出与死循环,而不是算法大方向。
Top-K / 高频元素小顶堆维护 K 个最大值,或用分桶/频次计数后局部聚合;分布式场景各分片先取局部候选再合并验证。区分“前 K 个元素”和“频率最高的 K 类”;内存受限时结合分治、Hash 分桶、外部排序。
大文件 / 海量日志分块、哈希分桶、MapReduce/流式聚合;对精确统计采用可验证的分区与合并,对近似统计选合适概率数据结构。要交代单条记录上限、内存预算、倾斜 key、磁盘 I/O、重复记录、排序/去重语义和失败重跑。
精确与近似统计HashSet/排序可精确去重;Bitmap 适合有限整数域;Bloom Filter 判定可能误报;HyperLogLog 估计基数但不输出精确集合。先说明业务是否容许误差,再选择数据结构;不能只说“节省内存”而不交代误差、删除能力与适用数据域。
常见算法模式双指针、滑动窗口、前缀和、哈希计数、单调栈/队列、BFS/DFS、回溯、贪心、动态规划、KMP。复习时为每种模式准备 1 道模板题,并讲清不变量、终止条件、时间/空间复杂度与反例。

10.7.1 上传资料中的经典算法补充:排序、图、回溯与动态规划

上传 PDF 第 21 章(目录标注页 232–244)列出二分查找、冒泡/插入/快速/希尔/归并/桶/基数排序,以及剪枝、回溯、最短路径、最大子数组、最长公共子序列和最小生成树。原报告的海量数据表已经覆盖通用模式,本节补齐这些经典算法题的复杂度和适用前提。

表 108:经典算法题型与复杂度边界

题型/算法典型复杂度与前提易错边界
二分查找O(log n),要求数据有序或满足单调谓词。明确闭区间/半开区间不变量、重复值返回策略与中点溢出;旋转数组等变体需先说明单调区间。
冒泡/插入/希尔排序冒泡通常 O(n²);插入平均/最坏 O(n²),近乎有序时表现好;希尔复杂度依赖 gap 序列。适合解释排序原理,不应把简单排序当作大数据通用方案;稳定性、原地性和输入分布要分开讲。
快速/归并/堆排序快速排序平均 O(n log n)、最坏 O(n²);归并 O(n log n) 但通常需要额外空间;堆排序 O(n log n) 且通常不稳定。随机化/三数取中可降低快速排序退化风险;归并常用于稳定排序与外部排序;堆适合在线 Top-K。
桶/计数/基数排序在键域或分布满足假设时可接近 O(n+k) 或 O(d(n+k))。不能把“线性时间”作为无条件结论;需要说明值域、桶分布、位数 d、额外空间与稳定性。
最短路径BFS 适用于无权图;Dijkstra 要求非负边权;Bellman–Ford 可处理负边但开销更高。说明图的方向、边权、是否存在负环、路径还原和优先队列实现对复杂度的影响。
最小生成树Kruskal 基于边排序与并查集;Prim 从顶点扩展生成树,均针对连通加权无向图。若图不连通得到的是最小生成森林;需要解释负权边不妨碍 MST 的定义。
最大子数组 / LCS最大子数组和可用 Kadane O(n);最长公共子序列经典动态规划 O(mn)。定义状态、转移、初始化与最终答案;可用滚动数组降低 LCS 的空间,但路径恢复需额外记录或策略。
回溯与剪枝枚举状态空间,常见最坏时间为指数级;剪枝通过提前排除不可能或不优分支减少实际搜索。剪枝通常不改变最坏复杂度上界;要证明剪枝正确,不能误删可能成为最优解的分支。

11. 版本说明

版本 核心演进内容
v6.2(2026-10-28)标题与岗位定位通用化:将页面主标题统一为“Java技术栈复习”,移除封面、品牌栏与章节标题中的经验年限标签;正文内嵌目录改为默认折叠,展开/收起控件、左侧智能导航、搜索、复习清单与原有技术正文继续保留。
v6.1(2026-10-28)阅读体验与正文目录优化:在内嵌目录标题下增加可访问的折叠/展开按钮;目录使用独立卡片层级,优化章节入口、次级缩进、焦点状态与窄屏显示;全文搜索排除正文目录链接,避免章节导航与正文重复命中;打印时仍可输出正文目录;统一当前版本元数据。保留 v6.0 原有技术正文、表格、代码块和左侧智能导航行为。
v6.0(2026-10-27)终极定稿与页面一致性修复:重建侧边栏与正文双套目录并使其由正文实际标题树生成;修正 7.3.1 层级、7.2.2 锚点和表格标题语义;更新当前元数据与审校说明;补充 JDK 24 JEP 484/485、Native Image/CRaC/Leyden AOT Cache 三路线、ShardingSphere 与 NewSQL 选型、HikariCP 小池原则、Prompt Caching/Structured Outputs/Graph Workflow;图表索引扩展至 145。保留 v5.9 全部原有正文、表格与代码块。
v5.9(2026-10-27)核对 v5.8 实际正文后确认 3.4.7 之后的章节已存在,未发现物理截断;保留原有正文,新增 Async-profiler/Safepoint Bias、Cleaner 堆外回收、JIT 锁消除/粗化、Spring AOT/Gateway、MySQL 8.0 优化器、Redis 6/7、HNSW/IVFFlat、TCC 空回滚/悬挂、Seata AT 修复、Cell 全局共享数据与 CQRS 投影延迟等 12 个机制级专题;图表索引扩展至 145,修正附录 F 标题层级并新增附录 G 官方参考来源。
v1 ~ v3.2 确立资深架构岗位定位与技术分级标准;校准 JMM、GC、MySQL 日志、双亲委派、Kafka 零拷贝等机制。
v3.3 ~ v3.5 补齐 ORM 执行层、依赖仲裁、共识算法、Spring AI 抽象、连接池故障、冷热分离、限流对比等决策表。
v3.8 补齐类加载器体系、集合源码、设计模式速查、HTTP/2&3、K8s 高级调度、API 设计与版本管理、性能调优方法论。
v3.9 全量整合《补充.md》:黄金九步法、11 个案例库、并发三大特性、中断与级联死锁、语言底层契约、数据库容灾 RPO/RTO、业务不变量更新、幂等与退避算法、Expand-Contract 发布、SSRF 与 BOLA 权限治理。
v4.0 补齐 TTSP 安全点陷阱、Glibc Arena 堆外虚高排查、CPU 缓存行伪共享 Disruptor 架构、HTTPS 零拷贝 kTLS 架构、异地多活单元化闭环防回环、模型上下文协议 MCP 与向量语义缓存(新增表 59~62)。
v4.1(架构与专家终极全量旗舰版) 本轮深度补充集合框架全量源码级下钻与全量十款 JVM 垃圾回收器横评体系:① 在 2.1.10 深度展开全量十款收集器(Serial/Serial Old、ParNew、Parallel Scavenge/Parallel Old、CMS、G1、ZGC、Shenandoah、Epsilon)运行机制与特性总表(新增表 63);② 在 2.1.11 深度剖析三色标记漏标充要条件及 CMS 增量更新、G1 SATB 与 ZGC 读屏障自愈的深层对比;③ 在 2.2.6 全量扩充核心集合底层实现(HashMap 扰动函数数学原理、高低位指针扩容 (e.hash & oldCap) == 0、红黑树泊松分布阈值、LinkedHashMap LRU 双链表、TreeMap vs 跳表无锁并发删除、WeakHashMap 引用清理、IdentityHashMap 探测、ArrayList 连续内存与 subList 绑定、LinkedList 节点膨胀、CopyOnWriteArrayList 弱一致性、ArrayDeque 位运算循环、PriorityQueue 完全二叉小顶堆,新增表 64);④ 全量同步更新第 1、9、10 章及自检清单;全报告图表扩充至 64 张表。
v4.8(2026-10-27)最终完整审校:补齐 1.2/1.3 缺失正文、修正并发/Spring/MQ 编号、恢复所有标题锚点与两级目录;核对 JDK 27.0.1.0.3、MCP 2026-07-28、Spring 执行器与 MySQL RC 锁边界;优化非技术能力章节与可交互复习清单,保全既有正文、表格、代码和参考资料。
v4.9(2026-10-27)JVM 专项深化:补全从 class 文件、类加载、运行时数据区、native 内存、对象分配、GC 屏障、JIT 与 Safepoint 的运行链路;将表 6 扩展为 JDK 8–27 逐主版本差异矩阵;新增运行时架构、版本演进维度、生产诊断命令与跨版本升级核对表。当前版本事实按官方资料核验,保留原有章节与交互。
v5.0(2026-10-27)目录结构复核:为 JDK 8–27 版本矩阵增加独立的 2.3.1 目录入口;将后续 2.3 小节顺延;统一并发章节从 2.2.1 起编号并同步锚点;澄清 JVM 垃圾收集器子标题与第 7 章跨领域补漏范围;将 Java 语言核心机制调整到字节码增强与设计模式之前。保留所有既有正文、表格、代码块及交互功能。
v5.1(2026-10-27)补齐 Spring Core/Boot/MVC/Security/事务/数据访问/测试与生态矩阵;扩展 Kafka、RocketMQ、RabbitMQ、Pulsar、JMS/Artemis、云托管 MQ,以及 Spring 集成框架、Outbox/CDC/幂等、运维故障场景;更新侧边目录和正文目录。
v5.2(2026-10-27)目录与知识点终审:将 Java 集合框架归入语言/标准库章节并修正并发编号;MQ 按通用模型、可靠性、Kafka 概览和产品专题重排;补足微服务治理与 RPC 框架选型;更新 Spring 与主流 MQ 官方版本快照;修正审校基准与图表索引说明。静态核对标题、重复 ID、锚点、代码块、复习清单与脚本语法,保留原有代码块与表格。
v5.3(2026-10-27)依据 PDai《Java 全栈知识点问题汇总》和《Java 工程师成神之路》交叉核对;补充 Java 基础语义、并发 API、GoF 模式、Servlet/Tomcat、I/O 模型、Redis 高可用、ORM、工程工具、Linux/OS 与数据结构/算法;新增来源映射附录 C。
v5.5(2026-10-27)依据用户上传《JAVA核心知识点整理.pdf》(2018-04-13,283 页)进行逐章差距核对;新增反射/注解/复制、ZooKeeper、负载均衡、Netty/RPC、CDN、数据库建模、NoSQL、Gossip/NWR/一致性哈希、缓存故障、大数据平台、容器、日志、密码学、经典算法与 ML 算法地图;新增附录 D 标明源主题、落点与过时边界。保留 v5.3 原有章节、表格和代码块。

📋 附录 A:图表与专题索引

本报告当前包含 144 个 HTML table 元素:封面元数据表 1 个、正文技术表格 139 个、附录 A 索引表 1 个、附录 C/D/E 来源映射表各 1 个。逻辑图表/专题编号已扩展至 145;表 118–129 为 v5.8 深水区专题,表 130–141 为 v5.9 机制级专题,表 142–145 为 v6.0 定稿补充。逻辑编号与 DOM 表格元素数量不必机械相等。

编号 图表/专题标题
1 五类目标岗位与其考察重点
2 Java 技术栈全景(按优先级分层)
3 P0 主题的三层追问落点
4 JVM 栈复习条目
5 并发栈复习条目
6 JDK 8–27 核心功能演进全景
7 Spring 栈复习条目
8 Spring Cloud Alibaba 组件栈
9 Dubbo SPI 与 JDK SPI 五维对比
10 四款消息中间件考察侧重
11 网络与 IO 最小必讲集合
12 MySQL 栈复习条目
13 隔离级别、读类型与幻读两条路径
14 Redis 栈复习条目
15 缓存一致性四种方案
16 big key 与热 key 的危害与处置
17 DDD 栈复习条目
18 分布式组件栈复习条目
19 分布式事务四模式选型
20 云原生栈复习条目
21 大数据栈复习条目
22 Java AI 栈复习条目
23 安全与工程质量栈复习条目
24 P0 栈打勾清单(26 项)
25 P1 栈打勾清单(24 项)
26 P2 栈打勾清单(13 项)
27 P0 核心栈总清单与必须讲清的问题
28 P1 进阶栈与建议掌握深度
29 MyBatis 核心机制与 资深岗位追问落点
30 共识算法谱系速查
31 依赖仲裁与冲突解决
32 Spring AI 三层抽象与工程化治理
33 HikariCP 与 HTTP 客户端的故障模式
34 冷热分离的触发信号、实现方式与迁移一致性
35 监控指标设计与告警策略
36 GC 选型决策表
37 单机 vs 分布式限流方案对比
38 ShardingSphere 跨分片查询三个高频坑
39 AQS 三组件对比
40 BFPP 与 BPP 对比
41 大表 DDL 四层方案
42 JIT 编译器深入:C1/C2/分层编译/方法内联/去优化
43 Java 21/25 新特性深入:Pattern Matching/Record Patterns/Sequenced Collections
44 Project Panama FFM API:告别 JNI 的安全原生交互
45 响应式编程栈:Reactor/RxJava/WebFlux
46 GitOps 深入:以 Git 为唯一真相源
47 混沌工程:主动注入故障验证弹性
48 JVM 类加载器体系详解
49 Java 集合框架核心组件机制对比与高频追问
50 设计模式速查
51 HTTP/2 与 HTTP/3 协议深入
52 API 设计与版本管理
53 Kubernetes 高级特性
54 性能调优方法论
55 并发三大特性与底层解决机制
56 分布式 ID 方案综合选型
57 Linux 生产故障排查工具矩阵
58 企业级测试分层体系
59 kTLS 与传统用户态 TLS 零拷贝性能对比
60 单元化多活关键设计与冲突裁决机制
61 MCP 协议架构与通信机制
62 内存分配器 ptmalloc vs jemalloc 对比
63 十大垃圾回收器特性与选型对比总表
64 Java 核心集合容器底层原理与复杂度特性对比表
65JVM TTSP 与 Counted Loop 安全点陷阱机制表(正文 2.1.8)
66三色标记与并发屏障机制对比表(正文 2.1.11)
67JDK 26/27 新特性与版本状态表(正文 2.3.4)
68JVM 运行时全链路架构与边界
69JDK 8–27 JVM 演进主线维度比较
70JVM 生产诊断工具与命令矩阵
71Spring IoC 容器与 Bean 生命周期面试对照
72Spring AOP 代理机制与切面执行链对照
73Spring 事务传播行为与真实边界对照
74Spring MVC 请求链与参数处理对照
75Spring 数据访问、缓存与测试边界对照
76Spring 生态框架与能力分层矩阵
77MQ 通用模型与投递语义对照
78MQ 产品、客户端、集成与流处理框架矩阵
79端到端可靠消息方案选型对照
80Java 基础语义与标准库常见陷阱
81并发 API 语义与协作机制
82GoF 23 种设计模式与 SOLID 原则
83Servlet 容器与 Web 请求处理边界
84I/O 模型与网络编程核心问法
85Redis 高可用、复制与集群边界
86ORM 框架机制与选型边界
87开发工具与常用库核心边界
88Linux/操作系统基础与生产排障
89常见数据结构的复杂度与适用边界
90排序、搜索与海量数据题型
91两份经典知识图谱与本报告章节映射
92反射、注解、内部类、对象复制与序列化边界(2.4.9)
93ZooKeeper:会话、ZNode、Watch 与 ZAB(3.2.4)
94L4/L7 负载均衡、算法与入口高可用(3.2.5)
95Netty 与自定义 RPC:事件循环、编解码和请求关联(3.2.6)
96CDN、边缘缓存与源站保护(3.4.7)
97关系模型、范式、并发控制与数据库可编程对象(4.1.7)
98缓存穿透、击穿、雪崩、预热与降级(4.2.6)
99MongoDB、HBase 与 Cassandra 对照(4.3.1)
100一致性哈希、Gossip 与 N/W/R 读写法定人数(5.2.9)
101Docker/容器内部机制:Namespaces、cgroups、镜像层与网络(6.1.2)
102日志门面、日志实现与 ELK/集中式日志治理(6.1.3)
103Hadoop:HDFS、MapReduce 与 YARN(6.3.1)
104Spark:RDD、DAG、Stage、Task 与 Shuffle(6.3.2)
105Storm、Spark Streaming 与 Flink 流处理模型比较(6.3.3)
106经典机器学习算法地图(6.4.8)
107加密、哈希、签名与校验:密码学边界(7.2.1)
108经典算法题型:排序、图、回溯与动态规划(10.7.1)
109上传 PDF 章节主题与本报告处理映射(附录 D)
110Java SPI / ServiceLoader、字符串常量池与类初始化顺序
111MySQL EXPLAIN 执行计划解读与 SQL 优化证据链
112Redis 数据结构、持久化与生产命令治理
113高可用机制协同:限流、隔离、降级与恢复
114系统设计场景题案例库:订单、秒杀、短链与大数据导出
115Web 安全补漏:XXE、命令注入、路径遍历与浏览器安全
116测试开发进阶:测试替身、属性测试、变异测试与 Flaky Test
117JavaGuide 面试突击版来源主题映射与补充结果
118NUMA 调优与 JVM/容器资源证据链
119VarHandle 内存访问模式与排序语义
120JCTools 队列拓扑与并发约束
121Spring Boot + Kubernetes 优雅停机时序
122InnoDB Buffer Pool LRU 与刷脏页诊断
123Bloom/Cuckoo Filter 与缓存并发重建策略
124Redis 内部编码、持久化与生产命令治理
125MongoDB/HBase/Cassandra 存储读写路径对比
126Elasticsearch/Lucene 索引、Segment 与分页
127MyBatis 执行器、插件与缓存边界
128DDD 战略/战术模型与架构依赖方向
129Seata 四模式失败场景与工程约束
130Async-profiler 事件模式与问题定位2.1.17
131DirectByteBuffer 与 Cleaner 堆外回收链2.1.18
132JIT 锁消除与锁粗化2.1.19
133Spring AOT、Runtime Hints 与 Native Image3.1.18
134Spring Cloud Gateway EventLoop 与 DataBuffer 生命周期3.1.19
135MySQL 8.0 Hash Join、倒序/不可见索引与 JOIN 顺序4.1.12
136Redis 6 I/O 多线程与 Redis 7 Multi-Part AOF4.2.8
137HNSW 与 IVFFlat 向量索引对比4.3.3
138TCC 空回滚、悬挂与分支控制表5.2.11
139Seata AT 脏写与补偿修复闭环5.2.12
140Cell-based 单元化与全局共享数据5.2.13
141CQRS 投影延迟、读己之写与事件重放5.2.14
142Java 启动加速路线:Native Image、CRaC、Leyden AOT Cache2.3.2.1
143HikariCP 小连接池原则与定容经验式3.4.4.1
144MySQL + ShardingSphere 与 TiDB / OceanBase 选型边界4.1.3.3
145Prompt Caching、Structured Outputs 与 Graph Workflow6.4.9

📚 附录 B:核心参考文献

技术体系与规范类

存储与分布式架构类

云原生、操作系统、安全与 AI 前沿类

  • Linux Kernel Documentation:Kernel TLS (kTLS)、ptmalloc vs jemalloc Memory Management
  • Kubernetes 官方文档:NetworkPolicy、HPA、PodDisruptionBudget、Requests/Limits、OOMKilled 排查
  • ArgoCD 官方文档:GitOps 声明式持续交付、SyncPolicy、Self-Heal
  • Prometheus / Google SRE Workbook:RED/USE 监控方法论、SLO 燃烧率告警
  • Chaos Mesh 官方文档:Kubernetes 原生混沌工程实验平台
  • OWASP Top 10 官方文档:SSRF 深度防御、BOLA/IDOR 对象级越权漏洞防范
  • ArchUnit 官方文档:Java 架构单元测试与分层合规性约束
  • Testcontainers 官方文档:基于 Docker 的可重复真实集成测试
  • Spring AI 官方文档:ChatClient、Advisor 链执行顺序、Tool Calling、RAG 混合检索与向量库接入
  • Model Context Protocol(MCP)官方规范:Host / Client / Server 分层、Resources / Prompts / Tools 原语与当前版本变更;早期由 Anthropic 发起,当前按开放规范演进。 当前 Server 规范 · 当前版本变更记录
  • Semantic Caching 生产架构白皮书:基于向量数据库的大模型端到端提速降本工程规范
  • JavaGuide 面试突击版:面试知识点总目录(本轮交叉核验来源,访问日期 2026-10-27)


📚 附录 C:经典知识图谱交叉核验与增补说明

本轮以两份资料的目录主题和问题分类作为核对基准,而不是把原文问答整段复制进本报告。PDai 的知识点问题汇总侧重“问题—追问”的面试复习清单;《Java 工程师成神之路》按照基础、底层、进阶、高级、架构和扩展逐层组织知识地图。v5.2 已覆盖它们的多数主干,因此本轮主要补足原文中缺少或没有形成成体系对照的边界点。

来源主题映射与本报告补充位置

表 91:两份经典知识图谱与本报告章节映射

主题领域来源范围本报告落点本轮处理
Java 基础 / 面向对象 / 值传递 / 时间与编码 / BigDecimal《成神之路》基础篇;PDai Java 基础问题汇总2.4.8;2.4.6;2.4.3补齐值传递、重载/重写、final 家族、浮点/金额、字符集与日期格式陷阱;其他基础点与已有专题交叉链接。
并发原理 / ThreadLocal / 线程池 / FutureTask / Phaser / ExchangerPDai 并发问题汇总;《成神之路》Java 并发编程2.2.10 与 2.2.1–2.2.9集中整理 API 语义、取消、中断、线程池场景与协作同步器,避免只背类名。
JVM / GC / 类加载 / JIT / 工具链PDai JVM 与故障排查;《成神之路》底层篇2.1.4、2.1.7、2.1.12–2.1.15已有章节覆盖主体;版本新旧差异以本报告的 JDK 8–27 矩阵为准,不沿用旧资料中已过时的默认行为。
I/O 模型 / TCP / HTTP / DNS / Cookie/Session / Web 容器PDai 网络与 I/O;《成神之路》网络编程和 Servlet/Tomcat3.4.6;3.1.15;已有 3.4.1–3.4.5在 HTTP/2/3 与连接池深挖外,补充经典 I/O 模型、Reactor、半包粘包和容器线程边界。
设计原则 / GoF 设计模式 / Spring 的模式应用《成神之路》进阶篇:设计模式2.6.1 与现有表 50补齐创建型、结构型、行为型 23 种模式分类和 SOLID,不复制原书段落。
数据库 / ORM / Redis / 缓存 / 分布式事务PDai 下篇开发基础与架构;《成神之路》数据库和架构篇4.1、4.2、4.2.5、4.4.1、5.2原有 MySQL、缓存与可靠性内容保留;补足 Sentinel/Cluster 的故障窗口与 Hibernate/JPA 的状态/缓存/懒加载边界。
Git / Maven/Gradle / 常用库 / 源码阅读PDai 开发工具;《成神之路》工具与源码阅读7.1.1 与 7.1在依赖仲裁/供应链安全基础上增加 Git 回退语义、构建可复现性、Lombok/MapStruct 和 JSON 反序列化风险。
数据结构 / 排序 / 搜索 / 海量数据PDai 算法与大数据处理;《成神之路》数据结构与算法10.7;与 2.4 集合源码专题联动新增复杂度/结构选择矩阵、Top-K、外部排序、Bloom Filter/Bitmap/HyperLogLog 的精确性边界。
Linux / OS / 生产性能诊断《成神之路》操作系统和性能优化;PDai 故障排查与开发基础6.5.4;已有 2.1 与 6.5.2补齐 Load Average、文件描述符、删除仍打开文件、TERM/KILL、IPC 和虚拟内存口径。
架构 / 安全 / 微服务 / 可观测性 / AI两份资料的架构、安全、高并发、高可用与扩展篇主题第 3、5、6、7 章,尤其 3.2、5.2、6.4、7.2–7.6v5.2 已有系统性覆盖;本轮不再重复列一份相同清单,版本敏感点按当前章节与官方资料复核。

来源链接与使用边界

来源使用说明

来源归纳:本附录保留原资料的主题层级和重点方向,并映射至本报告章节。本报告扩展:表格中的对比结论、生产边界、诊断方法与较新的版本状态由本报告重新归纳;若原资料未涉及某个具体实现细节,不应把该细节误认为原文原句或原作者结论。版本敏感内容以本报告的 JDK 8–27 对照和对应官方文档为准。

📚 附录 D:基于《JAVA核心知识点整理.pdf》的交叉提取与补充

本附录以用户上传的《JAVA核心知识点整理.pdf》为依据。文件元数据显示创建于 2018 年 4 月 13 日,共 283 页;本轮提取的是其章节主题与可复用知识框架,不是对原文的整段复制。表中“目录页”沿用 PDF 目录标注页码,实际 PDF 物理页可能因前置目录页而不同。

来源主题映射与处理结果

表 109:上传 PDF 的章节主题与本报告处理映射

PDF 章节(目录页)主题提取本报告落点本轮处理
2 JVM(19–44)运行时区域、GC、引用、类加载、IO/NIO2.1、2.3、3.4.6已有系统性专题;不重复复制旧版分代与收集器描述。
3–5(45–115)集合、并发、异常、反射、注解、内部类、泛型、序列化与复制2.2、2.4.1–2.4.9前半已有深度;新增 2.4.9 统一补齐反射/注解/内部类/复制/原生序列化边界。
6 Spring 原理(116–139)IoC/AOP、MVC、Boot、JPA、MyBatis 缓存、Tomcat3.1、3.1.15、4.4.1现有 Spring 全景专题已覆盖主干;本轮不重复。
7–9(140–168)微服务、服务发现/网关/配置、Netty/RPC、TCP/HTTP/HTTPS/CDN3.2.4–3.2.6、3.4.6–3.4.7新增 ZooKeeper、负载均衡、Netty/RPC 与 CDN 边缘缓存专题。
10 日志(169–170)SLF4J、Log4j、Logback、ELK6.1.3补齐门面/实现分层、MDC、结构化日志、异步队列与敏感数据治理。
11–13(171–182)ZooKeeper/ZAB、Kafka、RabbitMQ3.2.4、3.3ZooKeeper 新增专题;Kafka/RabbitMQ 原有内容较充分,保留并交叉引用。
14–16(183–200)HBase、MongoDB、Cassandra4.3.1、6.3新增三类 NoSQL 的模型、读写路径与选型矩阵;不照搬旧版专有数据模型术语。
17 设计模式(201–202)设计原则与 GoF 模式2.6.1已在 v5.3 补齐,不重复。
18 负载均衡(203–213)L4/L7、轮询/最少连接/IP Hash、LVS、Keepalived、Nginx、HAProxy3.2.5新增算法对照和网络/健康检查的工程边界。
19 数据库(214–224)范式、ACID、存储过程/触发器、锁、分片、分布式事务、CAP4.1.7、4.1、5.2新增关系设计与并发控制边界;已有 InnoDB 与分布式事务专题不重复。
20 一致性算法(225–231)Paxos、ZAB、Raft、N/W/R、Gossip、一致性哈希5.2.2、5.2.9共识谱系已有;新增副本读写法定人数、成员传播和分片的区别。
21–22(232–254)排序/搜索/图/DP、树、红黑树、B 树、Bitmap10.7、10.7.1、2.4.1数据结构主干已覆盖;新增经典算法的复杂度、前提和题型边界。
23–24(255–258)AES/RSA/CRC/MD5、缓存雪崩/穿透/预热/更新/降级7.2.1、4.2.6新增密码学原语边界与缓存故障全景;明确 CRC 非密码学方案、MD5 不用于新安全场景。
25、28(259–262、275–277)HDFS、MapReduce、YARN6.3.1新增架构职责;纠正把 Hadoop 1.x JobTracker/TaskTracker 说成 YARN 组件的历史混淆。
26–27(263–274)Spark/RDD/DAG、Storm 的 Spout/Bolt 与分组6.3.2、6.3.3新增 Spark 计算模型与流处理引擎比较;将 Storm 作为经典/存量系统知识标注。
29(278)决策树、随机森林、逻辑回归、SVM、朴素贝叶斯、KNN、K-Means、AdaBoost、神经网络、马尔可夫6.4.8新增 P2 算法地图,适用于理解任务和模型边界,不默认要求业务 Java 工程师实现训练算法。
30(279–283)SaaS/PaaS/IaaS、Docker Namespaces/cgroups/网络/镜像层、OpenStack6.1.2、6.1.1新增容器底层机制;OpenStack 只保留为按岗位选择的 P2 认知项,不扩写成当前部署建议。

旧材料需谨慎沿用的知识点

  • JVM 与 JDK:PDF 中的永久代、扩展类加载器、偏向锁与早期 GC 组合属于历史版本语境;应以本报告 2.1/2.3 的版本矩阵为准。
  • 并发集合:PDF 中以 Segment 描述 ConcurrentHashMap,主要对应旧版实现;不要直接套用到现代 JDK 8+ 实现。
  • 大数据架构:JobTracker/TaskTracker 属于 Hadoop 1.x 经典架构;现代 YARN 角色应以 ResourceManager、NodeManager 与 ApplicationMaster 区分。
  • 密码学:CRC 主要用于检测意外错误,不具备抗恶意篡改能力;MD5 不适合新的抗碰撞安全用途,也不应直接用于密码存储。
  • 分布式协调:ZooKeeper 临时节点/选主模型不能自动阻止暂停过久的旧持有者继续写;关键资源应考虑 fencing token 或目标端条件校验。
  • 高阶专题:OpenStack、Storm、HBase/Cassandra 等知识深度应按目标岗位和实际系统决定;来源中的出现并不代表每个 Java 后端职位都要求深入掌握。

来源边界与本报告的编辑方式

本轮依据上传 PDF 的目录与正文主题进行“已有覆盖 / 缺少专题 / 需要更新边界”三类核对。PDF 里可复用的主题被重新归纳为表格和面试边界,而不是逐段转载;版本敏感或历史性描述被明确标注,并以本报告中已建立的现代 JDK、Spring、MQ 与生产治理章节为参考。对于目标岗位未使用的技术,应优先掌握概念、架构位置与选型边界,不应为了清单完整而盲目引入生产系统。


📚 附录 E:JavaGuide 面试突击版交叉核验与查漏补缺

来源入口:JavaGuide 面试突击版首页。该首页列出 Java、计算机基础、数据库与缓存、系统设计、安全、Spring、设计模式、高性能、消息队列、高可用、分布式/微服务及测试开发等主题。首页是导航目录,不等于每个子页面的全部内容。本轮对首页分类逐项映射,并阅读了其中可访问的 Java 基础、新特性、集合、JVM、Linux、MySQL、Spring、设计模式、分布式、Redis、系统设计、认证授权、安全、高性能和高可用专题;抓取失败的子页面仅按首页目录做覆盖映射,不声称已逐字核验其全文。

来源主题映射与补充结果(表 117)

JavaGuide 首页主题/专题原报告覆盖情况本轮处置对应位置/来源
Java 基础基础语义、泛型、异常、反射和序列化已有覆盖;SPI、ServiceLoader、字符串常量池/类初始化顺序缺少独立专题。新增 SPI、String 与初始化追问,避免照搬简化对象数量结论。2.4.10 · Java 基础
Java 新特性已覆盖 JDK 8–27 版本矩阵与 JVM 演进。不重复新增;提醒区分语言功能、预览/孵化状态和发行商支持。2.3.1–2.3.5 · Java 新特性
集合、并发、JVM现有内容已较深入,包括源码、JMM、AQS、诊断工具和 GC。保持原有章节,作为重点复习主干。2.1、2.2、2.4.1 · 集合 / JVM
计算机网络、操作系统、LinuxTCP/HTTP/IO、Linux 资源排查已有覆盖。保持已有网络、容器和排障主题,不重复复制面试问答。3.4、6.1.2、6.5.2–6.5.4 · Linux
数据结构与算法已有数据结构、排序、图、动态规划与海量数据题型。继续以复杂度、正确性、不变量和工程边界为主要回答要求。10.7–10.7.1
MySQL已有索引、MVCC、锁、日志、分库分表和深分页;执行计划字段与实测对照不够集中。新增 EXPLAIN 诊断矩阵和 SQL 优化证据链。4.1.8 · MySQL 面试题
Redis缓存一致性、淘汰、Sentinel/Cluster、持久化选择已有覆盖;数据结构与生产命令风险分散在多节。新增数据结构、持久化、过期与命令复杂度统一矩阵。4.2.7 · Redis 面试题
系统设计与场景题已有需求澄清、容量估算、架构决策与生产案例,但短链/秒杀/订单/导出/迁移没有集中成对照表。新增场景案例库,明确状态、一致性、失败补偿和验证指标。5.3.3 · 系统设计场景题
认证与授权、Web 安全已有 JWT、OAuth/OIDC、对象级授权和 SSRF/注入/上传等内容;XXE、命令注入、路径遍历、CORS 边界未形成统一检查表。新增 Web 安全攻击面与防御矩阵,区分认证、授权、浏览器跨域策略。7.2.2 · 认证授权 / Web 安全
Spring / Spring BootIoC、AOP、事务、自动配置、MVC、安全、Boot 与生态矩阵已有专题。不重复扩写;继续关注版本兼容、代理边界和生产故障。3.1.6–3.1.15 · Spring 专题
设计模式已整理 GoF 23 种模式与 SOLID。不新增重复目录,强调实际使用条件与替代方案。2.6.1 · 设计模式
高性能已有缓存、分库分表、CDN、限流和性能调优;复杂场景的业务链路可更具象。加入高性能订单与系统设计案例,要求给出指标和压测验证。5.3.3 · 高性能系统
消息队列Kafka、RocketMQ、RabbitMQ、Pulsar、Outbox、幂等、重试和积压已有专题。保持现有体系,不重复列产品名称;场景题中强化异步一致性与补偿。3.3.1–3.3.11
高可用已有超时、重试、限流、熔断、降级、SLO、RPO/RTO 和混沌工程,但限流算法比较与协同闭环分散。新增限流算法、舱壁隔离、降级与恢复协同表。5.2.10 · 高可用系统
分布式系统与微服务已有共识、分布式 ID、锁、事务、ZooKeeper、RPC、服务治理和多活。保持原有专题;答题时用具体失败场景解释一致性与可用性取舍。3.2、5.2 · 分布式系统
测试开发已有 JUnit、Mockito、Testcontainers、ArchUnit、Pact 和压测;属性/变异测试、测试替身边界与 Flaky Test 治理不够集中。新增测试策略与稳定性专题。该项是根据首页测试开发分类进行的通用知识补充,并非对不可访问子页的全文提取。7.4.1 · 首页测试开发入口

补充范围与使用边界

  • 来源主题以 JavaGuide 面试突击版首页目录与本轮可访问子页面为依据;站点内容可能持续更新,本文不视为对整站所有隐藏页面/付费材料的穷尽复制。
  • “原报告已有覆盖”意味着有对应知识点,不代表覆盖源站的全部细节;新增条目优先补齐显著空白与面试中常见的工程化追问。
  • 本报告是独立重组的学习手册。源站观点与本报告扩展建议会通过表格说明区分;版本、算法细节和产品行为仍应以对应官方文档及目标运行环境验证。

附录 F:机制级深水区补充与官方核验边界

本轮对易变或容易被绝对化的细节采用官方资料核验。阅读时请将以下内容视为追查入口,而不是替代生产环境验证:

本附录仅记录本轮实际核验过的外部资料;各产品的具体行为可能随小版本、发行商补丁、配置与操作系统改变。对于 UseNUMA、虚拟线程文件 I/O、JDK 容器感知和复制一致性,应以目标构建和部署环境复测结果为准。

📚 附录 G:机制级补充与官方核验来源

本附录记录 v5.9 新增的机制级专题所依据的官方/项目文档,便于按目标版本继续核查。技术结论中,JVM/HotSpot 内部实现、Spring AOT、MySQL 优化器和 Redis 持久化的细节均应以实际部署版本为准。

G.1 本轮新增专题索引

  • JVM:Async-profiler 与 Safepoint Bias、DirectByteBuffer/Cleaner 回收链、JIT 锁消除与锁粗化。
  • Spring:Runtime Hints/Native Image、Spring Cloud Gateway EventLoop 与 DataBuffer 生命周期。
  • MySQL:Hash Join、倒序索引、不可见索引与 JOIN 顺序诊断。
  • Redis/向量检索:Redis 6 I/O 线程与 Redis 7 Multi-Part AOF、HNSW 与 IVFFlat 选择。
  • 分布式可靠性:TCC 空回滚/悬挂、Seata AT 外部写冲突修复、Cell 全局共享数据、CQRS 投影延迟与重放。

G.2 官方与项目参考链接

关于 v5.8 物理截断的校验说明:对本次实际读取的 Java技术栈复习全景报告_v5.8_全篇缺口回填与深水区补全版.html 检查后,3.4.7 后仍存在 3.5、4.1–4.4、第 5–11 章及附录 A–F 的正文;未发现正文物理截断。因此 v5.9 保留了这些已存在章节,并将缺少的机制级细节作为增量内容回填。如果另有一份不同的 v5.8 副本在 3.4.7 处真的被截断,应以该副本重新做文件级对照。

G.3 v6.0 新增技术点官方核验来源

核验说明:本附录链接用于核对版本状态与实现边界。性能收益、缓存命中、连接池最优值和分布式数据库延迟都受工作负载与部署环境影响,应以目标版本压测和故障演练为准。