本附录是全书 36 章的参数与数量级收敛点,面试前用它做最后一轮记忆校准。
使用说明
本附录只做速查,不重复推导。每个数值都标注了口径或版本区间;机制细节回到对应章节。
| 你要找什么 | 去哪一节 | 对应正文章节 |
|---|
| 一次内存访问、一次 RTT 差多少倍 | A.1 | 第 1、3 章 |
swappiness、ulimit -n 该不该调 | A.2 | 第 10、12 章 |
| RAID 写惩罚怎么算 | A.3 | 第 13 章 |
MSS 为什么是 1460 | A.4 | 第 15、16、17 章 |
| InnoDB 一棵 B+ 树能放多少行 | A.5 | 第 20、23 章 |
| Redis 什么时候从 listpack 转哈希表 | A.6 | 第 27 章 |
| 32 GB 为什么是压缩指针的分界线 | A.7 | 第 32 章 |
acks=all 到底保证了几份副本 | A.8 | 第 33、34 章 |
| 502 和 504 谁该重试 | A.9 | 第 18、35 章 |
| 最后一个小时背什么 | A.10 | 全书 |
注意
本附录的"默认值"一律指上游项目的出厂值,不是"生产推荐值"。两者的差距往往就是面试的追问点:面试官问"默认值多少",接着一定问"你线上改成了多少、为什么"。
A.1 延迟数量级表(面试心算基准)
单位统一为秒的十进制前缀:1 ns = 10⁻⁹ s、1 μs = 10⁻⁶ s、1 ms = 10⁻³ s。倍率列以 L1 缓存命中为 1× 的基准。
| 事件 | 典型耗时 | 相对倍率 | 量级直觉 |
|---|
| 寄存器访问 | < 1 ns | < 1× | 与 CPU 同频 |
| L1 缓存命中 | 约 1 ns | 1× | 约 4 个时钟周期(3 GHz) |
| 分支预测失败 | 约 5 ns | 5× | 流水线冲刷,重新取指 |
| L2 缓存命中 | 约 4 ns | 4× | 约十几周期 |
| L3 缓存命中 | 约 15 ns | 15× | 跨核共享,含一致性开销 |
| 主存访问(DRAM) | 约 100 ns | 100× | 缓存未命中的代价 |
| 互斥锁加解锁(无竞争) | 约 20 ns | 20× | 一条原子指令 + 分支 |
系统调用(如 getpid) | 约 100 ns ~ 1 μs | 100~1000× | 用户态/内核态切换 |
| 上下文切换 | 约 1~5 μs | 1000~5000× | 换页表 + 寄存器 + 缓存污染 |
| 同机房网络往返(RTT) | 约 0.1~0.5 ms | 10⁵× | 约等于 1000~5000 次主存访问 |
| SSD 随机读(4 KB) | 约 100 μs | 10⁵× | NVMe 更快,见 A.3 |
| 机械盘随机读(4 KB) | 约 5~10 ms | 10⁷× | 一次寻道 + 旋转延迟 |
| 跨大洲网络往返 | 约 150 ms | 10⁸× | 光速 + 路由跳数 |
常用换算(面试官爱让现场算):
1
2
3
4
5
6
7
8
9
| 1 次同机房调用 ≈ 0.3 ms ≈ 300 000 ns
1 次同机房调用 ≈ 3000 次主存访问 ≈ 300 000 次 L1 缓存命中
1 次同机房调用 ≈ 3 次 SSD 随机读(0.1 ms × 3)
1 次机械盘随机读 ≈ 20 次同机房调用
1 次跨大洲调用 ≈ 300 次同机房调用
内存访问墙:约 100 ns
网络墙:同机房约 0.1 ms,跨地域 ≥ 30 ms(光速下限)
磁盘墙:SSD 约 100 μs,机械盘约 10 ms
|
重要
面试里最有杀伤力的一句话是:“同机房一次 RPC 的时间,等价于三千次内存访问。” 它直接解释了为什么"循环里调 RPC"(N+1 查询、循环发 MQ)是不可接受的,也解释了为什么本地缓存能把 P99 从毫秒级压到微秒级。
提示
心算口诀:主存 100 ns、SSD 100 μs、同机房 0.3 ms、机械盘 10 ms、跨洲 150 ms。相邻两档普遍差 1000 倍(主存→SSD→同机房),只有同机房→机械盘是约 30 倍。
A.2 Linux 内核参数与资源限制默认值
以下默认值以 Linux 5.x/6.x 主线内核为口径;发行版(尤其是 RHEL 系与容器镜像)常带自己的 sysctl 覆盖,容器里看到的可能是宿主机或 runtime 注入的值。
| 参数 | 默认值 | 含义 | 调它解决什么问题 | 调错的风险 |
|---|
vm.swappiness | 60 | 换出匿名页相对回收文件页的权重(0~100) | 数据库/缓存服务想优先保留匿名页,降到 1~10 | 设 0 并非禁用 swap,内存紧张时仍可能换出;设太高会让热数据被换出,延迟抖动 |
vm.overcommit_memory | 0 | 启发式过量提交:明显超额的分配才拒绝 | Redis fork 做 RDB 时被 fork 失败或 OOM 打断,可设 1 | 设 1(总是允许)会让 malloc 成功但触碰时才 OOM,进程被 OOM killer 杀掉 |
net.core.somaxconn | 4096(5.4+;更早版本 128) | listen 全连接队列上限 | 高并发短连接下 SYN 之后被丢、客户端超时 | 调大但应用 listen(backlog) 传得小,实际仍取 min;积压请求占用内存 |
net.ipv4.tcp_max_syn_backlog | 随内存变化(常见 256~1024,部分发行版 4096) | 半连接(SYN 队列)上限 | 抗 SYN Flood、抗突发建连 | 只调它不调 somaxconn 会把瓶颈从半连接挪到全连接队列 |
net.ipv4.tcp_syn_retries | 6(约 127 s 后放弃) | 主动建连 SYN 重传次数 | 缩短上游不可达时的建连等待 | 调太小会在网络抖动时误判服务不可用 |
net.ipv4.tcp_synack_retries | 5 | 被动方回 SYN+ACK 的重传次数 | 与 tcp_max_syn_backlog 配合抗 flood | 调太小会让慢客户端连不上 |
net.ipv4.tcp_tw_reuse | 0(关闭) | 允许把 TIME_WAIT 套接字复用于主动新建连(需时间戳) | 客户端侧大量 TIME_WAIT 导致本地端口耗尽 | 在 NAT 设备后或时间戳被剥离时可能收到旧连接的迟到包 |
net.ipv4.tcp_tw_recycle | 已从 4.12 起移除 | 曾用于快速回收 TIME_WAIT | —— | 不要再引用它;在 NAT 环境下会导致连接被静默丢弃 |
ulimit -n(软限制) | 1024 | 单进程可打开的文件描述符数 | 高并发下 accept 报 EMFILE、“Too many open files” | 软限制提高但硬限制没提,进程无法自行再提高;select 的 1024 上限是另一回事 |
ulimit -n(硬限制) | 常见 1048576(发行版默认 nofile),旧系统 4096 | 非 root 进程能提到和上限 | 给软限制留出提升空间 | 只改软限制是暂时的,重启或新会话后失效,需写进 limits.conf/systemd LimitNOFILE |
fs.file-max | 随内存自动计算(通常远大于 10 万) | 全系统 fd 总数上限 | 单机跑大量进程时全局 fd 耗尽 | 调太小会让提高 ulimit -n 无效,因为全局池先满 |
vm.dirty_ratio | 20(百分比) | 脏页占内存达到该值,写进程同步回写并阻塞 | 削峰:降低它让回写更早、单次阻塞更短 | 调太低会让写吞吐下降;调太高会造成长时间卡顿式回写 |
vm.dirty_background_ratio | 10(百分比) | 达到该值,后台线程开始异步回写 | 让回写更早启动,避免触顶 | 调太低会频繁唤醒回写线程,与 dirty_ratio 靠太近会失去缓冲 |
vm.max_map_count | 65530 | 单进程内存映射区数量上限 | Elasticsearch 等大量 mmap 的场景启动报错 | 调太大会增加内核 vm_area_struct 内存开销 |
net.ipv4.ip_local_port_range | 32768 60999 | 主动连接可用的本地临时端口范围 | 客户端侧短连接 QPS 高、端口耗尽 | 范围过大且 tcp_tw_reuse 关闭时会堆积更多 TIME_WAIT;扩大范围不影响其他进程已占用端口 |
警告
“提高 ulimit -n 就能解决 Too many open files” 是常见错误回答。要同时检查:软限制、硬限制、fs.file-max、进程是否被 systemd 的 LimitNOFILE 覆盖,以及是不是 fd 泄漏(用 lsof -p <pid> | wc -l 看是不是只增不减)。见第 10 章与第 13 章。
相关观测命令(口径要对):
1
2
3
4
5
6
7
8
9
| # 看进程真正的软/硬限制,而不是当前 shell 的
cat /proc/<pid>/limits | grep -i 'open files'
# 看内核实际生效的 somaxconn 与队列溢出计数
sysctl net.core.somaxconn
nstat -az TcpExtListenOverflows TcpExtListenDrops
# 脏页回写相关
sysctl vm.dirty_ratio vm.dirty_background_ratio vm.dirty_expire_centisecs
|
A.3 磁盘与文件系统
A.3.1 ext4 与 xfs 速查
| 维度 | ext4 | xfs |
|---|
| 设计取向 | 通用、成熟、工具链老牌 | 大文件、大容量、并行分配 |
| inode 分配 | 建文件系统时预分配固定数量(可 -i 调比例) | 动态分配,不易凭空耗尽 inode |
| 在线扩容 | 支持(resize2fs),缩容也支持 | 支持扩容,不支持缩容 |
| 元数据规模 | 大目录下性能下降明显 | B+ 树目录,大目录更稳 |
| 删除大文件 | 相对慢 | 相对快(延迟回收) |
| 典型场景 | 系统盘、小文件多 | 数据盘、大数据量、容器宿主机 |
A.3.2 容量与 inode 观测
| 命令 | 看什么 | 关键点 |
|---|
df -h | 块容量使用率 | 分母是数据块,与 inode 无关 |
df -i | inode 使用率 | inode 用满时 df -h 可能显示还有空间,但创建文件报 No space left on device |
du -sh <dir> | 目录实际占用 | 与 df 不一致的典型原因:文件已 rm 但被进程持有 |
lsof +L1 | 已删除仍被打开的文件 | 定位"删了文件空间没释放" |
创建 inode 数量与"平均文件大小"相关:
1
2
3
| ext4 默认 inode 数 ≈ 卷容量 / 16 KB(bytes-per-inode 默认 16384)
例:1 TB 卷 ≈ 6553.6 万个 inode
放 100 万个小文件绰绰有余;放十亿级小文件必须显式调小 -i 或改用 xfs
|
A.3.3 常用挂载选项
| 选项 | 作用 | 副作用 / 注意 |
|---|
noatime | 不更新访问时间 | 依赖 atime 的工具有影响;通常收益大于风险 |
nodiratime | 只不更新目录访问时间 | 比 noatime 保守 |
relatime | 访问时间早于修改时间才更新(现代默认) | 折中方案 |
data=ordered | 数据先落盘再提交元数据(ext4 默认) | 崩溃后不会读到"指向垃圾数据的元数据" |
data=writeback | 不保证数据先于元数据 | 吞吐略好,崩溃后可能读到旧数据 |
barrier=1/nobarrier | 是否发写屏障保证顺序 | 关闭要有电池保护 RAID 卡才安全 |
noexec/nosuid | 禁止执行/忽略 setuid | 安全加固常用 |
discard / fstrim | 向 SSD 通报无效块 | 挂载期 discard 有开销,常改为定期 fstrim |
A.3.4 RAID 级别对照(含写惩罚)
写惩罚(write penalty) 指一次逻辑随机写引发的物理 I/O 次数,是评估 RAID 随机写 IOPS 的核心:
| 级别 | 容量利用率 | 容错能力 | 随机写惩罚 | 恢复期风险 | 典型用途 |
|---|
| RAID 0 | 100%(N 块全用) | 无,坏一块全丢 | 1 | —— | 临时数据、缓存盘 |
| RAID 1 | 50% | 允许坏 1 块 | 2 | 低 | 系统盘 |
| RAID 5 | (N−1)/N | 允许坏 1 块 | 4(读旧数据 + 读旧校验 + 写新数据 + 写新校验) | 高(重建期再坏即全丢) | 读多写少的归档 |
| RAID 6 | (N−2)/N | 允许坏 2 块 | 6 | 中 | 大容量冷数据 |
| RAID 10 | 50% | 每镜像组可坏 1 块(视布局) | 2 | 低(重建只拷一份) | 数据库、高并发随机写 |
写惩罚换算有效 IOPS:
1
2
3
4
5
6
7
8
9
| RAID5 有效随机写 IOPS ≈ 物理盘 IOPS 总和 / 4
RAID6 有效随机写 IOPS ≈ 物理盘 IOPS 总和 / 6
RAID10 有效随机写 IOPS ≈ 物理盘 IOPS 总和 / 2
算例:8 块盘,单盘 150 随机写 IOPS
RAID5 ≈ (8 × 150) / 4 = 300 IOPS
RAID6 ≈ (8 × 150) / 6 = 200 IOPS
RAID10 ≈ (8 × 150) / 2 = 600 IOPS
结论:数据库随机写场景,RAID10 常以一半容量换两倍以上写 IOPS
|
A.3.5 IOPS、块大小与队列深度
| 概念 | 公式 / 口径 | 说明 |
|---|
| 吞吐 | 吞吐 = IOPS × 块大小 | 顺序大块 I/O 看吞吐,随机小块看 IOPS |
| 顺序 vs 随机 | 机械盘差 100 倍以上,SSD 差距缩小 | 用 fio 时必须声明 --bs、--rw、--iodepth |
| 队列深度(QD) | QD = IOPS × 平均延迟(Little 定律) | QD 越高越能压满设备,但延迟上升 |
| 观测 | iostat -x 的 aqu-sz(平均队列长度)、await | %util 接近 100% 不等于"设备已饱和",见第 11 章 |
| 树化阈值式的口径差异 | SSD 的 4 KB 随机读与 128 KB 顺序读是两种设备 | 报价单上的 IOPS 必须问清块大小与 QD |
A.3.6 SSD 写放大与 TRIM
| 概念 | 说明 |
|---|
| 写放大(write amplification, WA) | WA = 实际写入闪存的数据量 / 主机请求写入的数据量;WA 越大寿命越短 |
| 成因 | 闪存只能整块擦除,改一个 4 KB 页可能触发整块(通常 256 KB~几 MB)搬移与重写 |
| 缓解 | 预留空间(over-provisioning)、对齐分区、避免大量随机小写、TRIM 让主控提前知道哪些块可回收 |
| TRIM | discard 挂载选项或定期 fstrim;不 TRIM 会让 SSD 误以为数据仍有效,WA 上升 |
| 磨损均衡 | 主控把写分散到全部块上,寿命看 TBW(总写入字节数)而非通电时间 |
| 与数据库的关系 | 随机写模式最伤 SSD;redo/binlog 的顺序写远比数据页随机写友好 |
小心
说"RAID5 随机写只要 2 次 I/O"会当场暴露没算过写惩罚。记住:RAID5 是 4 次、RAID6 是 6 次、RAID10 是 2 次;这也是"数据库盘为什么不用 RAID5"的标准答案。
A.4 TCP/IP 参数与常量
A.4.1 报文头与 MTU/MSS
| 常量 | 数值 | 说明 |
|---|
| 以太网 MTU | 1500 字节 | 链路层最大传输单元 |
| IP 头最小长度 | 20 字节 | 无选项时;有选项最长 60 字节 |
| TCP 头最小长度 | 20 字节 | 无选项时;有选项最长 60 字节 |
| MSS(IPv4 常用值) | 1500 − 20 − 20 = 1460 字节 | 分段发生在传输层,分片发生在网络层 |
| MSS(含时间戳选项) | 常见协商为 1448 或更小 | 每方向独立协商,取 min(本端, 对端) |
| 最小 MSS | 536 字节(IPv4)/ 1220 字节(IPv6) | 保证任何链路都能通过 |
| IP 分片能力发现 | PMTUD,DF 位置 1 | 黑洞路由会导致"小请求通、大请求挂" |
| TCP 窗口字段 | 16 位,最大 65535 字节 | 窗口扩大因子(window scale)最大 14,即 65535 × 2¹⁴ |
为什么必须做窗口扩大:带宽时延积(BDP)决定"在途数据量"上限。
1
2
3
4
5
6
7
| BDP = 带宽 × RTT
100 Mbps × 100 ms = 10 Mb = 1.25 MB 在途
若窗口上限只有 64 KB,则吞吐上限 = 64 KB / 100 ms ≈ 5.2 Mbps
⟹ 链路再快也跑不满,所以 RFC 1323 引入窗口扩大因子
同一链接下的理论上限 = 窗口大小 / RTT
想跑满 1 Gbps、RTT 100 ms,需要窗口 ≈ 12.5 MB,远超 64 KB
|
A.4.2 TIME_WAIT 与 MSL
| 项 | 取值 | 说明 |
|---|
TIME_WAIT 时长 | 2 × MSL | 主动关闭方进入,等两个方向旧报文全部消亡 |
| MSL 常见取值 | Linux 中 TCP_TIMEWAIT_LEN 为 60 s,即 TIME_WAIT 约 60 s | Linux 不直接用 RFC 建议的 2 min MSL,而是固定 60 s |
| RFC 793 建议 MSL | 2 min(TIME_WAIT 即 4 min) | 引用规范时用 2 min,引用 Linux 行为时用 60 s |
| 端口复用条件 | tcp_tw_reuse + 时间戳 + 主动建连 | 只对客户端出向连接有意义 |
大量 TIME_WAIT 出现在服务端 | 通常是服务端主动关闭连接 | 让客户端先关(HTTP keep-alive + 超时对齐)或收敛连接数 |
A.4.3 RTO 与重传
| 项 | 取值 | 说明 |
|---|
| RTO 初值 | 1 s(RFC 6298) | 首个 SYN 与未取得 RTT 样本时用 |
| RTO 最小 | 200 ms(Linux 实现) | 防止抖动的 RTT 样本把 RTO 压得过小 |
| RTO 退避 | 每次超时翻倍,上限常见 120 s | tcp_syn_retries = 6 时首次建连约在 127 s 后放弃 |
| 平滑公式 | SRTT = (1 − α) × SRTT + α × RTT,α = 1/8 | 指数加权移动平均 |
| 偏差估计 | `RTTVAR = (1 − β) × RTTVAR + β × | SRTT − RTT |
| 重传超时 | RTO = SRTT + 4 × RTTVAR | 系数 4 保证约 99% 的样本被覆盖 |
RTO.min/RTO.max | 内核可调,常见 200 ms / 120 s | 与快速重传配合,避免长尾卡顿 |
A.4.4 拥塞窗口与阈值初值
| 项 | 早期取值 | 现代取值 | 影响 |
|---|
cwnd 初值 | 1 个 MSS(RFC 2001) | 10 个 MSS(RFC 6928,IWN10) | 同样 RTT 下首轮可发数据量差 10 倍,显著缩短短流完成时间 |
ssthresh 初值 | 65535 字节(RFC 2001) | Linux 取一个很大的值(近似无穷,首个丢包才确定) | 决定了慢启动何时切到拥塞避免 |
| 慢启动行为 | 每个 RTT 翻倍(cwnd = cwnd + MSS 每 ACK) | 同 | 指数增长,直到 cwnd ≥ ssthresh |
| 拥塞避免行为 | 每 RTT 加 1 个 MSS(cwnd = cwnd + MSS × MSS / cwnd) | 同 | 线性增长,AIMD 的加性增 |
| 快速重传触发 | 3 个重复 ACK | 同;配合 SACK 可减少重传量 | 不必等超时 |
| 快恢复(Reno) | ssthresh = cwnd / 2,cwnd = ssthresh | NewReno 改进了部分确认的处理 | 乘法减 |
| 超时重传后 | ssthresh = cwnd / 2,cwnd 回 1 MSS | 同(部分算法回 10 MSS 以内) | 回到慢启动 |
拥塞控制算法要点对照:
| 算法 | 丢包判据 | 增长规律 | 核心思想 | 已知短板 |
|---|
| Tahoe | 超时或 3 个重复 ACK | 回到 cwnd = 1 | 最早的完整实现 | 恢复太慢 |
| Reno | 3 个重复 ACK 触发快重传 | 慢启动 + 拥塞避免 | 提出快重传/快恢复 | 一个窗口多个丢包时反复减半 |
| NewReno | 改进了部分 ACK 判定 | 同 Reno | 无 SACK 也能恢复一个窗口内的多丢包 | 仍以丢包为唯一信号 |
| CUBIC | 丢包 | cwnd 按三次函数增长,先快后慢 | 以时间为轴,RTT 公平性更好 | 高丢包长肥管道上仍偏保守 |
| BBR | 不把丢包当拥塞,看带宽与最小 RTT | 探测 BtlBw 与 RTprop | 主动探测瓶颈带宽 | 与基于丢包的流共存时可能不公平 |
正确口径:cwnd 初值 1 个 MSS 出自 RFC 2001,10 个 MSS 出自 RFC 6928(2013 年)。面试答"1 个 MSS"不算错,但必须说清这是旧口径,并补一句"现代实现按 RFC 6928 用 10 个 MSS"。
A.5 MySQL / InnoDB 默认值与关键常量
A.5.1 结构常量
| 项 | 默认值 / 取值 | 说明 |
|---|
页大小(innodb_page_size) | 16 KB | 数据页、索引页、undo 页统一口径 |
| 区(extent) | 1 MB = 64 个页 | 连续页的分配单位,减少随机 I/O |
| 段(segment) | 由若干区组成 | 每张表至少一个数据段 + 若干索引段 |
| 行格式 | 5.7 默认 COMPACT,8.0 默认 DYNAMIC | DYNAMIC 更依赖溢出页 |
| 主键 | 聚簇索引,叶子节点存整行 | 无主键时用唯一非空索引,再退化到隐藏 row_id |
A.5.2 关键参数与丢数据窗口
| 参数 | 默认值 | 含义 | 丢数据窗口 |
|---|
innodb_buffer_pool_size | 128 MB | 缓存数据页与索引页(兼作自适应哈希) | 不涉及持久性;生产常设物理内存 50%~70% |
innodb_lock_wait_timeout | 50 s | 行锁等待超时 | 超时抛 Lock wait timeout exceeded,事务不一定回滚 |
innodb_flush_log_at_trx_commit | 1 | redo log 的刷盘策略 | 1:每次提交都 fsync,几乎不丢;0:每秒刷一次,崩掉最多丢 1 s;2:写 OS 缓存,OS 崩溃丢、进程崩溃不丢 |
sync_binlog | 1 | binlog 刷盘策略(8.0 默认 1) | 与上者组合决定"提交但未落盘"的窗口;0 时由 OS 决定 |
innodb_log_buffer_size | 16 MB | redo log 内存缓冲 | 太大浪费,太小导致频繁刷 |
innodb_redo_log_capacity | 100 MB(8.0.30 起) | redo 日志总容量上限 | 替代 8.0.30 之前的 innodb_log_file_size(默认 48 MB)× innodb_log_files_in_group(默认 2) |
innodb_io_capacity | 200 | 后台刷脏的 IOPS 预算 | 设太小会让刷脏跟不上,脏页堆积 |
innodb_flush_neighbors | 1(机械盘有利,SSD 建议 0) | 刷脏页时是否顺带刷相邻页 | 与 SSD 随机写特性冲突 |
transaction_isolation | REPEATABLE READ | 默认隔离级别 | 注意 PostgreSQL 默认是 READ COMMITTED |
max_connections | 151 | 最大连接数 | 连接是线程,过多会上下文切换 |
table_open_cache | 2000(8.0) | 打开表缓存 | 与 fd 上限联动 |
一处高发口径错误:在 MySQL 8.0.30 之后仍说 innodb_log_file_size 默认 48 MB 属于过时回答。新参数是 innodb_redo_log_capacity,默认 100 MB,它把多个 redo 文件统一成容量管理;老参数在 8.0.30 起被弃用。
A.5.3 redo log 环形结构与两阶段提交
1
2
3
4
5
6
7
8
9
10
11
| redo log 环形结构(write pos 追着 checkpoint 跑)
checkpoint write pos
↓ ↓
┌───────┬────────────┬────────────┬──────────┐
│ 已刷盘 │ 可覆盖区域 │ 待刷脏页区 │ 可写入区 │
└───────┴────────────┴────────────┴──────────┘
└──── 已写入但未刷脏的数据页 ────┘
write pos 追上 checkpoint ⟹ 无处可写 ⟹ 必须停下来推 checkpoint(刷脏页)
⟹ 这是"redo 太小导致写入抖动"的根因
|
两阶段提交时序(innodb_flush_log_at_trx_commit = 1、sync_binlog = 1):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| 阶段一:redo prepare
1. 写 redo log,标记 prepare
2. 刷 redo(fsync)
阶段二:写 binlog
3. 写 binlog
4. 刷 binlog(fsync)
5. 写 redo log,标记 commit(不需要立刻 fsync,靠组提交合并)
崩溃点分析:
A. 步骤 2 之前崩:redo 无记录、binlog 无记录 ⟹ 事务丢失,一致
B. 步骤 2 之后、步骤 4 之前崩:
redo 有 prepare 但无 commit,binlog 不完整
⟹ 恢复时发现 redo prepare 但 binlog 缺失 ⟹ 回滚该事务
C. 步骤 4 之后、步骤 5 之前崩:
binlog 完整,redo 处于 prepare
⟹ 恢复时按 binlog 补提交(commit 该事务)
判定依据:redo 的 XID 是否出现在 binlog 中
|
A.5.4 B+ 树树高估算算例
假设:主键 BIGINT 占 8 字节,页内指针占 6 字节,页头/页尾等开销约 100 字节(按 16 KB 页扣减)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| 单页可容纳的键数量:
每对 (键, 指针) = 8 + 6 = 14 字节
(16384 − 100) / 14 ≈ 1163,取整约 1170 个键(含页目录等开销的常见口径)
叶子层:每行按 1 KB 估算,一页放 16 行
树高(h 层)可索引的行数:
非叶层数 = h − 1,每层放大 1170 倍
h = 1:16 行
h = 2:1170 × 16 ≈ 1.87 万行
h = 3:1170 × 1170 × 16 ≈ 2190 万行
h = 4:约 256 亿行
结论:三层 B+ 树可索引约 2000 万行量级。
查询一次主键等值:3 次页访问;根节点常驻 buffer pool,实际磁盘 I/O 通常只有 0~1 次。
|
A.5.5 key_len 计算所需的字段宽度
| 类型 / 情形 | 占用字节 | 说明 |
|---|
TINYINT | 1 | 有符号同宽 |
SMALLINT | 2 | |
MEDIUMINT | 3 | |
INT | 4 | |
BIGINT | 8 | |
FLOAT | 4 | |
DOUBLE | 8 | |
DATE | 3 | |
TIME | 3 | 不含小数秒 |
DATETIME | 5(旧版 8) | MySQL 5.6.4 起 DATETIME 不再固定 8 字节 |
TIMESTAMP | 4 | |
CHAR(n) | n × 字符集字节数 | utf8mb4 下每字符 4 字节 |
VARCHAR(n) | n × 字符集字节数 + 2 | 变长长度前缀 2 字节 |
| 可空列 | 额外 +1 | 需要 1 字节标记 NULL |
utf8mb4 单字符 | 最多 4 字节 | utf8mb3/utf8 为 3 字节 |
| 联合索引只用前 k 列 | 各列 key_len 相加 | 用于判断到底用到了联合索引的几列 |
1
2
3
4
5
| 算例:KEY idx_a (a INT NOT NULL, b VARCHAR(20) NULL) CHARSET utf8mb4
只用 a: 4
a + b: 4 + (20 × 4 + 2) + 1 = 87
EXPLAIN 的 key_len = 4 ⟹ 只用到 a
EXPLAIN 的 key_len = 87 ⟹ a、b 都用到
|
提示
key_len 是"有没有把联合索引用满"的唯一客观证据,比 Extra 里的 Using index condition 更直接。记住三个常数:可空 +1、VARCHAR +2、utf8mb4 ×4。
A.6 Redis 默认配置与阈值
A.6.1 编码转换阈值
| 参数 | 默认值 | 触发效果 |
|---|
hash-max-listpack-entries | 128 | Hash 字段数 ≤ 128 且值不大时用 listpack |
hash-max-listpack-value | 64 | 单个值超过 64 字节即转 hashtable(超阈值才转) |
zset-max-listpack-entries | 128 | ZSet 元素数阈值 |
zset-max-listpack-value | 64 | ZSet 成员长度阈值 |
list-max-listpack-size | 128 | 也可写负数表示字节数上限(如 -2 表示 8 KB) |
set-max-intset-entries | 512 | 全整数集合且元素数 ≤ 512 用 intset |
set-max-listpack-entries | 128 | 7.2 起 Set 用 listpack 而非 ziplist |
hash-max-ziplist-entries | 128 | 7.x 前的老名字,语义与 listpack 版一致 |
| String 分界 | 阈值 | 编码 |
|---|
| embstr 上限 | 44 字节 | ≤ 44 字节用 embstr(与 redisObject 一次分配) |
| raw | > 44 字节 | 单独分配 SDS |
| int | 可解析为 long 且不超范围 | 直接存整数值,不存字符串 |
| Redis 4.0 起 | sdshdr5/8/16/32/64 | 按字符串长度选头结构,省内存 |
1
2
3
4
| 为什么是 44 字节:
jemalloc 最小分配档位 64 字节
redisObject = 16 字节(类型 + 编码 + LRU + 引用计数 + 指针)
64 − 16 = 48,SDS 头需 3 字节 + 结尾 '\0' 1 字节 ⟹ 可用 44 字节
|
A.6.2 持久化
| 参数 | 默认值 | 含义 | 风险 |
|---|
appendfsync | everysec | AOF 刷盘策略 | always 最安全最慢;no 交给 OS,宕机可能丢数十秒 |
save | 3600 1 300 100 60 10000 | RDB 自动快照触发条件 | 频率过高会频繁 fork,影响延迟 |
auto-aof-rewrite-percentage | 100 | AOF 增长到上次重写后的一倍就重写 | 重写期间写放大 |
aof-use-rdb-preamble | yes(4.0+) | 混合持久化:RDB 头 + AOF 增量 | 兼容性依赖版本 |
rdbcompression | yes | RDB 使用 LZF 压缩 | CPU 换空间 |
A.6.3 内存淘汰策略(八种)
| 策略 | 淘汰范围 | 淘汰依据 |
|---|
noeviction | 不淘汰 | 写入直接报错(默认值) |
volatile-lru | 只含过期时间的键 | 最近最少使用 |
volatile-lfu | 只含过期时间的键 | 最少使用频率(4.0+) |
volatile-random | 只含过期时间的键 | 随机 |
volatile-ttl | 只含过期时间的键 | 剩余生存时间最短优先 |
allkeys-lru | 全部键 | 最近最少使用 |
allkeys-lfu | 全部键 | 最少使用频率 |
allkeys-random | 全部键 | 随机 |
A.6.4 集群、统计与过期删除
| 项 | 取值 | 说明 |
|---|
| Cluster 槽位数 | 16384 | CRC16(key) mod 16384;位图仅 2 KB,心跳成本低 |
| 集群最少主节点 | 3(推荐 3 主 3 从) | 与 16384 / 3 的整数分配有关 |
| 转发错误 | MOVED(槽已迁移完成)/ ASK(槽正在迁移) | 客户端必须处理重定向 |
| HyperLogLog 误差 | 0.81%(标准误差) | 固定 12 KB,可用 PFCOUNT 合并多键 |
| HyperLogLog 稀疏编码上限 | hll-sparse-max-bytes 默认 3000 | 超过就转稠密编码 |
| 惰性删除 | 访问键时检查是否过期 | 过期键不被访问就永远不删 |
| 定期删除 | 默认每 100 ms 执行,随机抽样过期键 | hz 默认 10,即每秒 10 次 |
| 抽样比例 | 每轮从过期字典抽样检查,删除比例超过 25% 就继续本轮 | 防止过期键长期占用内存 |
| 单线程模型 | 6.0 起网络 I/O 多线程,命令执行仍单线程 | 慢命令会阻塞全部请求 |
| 大 key 阈值(经验) | String > 10 KB、集合元素 > 5000 | 无官方硬阈值,以 --bigkeys 输出为准 |
另一个容易漏的默认值:maxmemory 默认是 0(不限制),此时淘汰策略形同虚设 —— 内存会一直涨到被 OOM killer 杀掉。上线必设 maxmemory + maxmemory-policy,这是缓存服务最容易漏的一步。
A.7 JVM 默认值与关键常量
A.7.1 GC 与堆
| 项 | 版本口径 | 默认值 / 语义 |
|---|
| 服务端默认 GC | JDK 8 | Parallel Scavenge + Parallel Old(吞吐优先) |
| 默认 GC | JDK 9 ~ JDK 20 | G1 |
| 默认 GC | JDK 21+ | 分代 ZGC(开启分代模式后为默认低延迟收集器) |
-Xmx 未设置 | 所有版本 | 物理内存的 1/4 |
-Xms 未设置 | 所有版本 | 物理内存的 1/64(早期实现口径) |
SurvivorRatio | 默认 8 | Eden : Survivor = 8 : 1(单个 Survivor) |
MaxTenuringThreshold | 默认 15 | 晋升年龄上限;对象头年龄位只有 4 位 |
| 动态年龄判定 | 默认开启 | Survivor 中同年龄对象总和超过一半即全部晋升 |
MetaspaceSize | 默认约 21 MB | 首次触发元空间 GC 的阈值,不是固定大小 |
MaxMetaspaceSize | 默认不限(-1) | 不设就会一直涨到本地内存耗尽 |
| 压缩指针(Compressed Oops) | 默认开启(堆 ≤ 约 32 GB) | 对象引用 4 字节,MaxHeapSize 超过约 32 GB 后自动失效 |
TLAB | 默认开启 | 线程本地分配缓冲,减少分配竞争 |
| 大对象阈值 | -XX:PretenureSizeThreshold 默认 0(不启用) | 设了才直接进老年代 |
CMSInitiatingOccupancyFraction | 老年代占比阈值 | 仅 CMS 关注,G1/ZGC 无此参数 |
1
2
3
4
5
6
7
| 32 GB 压缩指针分界线的由来:
压缩指针用 4 字节表示引用,寻址单位是 8 字节(对象对齐)
2³² × 8 字节 = 32 GB
⟹ 堆 ≤ 32 GB 时可寻址全部对象,引用只占 4 字节,缓存友好
⟹ 堆 > 32 GB 时改用 8 字节引用,同样的对象图占用更多内存
⟹ 所以 31 GB 常比 33 GB 更划算:"32 GB 不是上限,是拐点"
补充:可用 -XX:ObjectAlignmentInBytes=16 把上限提到 64 GB,但有对齐浪费
|
A.7.2 集合与常量
| 项 | 值 | 说明 |
|---|
Integer 缓存 | -128 ~ 127 | 由 IntegerCache 实现,可用 -XX:AutoBoxCacheMax 扩大上界 |
Long/Short/Byte 缓存 | -128 ~ 127 | 规则固定,不可通过参数扩大 |
Boolean 缓存 | TRUE/FALSE 两个实例 | 无需缓存数组 |
Character 缓存 | 0 ~ 127 | |
HashMap 默认容量 | 16 | 首次 put 时才分配(延迟初始化) |
HashMap 负载因子 | 0.75 | 时间与空间的折中;泊松分布下桶冲突概率 |
HashMap 树化阈值 | 8 | 单桶链表长度达到 8 且表容量 ≥ 64 才树化 |
HashMap 退化阈值 | 6 | 树节点数降到 6 退回链表,避免反复转换 |
HashMap 最小树化容量 | 64 | 表容量小于 64 时只扩容,不树化 |
HashMap 容量上限 | 1 << 30 | 超过后不再扩容,负载因子形同失效 |
ArrayList 默认容量 | 10(首次 add 分配) | 扩容约 1.5 倍 |
ConcurrentHashMap 并发模型 | 无锁读 + CAS 插入空桶 + synchronized 锁头节点 | 扩容时多线程协助迁移,用 ForwardingNode 标记 |
ConcurrentHashMap 默认并发度 | sizeCtl 由容量与负载因子推导 | 不再有 JDK 7 的 Segment 分段锁 |
ThreadLocalMap 初始容量 | 16 | 弱引用 ThreadLocal 为 key,泄漏根因见第 30 章 |
版本口径要答全:JDK 8 服务端默认 Parallel GC,JDK 9 ~ JDK 20 默认 G1;JDK 21 起分代 ZGC 成为 ZGC 的默认模式(JDK 21 中分代尚需显式开启,JDK 23 起直接默认),所以"JDK 21 默认 ZGC"这句话必须带版本前提才成立。
A.8 分布式与 MQ 关键参数
A.8.1 Kafka
| 参数 | 取值 | 语义与代价 |
|---|
acks | 0 | 发出即认为成功,不等任何确认;可能丢 |
acks | 1 | leader 写入本地日志即确认;leader 挂掉且未同步时会丢 |
acks | all(等价 -1) | 等 ISR 中所有副本确认;配合 min.insync.replicas 才有意义 |
min.insync.replicas | 常设 2(默认为 1) | 至少要写入成功的最小同步副本数;ISR 不足时生产者报 NotEnoughReplicas |
replication.factor | 常设 3 | 副本总数;与上者的组合决定"还能坏几台" |
max.in.flight.requests.per.connection | 默认 5 | 幂等生产者开启时必须 ≤ 5;不幂等时设 1 才严格有序 |
enable.idempotence | 默认 false(3.0 起生产者默认 true) | 幂等 + 序列号去重,解决重试导致的重复 |
retries | 默认 2147483647 | Kafka 2.1 起生产者默认无限重试 |
ISR | In-Sync Replicas | 与 leader 保持同步的副本集合;落后超过 replica.lag.time.max.ms(默认 30 s)被踢出 |
LEO | Log End Offset | 每个副本下一条待写入消息的位点 |
HW | High Watermark | ISR 中所有副本 LEO 的最小值;消费者只能读到 HW 之前 |
commitIndex 的类比 | Kafka HW ≈ Raft commitIndex | 都表示"已确认可对外可见"的位点 |
unclean.leader.election.enable | 默认 false(3.0 起) | 开启会选非 ISR 副本当 leader,牺牲一致性换可用性 |
A.8.2 RocketMQ
| 项 | 取值 | 说明 |
|---|
| 延时级别数 | 18 级 | 固定级别:1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h |
| 默认 Topic 数 | 每个 Broker 自动创建 | autoCreateTopicEnable 生产应关闭 |
| 刷盘策略 | 同步刷盘 / 异步刷盘 | 同步刷盘保证不丢,但有性能代价 |
| 主从复制 | 同步 / 异步 | 同步双写才等价于 acks=all 的效果 |
| 消费模式 | 集群消费 / 广播消费 | 集群消费下同一 consumerGroup 分摊队列 |
| 死信队列 | %DLQ%<ConsumerGroup> | 重试次数耗尽后进入 |
| 重试次数 | 默认 16 次 | 按延时级别递减退避 |
A.8.3 Raft、Snowflake 与一致性哈希
| 项 | 典型取值 / 结构 | 说明 |
|---|
| 选举超时(election timeout) | 随机 150~300 ms(etcd 默认) | 随机化避免选票瓜分 |
| 心跳间隔(heartbeat interval) | 通常为选举超时的 1/10~1/3,如 100 ms | 必须显著小于选举超时,否则跟随者频繁发起选举 |
| Raft 比例关系 | 心跳 ≪ 选举超时;超时随机区间要大于一次 RPC 往返 | 经验:选举超时 ≥ 10 × 心跳间隔 |
| 多数派 | ⌊N/2⌋ + 1 | 3 节点容忍 1 台故障,5 节点容忍 2 台 |
| Snowflake 位结构 | 1 + 41 + 10 + 12 = 64 位 | 符号位 1(恒 0)+ 时间戳 41 + 机器 ID 10 + 序列号 12 |
| Snowflake 时间寿命 | 41 位毫秒 ≈ 69 年 | 2⁴¹ ms ÷ (365×24×3600×1000) ≈ 69.7 年 |
| Snowflake 单机 QPS | 2¹² = 4096/ms ≈ 409.6 万/s | 每毫秒一个序列周期 |
| 时钟回拨处理 | 等待、抛异常、用备用位序列号 | 不能静默生成重复 ID |
| 一致性哈希扩容迁移比例 | 从 N 个节点加到 N+1,约 1/(N+1) 的键需要迁移 | 普通取模需迁移 N/(N+1),几乎全量 |
| 虚拟节点 | 每物理节点 100~1000 个 | 缓解数据倾斜,节点数少时必备 |
| 槽位式方案 | Redis Cluster 16384 槽、Codis 1024 槽 | 迁移粒度固定,运维可控 |
1
2
3
4
5
| 取模 vs 一致性哈希(N → N+1 个节点):
取模: 键映射几乎全部改变 ⟹ 需迁移约 N/(N+1) 的键(N=9 时约 90%)
一致性哈希:只有落在新节点环区间的键需迁移 ⟹ 约 1/(N+1) 的键(N=9 时约 10%)
这就是"扩容抖动量级差一个数量级"的由来。
|
A.8.4 分布式事务方案的不一致窗口
| 方案 | 一致性 | 不一致窗口 | 主要缺陷 |
|---|
| 2PC(XA) | 强(提交点后一致) | 协调者宕机期间参与者阻塞,窗口 = 协调者恢复时间 | 同步阻塞、单点、协调者故障导致悬挂 |
| 3PC | 弱化阻塞 | 预提交后宕机仍可能不一致 | 网络分区下依然不保证,工程上少用 |
| TCC | 最终一致 | Try 成功到 Confirm 之间 | 需写三个接口;空回滚、悬挂、幂等三坑 |
| Saga | 最终一致 | 每步到补偿之间 | 无隔离性,需语义锁或版本号防脏读 |
| 本地消息表 | 最终一致 | 本地事务提交到消息被消费之间 | 依赖消息表与业务库同库 |
| 最大努力通知 | 最终一致 | 通知重试期间 | 不保证到达,只保证尽力 |
| 事务消息(MQ 两阶段) | 最终一致 | 半消息到提交/回滚之间 | 需要 MQ 支持回查 |
警告
“用了 TCC 就没有不一致了"是错的。TCC 只把不一致窗口压缩到 Try → Confirm 之间,这段窗口里资源已被预留但业务未完成,必须靠幂等 + 防悬挂 + 空回滚三件套兜住。
A.9 端口、协议与默认值对照
A.9.1 常用端口
| 端口 | 协议 | 服务 | 备注 |
|---|
| 20 / 21 | TCP | FTP 数据 / 控制 | 明文,已被 SFTP 替代 |
| 22 | TCP | SSH / SFTP | |
| 23 | TCP | Telnet | 明文,禁用 |
| 25 | TCP | SMTP | 提交端口常用 587 |
| 53 | TCP + UDP | DNS | 查询用 UDP,区域传送与大响应用 TCP |
| 67 / 68 | UDP | DHCP 服务端 / 客户端 | |
| 80 | TCP | HTTP | |
| 110 | TCP | POP3 | 加密 995 |
| 123 | UDP | NTP | |
| 143 | TCP | IMAP | 加密 993 |
| 161 / 162 | UDP | SNMP / Trap | |
| 443 | TCP | HTTPS | |
| 873 | TCP | rsync | |
| 3306 | TCP | MySQL | |
| 5432 | TCP | PostgreSQL | |
| 6379 | TCP | Redis | |
| 27017 | TCP | MongoDB | |
| 5672 | TCP | RabbitMQ(AMQP) | 管理界面 15672 |
| 9092 | TCP | Kafka | |
| 2181 | TCP | ZooKeeper | |
| 11211 | TCP + UDP | Memcached | |
| 8080 | TCP | HTTP 备用 / 应用容器 | 非标准,需显式指定 |
A.9.2 UDP 与 TCP 的使用场景
| 维度 | TCP | UDP |
|---|
| 连接 | 面向连接,三次握手 | 无连接 |
| 可靠性 | 确认 + 重传 + 排序 | 不保证 |
| 头部开销 | 20 字节起 | 8 字节 |
| 传输形态 | 字节流(无消息边界) | 数据报(保留边界) |
| 拥塞控制 | 有 | 无(QUIC 在用户态实现) |
| 典型场景 | HTTP、数据库、文件传输 | DNS、DHCP、NTP、音视频、游戏、QUIC |
A.9.3 HTTP 状态码速查(含语义陷阱)
| 状态码 | 语义 | 陷阱 / 注意 |
|---|
| 200 | 成功 | 不代表业务成功,需看响应体 |
| 301 | 永久重定向 | 浏览器会缓存;做短链会损失统计与可控性 |
| 302 | 临时重定向 | 历史上部分客户端把 POST 改 GET |
| 303 | See Other | 明确要求改用 GET 访问新位置 |
| 307 | 临时重定向 | 保持原方法(POST 仍为 POST) |
| 308 | 永久重定向 | 保持原方法,且会被缓存 |
| 304 | 未修改 | 靠 ETag/Last-Modified 命中协商缓存 |
| 400 | 请求语法错误 | 客户端问题,不该重试 |
| 401 | 未认证 | 缺凭据;应带 WWW-Authenticate |
| 403 | 已认证但无权限 | 与服务端 ACL 有关;与 401 的区分是高频考点 |
| 404 | 资源不存在 | 也可能被用于隐藏 403 |
| 408 | 请求超时 | 服务端等请求体超时 |
| 429 | 请求过多 | 应带 Retry-After |
| 499 | 客户端主动断开(Nginx 自定义) | 非标准码,用于统计客户端取消 |
| 500 | 服务端内部错误 | 业务代码抛异常 |
| 502 | 网关拿到无效响应 | 后端进程挂了/重启中;上游连接失败 |
| 503 | 服务不可用 | 过载或维护,常配 Retry-After |
| 504 | 网关等待上游超时 | 上游连接成功但响应超时 |
1
2
3
4
5
6
7
| 502 vs 504 的判据(面试常问"线上大量 5xx 你怎么查"):
502 Bad Gateway ⟹ 网关连不上上游(进程没了 / 端口没监听 / 连接被拒)
504 Gateway Timeout ⟹ 连上了,但上游在超时时间内没返回(慢查询 / 下游雪崩)
重试语义:
502、504、503、429 通常可重试(配合退避与幂等)
400、401、403、404、422 重试无意义,只会放大流量
|
499 是 Nginx 自定义状态码(客户端提前关闭连接),不是 HTTP 规范的一部分。面试里说"499 表示客户端取消"要带上"Nginx 定义"这个限定。
A.10 一句话记忆锚点
归零不是删除:deleted 标记位只是隐藏,purge 才真删。%util 不是利用率:队列非空即接近 100%,并发 I/O 下会失真。RR 的幻读只在当前读出现,快照读靠 ReadView 天然防幻读。show index 看的是基数不是精确值,Cardinality 是采样估算。ABA 用版本号,不是再比一次值。Time Wait 属于主动关闭方,服务端堆 TIME_WAIT 说明它先关的。CLOSE_WAIT 堆积是代码没 close,与内核参数无关。MSS 在传输层、分片在网络层,两者不可互换。RTO 有最小值 200 ms,别把 RTT 直接当重传超时。快重传靠 3 个重复 ACK,超时重传才是最后手段。cwnd 初值 10 个 MSS 是 RFC 6928 的现代口径。窗口扩大因子最大 14,上限是 65535 × 2¹⁴。vm.swappiness = 0 不等于禁用 swap。overcommit = 1 会让 malloc 骗过你,触碰时才 OOM。dirty_ratio 触发同步回写,dirty_background_ratio 是异步。RAID5 随机写惩罚为 4,RAID6 为 6,RAID10 为 2。%i 用满也会 No space left,df -h 看不出来。du 与 df 不一致:删了文件但进程还持有。noatime 几乎无副作用,是低风险高收益的挂载项。innodb_redo_log_capacity 默认 100 MB,8.0.30 起取代旧参数。redo 是环形,write pos 追上 checkpoint 就得停下来刷脏。两阶段提交靠 XID 对齐,binlog 有就补提交。三层 B+ 树约 2000 万行,根节点常驻内存。key_len 可空加 1、varchar 加 2、utf8mb4 乘 4。RR 是 MySQL 默认,PostgreSQL 默认是 RC。innodb_lock_wait_timeout 默认 50 s,超时不等于回滚。hash 128 条 64 字节是 listpack 转 hashtable 的界。String 44 字节是 embstr 与 raw 的分界。maxmemory 默认 0,不设淘汰策略等于没设。16384 槽让集群心跳位图只有 2 KB。HyperLogLog 误差 0.81%,固定 12 KB。32 GB 是压缩指针拐点,不是堆内存上限。MaxTenuringThreshold 默认 15,因为年龄位只有 4 位。MetaspaceSize 是首次 GC 阈值,不是初始大小。HashMap 树化 8、退化 6、最小容量 64。Integer 缓存 -128~127,超出即新对象。acks=all 必须配 min.insync.replicas,否则等于 acks=1。HW 取 ISR 最小 LEO,消费者只能读到 HW。18 级延时消息是 RocketMQ 的固定档位。选举超时要大于 10 倍心跳,否则选主抖动。一致性哈希扩容迁移约 1/(N+1),取模是 N/(N+1)。502 是连不上,504 是等超时。301 会被缓存,短链要用 302 保留统计。401 是没认证,403 是没权限。
提示
最后一小时的用法:按 A.1 → A.4 → A.5 → A.7 的顺序过一遍倍率与默认值,再把 A.10 的锚点逐条读出声。能在 10 分钟内复述出"倍率三档 + 三个版本坑(8.0.30 的 redo、JDK 21 的 ZGC、RFC 6928 的 cwnd)+ 两处反直觉(%util、swappiness)",这一轮校准就到位了。
附:本附录的口径与版本约定
| 领域 | 版本口径 | 需要特别说明的可变项 |
|---|
| Linux | 5.x / 6.x 主线 | somaxconn、tcp_max_syn_backlog、fs.file-max 随版本与内存变化;tcp_tw_recycle 已于 4.12 移除 |
| MySQL | 8.0(部分标注 8.0.30 起) | redo 容量参数更名;行格式默认从 COMPACT 变 DYNAMIC |
| Redis | 7.x | listpack 已取代 ziplist;Set 编码参数为 7.2 起的新名字 |
| JVM | JDK 8 / 9+ / 21+ | 默认 GC 三次变更;分代 ZGC 的默认化有版本前提 |
| Kafka | 3.x | 幂等生产者与 unclean.leader.election 的默认值在 3.0 发生变化 |
| TCP 规范 | RFC 793 / 1122 / 5681 / 6298 / 6928 | cwnd 初值、RTO 计算、拥塞控制均以 RFC 为准,Linux 实现另有微调 |
延伸阅读
- RFC 793《Transmission Control Protocol》、RFC 6298《Computing TCP’s Retransmission Timer》、RFC 6928《Increasing TCP’s Initial Window》、RFC 5681《TCP Congestion Control》。
- Linux 手册页:
man 7 tcp、man 5 proc、man 8 sysctl、man 5 limits.conf。 - MySQL 官方手册:InnoDB 参数、InnoDB 事务模型与锁、
innodb_redo_log_capacity 变更说明。 - Redis 官方文档:内存优化(
memory-optimization)、持久化、集群规格(cluster-tutorial)、键过期(EXPIRE)。 - Oracle 官方文档:
java 命令参考(-XX 选项与默认 GC)、HashMap 与 Integer 的 API 说明。 - Apache Kafka 官方文档:生产者配置(
acks、min.insync.replicas、max.in.flight)与复制设计。