前言
又是两场面试,一场是北京的量化公司好像,感觉很不尊重面试者,被我自己pass了。另一家火山模型的SRE,经历不太匹配没后文了。
挺迷茫的。
复盘
按主题分四块整理:
- 一、网络与算法基础
- 二、容器与 K8s
- 三、存储与中间件
- 四、大模型 SRE 与 AI Agent
一、网络与算法基础
Q1. TCP 三次握手的过程是怎样的?为什么不能是两次或四次?
面试的时候只答了个大概,”客户端发起握手包 → 服务端返回 ACK → 客户端再回复”,标志位和序列号细节都忘了。补一下完整版:
1 | 客户端 服务端 |
三次握手的本质是**双方各确认一次”自己的收发能力”和”对方的收发能力”**,并同步双方的初始序列号(ISN)。
- 为什么不能是两次:服务端一收到 SYN 就 ESTABLISHED,会有两个致命问题——① 网络中滞留的旧 SYN 报文姗姗来迟,服务端会误建连接、白分配资源;② 客户端的 ISN 没有得到 ACK 确认,双方序列号没达成一致
- 为什么不需要四次:TCP 支持捎带确认(piggyback),SYN+ACK 可以合并成一个报文,一次 RTT 同时完成”确认对方 + 发起自己”
高频追问:SYN Flood 攻击
攻击者伪造源 IP 大量发 SYN,服务端维持海量半连接(SYN_RCVD 队列)耗尽资源。防御手段:
| 手段 | 说明 |
|---|---|
| SYN Cookie | 不占半连接队列,用 cookie 验算合法性,net.ipv4.tcp_syncookies=1 |
| 调大半连接队列 | net.ipv4.tcp_max_syn_backlog |
| 减少 SYN+ACK 重试 | net.ipv4.tcp_synack_retries |
| 全连接队列 | somaxconn 与应用 backlog 取小,满了直接丢弃新连接,表现为偶发连接超时 |
Q2. TCP 拥塞控制有哪些算法?大致原理是什么?
面试时只答了”有个窗口,丢包就缩小”,具体算法名字一个没说出来。补齐一下:
经典四件套(Reno/Tahoe 体系):
| 阶段 | 行为 |
|---|---|
| 慢启动 | 初始 cwnd = 1 MSS,每收到一个 ACK 翻倍,指数增长,直到 ssthresh |
| 拥塞避免 | cwnd ≥ ssthresh 后改为线性增长(每 RTT +1 MSS) |
| 快重传 | 收到 3 个重复 ACK 立即重传丢失报文,不等 RTO 超时 |
| 快恢复 | 快重传后 ssthresh = cwnd / 2,cwnd = ssthresh,进入拥塞避免(而不是回到慢启动) |
现代主流算法:
- CUBIC:Linux 默认,基于丢包的窗口增长曲线(三次函数),在长肥管道上比 Reno 收敛更快
- BBR:Google 提出,不依赖丢包信号,主动测量瓶颈带宽(BtlBw)和最小 RTT(RTprop),以
BDP = BtlBw × RTprop为目标窗口。在高延迟 / 有随机丢包的链路(跨洋、无线)上表现远好于 CUBIC - Vegas / DCTCP:分别基于 RTT 变化和 ECN 标记,做更早、更精细的拥塞判断
流量控制 vs 拥塞控制(很容易混):
- 流量控制:管的是端到端的接收能力,接收方通过
window字段通告缓冲余量 - 拥塞控制:管的是网络链路的承载能力,是发送方基于丢包/延迟的自反馈
- 实际发送窗口 =
min(rwnd, cwnd)
Q3. 简单说下快排和归并排序的思路
面试时归并直接答不上来了,快排也讲得磕磕绊绊。这两个都是分治思想,但方向恰好相反:
快速排序(Quick Sort):先分再排
1 | 1. 选一个基准值 pivot(一般取首/尾/随机/三数取中) |
- 时间复杂度:平均
O(n log n),最坏O(n²)(有序数组 + 固定取首/尾做 pivot),随机化 pivot 可规避 - 空间复杂度:
O(log n)(递归栈) - 不稳定排序,但常数因子小、原地排序,工程上最常用
归并排序(Merge Sort):先拆再合
1 | 1. 把数组从中间一分为二 |
- 时间复杂度:**稳定
O(n log n)**,最坏也是这个 - 空间复杂度:
O(n),需要额外数组存合并结果 - 稳定排序,天然适合链表(合并可以原地做)和外部排序(磁盘/多路归并)
一句话对比:快排”分区在合并前”、原地但不稳定;归并”分区在合并后”、稳定但要额外空间。工程上:内存排序多用快排(如 C 的 qsort、C++ 的 std::sort 是 introsort = 快排 + 堆排 + 插入排序),外部排序和链表用归并。
Q4. 你写代码吗?Python 熟不熟?
日常写运维脚本、Agent 逻辑都是 Python,够用。但确实”AI 加持下人与人差距越来越小”,很多东西直接让 AI 生成,自己反而对基础语法细节(装饰器、生成器、上下文管理器、asyncio)有点生疏。
准备面试的话建议至少能口头讲清楚:
- GIL 是什么,为什么 CPU 密集型用多进程、IO 密集型用多线程/协程
- 装饰器的本质是”接受函数返回函数”,
functools.wraps保留元信息 - 生成器(
yield)与迭代器的区别,惰性求值节省内存 - asyncio 的 event loop、
async/await、asyncio.gather并发
二、容器与 K8s
Q5. 容器和虚拟机(VMware)有什么区别?
核心差异在于虚拟化的层次:
1 | ┌──────────────────────────────┐ ┌──────────────────────────────┐ |
| 维度 | 虚拟机 | 容器 |
|---|---|---|
| 虚拟化层次 | 硬件级(Hypervisor 虚拟出 CPU/内存/设备) | 操作系统级(共享内核,进程隔离) |
| 是否含 OS | 每个 VM 都带完整 Guest OS | 只有应用与依赖,共享 Host Kernel |
| 启动速度 | 分钟级 | 秒级 / 毫秒级 |
| 资源开销 | GB 级 | MB 级 |
| 隔离强度 | 强(Hypervisor 边界) | 较弱(共享内核,靠 Namespace + Cgroup) |
| 典型代表 | VMware、KVM、Hyper-V | Docker、containerd、CRI-O |
公有云的形态:一台物理机上通常运行几十个甚至上百个 VM,Hypervisor 把物理资源(CPU、内存、磁盘、网络带宽)切分给上层 VM;VM 内再跑容器也很常见(”套娃”部署)。
Q6. CGroup 和 Namespace 分别起什么作用?
这题面试时答混了——把”隔离”也归给了 CGroup,实际上隔离是 Namespace 的活。厘清一下:
| 技术 | 定位 | 类比 |
|---|---|---|
| Namespace | 隔离:让进程”看不见”其他进程/资源 | 一堵墙,把视图分开 |
| CGroup | 限制:限制、审计、控制进程能用的资源量 | 一个配额表,规定你能吃多少 |
Namespace 的 8 种(Linux 5.6+):
| Namespace | 隔离内容 |
|---|---|
| PID | 进程 ID,容器内 PID=1 是主进程 |
| Mount (mnt) | 挂载点、文件系统视图 |
| Network | 网卡、IP、端口、路由表、iptables |
| UTS | 主机名和域名 |
| IPC | 信号量、消息队列、共享内存 |
| User | 用户/组 ID 映射(容器内 root ≠ 宿主 root) |
| Cgroup | cgroup 根目录视图 |
| Time | 系统时间(较新) |
CGroup 的能力:
- 资源限制:CPU(
cpu.max配额)、内存(memory.max)、IO 带宽(blkio)、PID 数量(pids.max) - 优先级:CPU 权重(
cpu.weight) - 审计:
cpuacct、memory.usage_in_bytes统计用量 - 控制:冻结/恢复进程组(
freezer)
K8s 里 request/limit 的落地:
1 | limit.cpu=1 → cgroup v1: cpu.cfs_quota_us=100000, cpu.cfs_period_us=100000 |
一句话:**Namespace 决定”能看到什么”,CGroup 决定”能用多少”**,两者共同构成了容器的底层实现。
Q7. K8s 中 Deployment、Pod、Service 三者是怎么关联的?
面试时”Selector”这个词一时没听清,其实答案很简单——通过 Label 和 Selector 串起来:
1 | Deployment ReplicaSet Pod Service |
- Deployment:定义 Pod 模板(
spec.template)和更新策略,通过管理 ReplicaSet 间接管理 Pod - Pod:从 Deployment 模板生成,自动带上模板中的
labels - Service:通过
spec.selector选中一组 Label 匹配的 Pod,把它们的 IP 收集到 Endpoints / EndpointSlice 中;访问 Service ClusterIP 时由 kube-proxy 转发到某个后端 Pod
关键点:
- Label 是唯一的粘合剂——Deployment 与 Pod、Service 与 Pod、Job 与 Pod 全靠 Label
- Selector 不匹配 = Endpoints 为空:80% 的”Service 访问不通”就出在这里
- Deployment 不直接管 Pod,中间隔了一层 ReplicaSet,这也是”滚动更新 = 新旧 RS 交替扩缩”的实现基础
Q8. 讲一下 K8s 的 QoS 等级?驱逐顺序是怎样的?
面试时答了个大概——三种 QoS,request=limit 是最高级,什么都没设的最先被杀。完整版:
| QoS 等级 | 判定条件 | 驱逐优先级 |
|---|---|---|
| Guaranteed | 所有容器 requests == limits(CPU 和内存都设且相等) |
最后被驱逐 |
| Burstable | 至少一个容器设置了 requests 或 limits,但不满足 Guaranteed |
中间 |
| BestEffort | 完全没设置 requests/limits | 最先被驱逐 |
驱逐触发时机:
- 节点资源不足:kubelet 检测到
MemoryPressure/DiskPressure/PIDPressure - 超过 eviction threshold:默认
memory.available < 100Mi、nodefs.available < 10%、imagefs.available < 15% - cgroup OOM:容器超过自身 memory limit,内核 oom-killer 直接干掉
同 QoS 等级内的排序:按实际用量超过 requests 的百分比排序,超得越多越先被驱逐。这也是”Burstable 里 limit 定得离谱的容器先死”的原因。
驱逐流程:
1 | kubelet 检测到压力 → 按 QoS + 超额比例打分 → 逐个 Evict(走 GracefulTermination) |
PodDisruptionBudget(PDB) 是另一层保护:即使被驱逐,也要保证 minAvailable / maxUnavailable 不被突破,防止一次驱逐干掉太多副本。
Q9. 如果节点上只剩 Guaranteed Pod 且内存不足,还会被驱逐吗?
面试时答”理论上不会,除非超卖”——这个说法不够准确。补一下:
结论:会,但通常是节点级 OOM,而不是 kubelet 主动驱逐。
分两种情况:
- kubelet 主动驱逐:只要节点资源低于阈值,即使是 Guaranteed 也会被驱逐。kubelet 驱逐是按分数排序的,Guaranteed 分数最低所以最后被杀,但不代表不杀。当所有 Pod 都是 Guaranteed 且节点内存持续下压时,最终一定会挑一个杀
- cgroup OOM:Guaranteed 的定义是
requests == limits,容器内存使用不会超过自身 limit(超了立即被 cgroup OOM Killer 干掉)。但如果 kubelet / 系统进程 / kernel slab 占用过多,节点整体内存告急,Guaranteed Pod 也会因为节点级压力被驱逐
为什么 Guaranteed 更安全:
- 不会被 CPU throttle(
cpu.cfs_quota_us匹配cpu.shares) - 内核 OOM 打分最低(
oom_score_adj = -997,BestEffort 是1000) - 节点资源规划更准(
requests就是实际占用)
极端情况下的兜底:system-reserved 和 kube-reserved 预留一部分资源给系统进程和 kubelet,避免业务 Pod 把节点吃死。
Q10. 什么是节点污点(Taint)?除了标记 NotReady 还有什么用?
面试时只答了”kubelet 掉线会打 NotReady 污点驱逐 Pod”,其他作用完全没答上。补全:
污点的本质:节点主动拒绝 Pod,与亲和性(Pod 选节点)方向相反。
语法与三种 effect:
1 | kubectl taint nodes node1 gpu=true:NoSchedule |
| effect | 行为 |
|---|---|
| NoSchedule | 不调度新 Pod 上来,已有的不动 |
| PreferNoSchedule | 尽量不调度,实在没地方还是会上 |
| NoExecute | 不调度新 Pod,且驱逐已存在的不容忍 Pod |
Pod 侧通过 tolerations 声明容忍:
1 | tolerations: |
除了 NotReady,污点的核心用途:
| 场景 | 说明 |
|---|---|
| 专用节点池 | GPU 节点、高内存节点、SSD 节点,打污点防止普通负载混入,配合 toleration 定向调度 |
| 节点故障自动隔离 | kubelet 心跳丢失时,Node Controller 自动打 node.kubernetes.io/unreachable:NoExecute,5 分钟后驱逐 Pod(tolerationSeconds: 300) |
| 节点维护 | kubectl drain 会打上 node.kubernetes.io/unschedulable:NoSchedule,配合驱逐完成滚动维护 |
| 控制面隔离 | Master 节点默认打 node-role.kubernetes.io/control-plane:NoSchedule,业务 Pod 不会调度上去 |
| 多租户/环境隔离 | 生产、测试节点池用不同污点隔离,防止误部署 |
K8s 内置的几个自动污点:
node.kubernetes.io/not-ready:节点未就绪node.kubernetes.io/unreachable:节点失联node.kubernetes.io/memory-pressure/disk-pressure/pid-pressure:资源压力node.kubernetes.io/unschedulable:手动 cordon
排查 Pod Pending 时看 describe pod 的 Events,node(s) had taint ... that the pod didn't tolerate 就是污点没容忍。
Q11. 如何排查一个处于 Pending 状态的 Pod?
面试时答了调度慢和探针两块,其中探针其实不影响 Pending 阶段(探针影响的是 Ready),这是一个概念偏差。
Pending 的准确定义:Pod 已被 APIServer 接受,但至少一个容器还没创建——要么还没被 scheduler 绑定到节点,要么已经在拉镜像 / 挂卷。
排查思路:kubectl describe pod 看 Events
1 | kubectl describe pod <pod-name> -n <ns> |
按 Events 里的关键字对号入座:
| Events 关键字 | 原因 | 处置 |
|---|---|---|
Insufficient cpu / Insufficient memory |
节点可分配资源不足 | 扩容节点 / 调小 requests / 检查是否被其他 Pod 挤占 |
node(s) had taint ... that the pod didn't tolerate |
污点没容忍 | 加 toleration 或去掉节点污点 |
node(s) didn't match Pod's node affinity/selector |
节点选择器/亲和性太严 | 检查 nodeSelector / nodeAffinity 表达式 |
persistentvolumeclaim is not bound |
PVC 没绑定 | 检查 StorageClass、provisioner、容量、访问模式 |
Failed to pull image / ImagePullBackOff |
镜像拉不下来 | 检查镜像名、tag、私有仓库凭证、网络 |
0/N nodes are available |
综合原因 | 逐条看后面的详情 |
| 没有任何 Events | Scheduler 未处理 | 检查 kube-scheduler 是否正常 |
排查流程:
1 | 1. kubectl get pod -o wide 看是否已被绑定节点(NODE 列有没有值) |
已调度但仍 Pending(ContainerCreating):多半是镜像拉取慢或volume 挂载失败,看 kubelet 日志和 CSI driver 日志。
Q12. K8s 有哪几种探针?分别用来做什么?
三种探针,用途完全不同,触发时机也不同:
| 探针 | 目的 | 失败后果 | 什么时候开始 |
|---|---|---|---|
| startupProbe | 判断应用是否完成启动 | 未达到 failureThreshold 前屏蔽其他两个探针;超过则杀掉重启 |
容器创建后立即 |
| livenessProbe | 判断容器是否存活 | 重启容器(按 restartPolicy) | startup 通过后开始 |
| readinessProbe | 判断容器是否能接流量 | 从 Service Endpoints 摘除,不重启 | startup 通过后开始 |
探测方式(三种探针通用):
httpGet:请求指定 path,2xx/3xx 视为成功tcpSocket:尝试建立 TCP 连接exec:容器内执行命令,退出码 0 视为成功grpc(1.24+):调用 gRPC Health Checking 协议
关键参数:
1 | livenessProbe: |
startupProbe 的价值:以前处理慢启动应用只能把 livenessProbe.initialDelaySeconds 调很大,但这样又让”启动后崩溃”的检测变慢。startupProbe 用一个宽松的 failureThreshold × periodSeconds(比如 30 × 10s = 5 分钟)作为启动上限,通过后再让 liveness/readiness 用严格的参数接管。
Q13. 探针配置不合理会导致什么问题?
这题面试时答得还行,三种探针都能举出反例。系统化整理:
Liveness 配置不当 → 无谓重启
| 反例 | 后果 |
|---|---|
initialDelaySeconds 太小 + 没配 startupProbe |
应用还没起来就被杀,进入 CrashLoopBackOff |
failureThreshold 太小(如 1) |
一次接口抖动就重启,把偶发变故障 |
探针路径依赖下游(如 /health 里查数据库) |
下游抖动导致上游服务被集体重启,级联雪崩 |
timeoutSeconds 太小 + 应用 GC 卡顿 |
长时间 STW 时被误判死亡 |
| CPU limit 太紧 + 探针用 exec | 探针命令自己被 throttle,超时失败 |
最佳实践:liveness 只探测进程本身的健康(能否响应、是否死锁),不要探测下游依赖。
Readiness 配置不当 → 流量打飞
| 反例 | 后果 |
|---|---|
initialDelaySeconds 太小 |
应用还没预热完就接流量,前几个请求超时/报错 |
| 探针太宽松(如仅 TCP 探测) | 端口通了但业务未 ready,请求进去报错 |
periodSeconds 太大 |
应用异常后,摘除延迟高,一段时间内流量还在打过去 |
| Readiness 依赖下游 | 下游抖动导致所有上游被摘除,流量无后端可用 |
最佳实践:readiness 探测是否能处理业务请求(缓存预热完成、连接池就绪、依赖服务可达),但不要让它承担熔断职责。
Startup 配置不当 → 慢启动应用被杀
failureThreshold × periodSeconds小于应用真实启动时间 → 永远起不来- 忘记配 startupProbe,直接用 liveness 兜底 → 老问题回归
排查手段:kubectl describe pod 看 Events 里的 Liveness probe failed / Readiness probe failed / Unhealthy;kubectl get events -A --field-selector reason=Unhealthy。
Q14. HPA 是怎么工作的?大模型场景下有什么变化?
传统 HPA 原理:
1 | 期望副本数 = ceil[ 当前副本数 × (当前指标值 / 目标指标值) ] |
例如:当前 3 副本、平均 CPU 80%、目标 50% → 3 × 80/50 = 4.8 → 扩到 5。
指标链路:
1 | kubelet(cAdvisor) → metrics-server → HPA Controller |
- Resource Metrics(CPU/内存):走
metrics.k8s.io,由 metrics-server 提供 - Custom Metrics(QPS、队列长度):走
custom.metrics.k8s.io,通常由 Prometheus Adapter 提供 - External Metrics(消息队列堆积、外部服务指标):走
external.metrics.k8s.io,KEDA 是这层的常用方案
必备前提:Pod 必须设置 requests。CPU 利用率 = 实际用量 / requests,不设 requests HPA 直接算不出来,显示 <unknown>。
大模型场景的差异:
传统 CPU/内存指标在推理服务上不够敏感——GPU 打满时 CPU 可能才 20%,靠 CPU 扩容永远跟不上。业界主流是基于业务队列指标做扩容:
| 指标 | 说明 | 来源 |
|---|---|---|
| Batch Size | 当前连续批处理的样本数,接近上限说明容量吃紧 | vLLM / TGI / rtp-llm 的 /metrics |
| Waiting Queue Length | 排队中的请求数,反映真实积压 | 推理引擎或网关埋点 |
| TTFT (Time To First Token) | 首 token 延迟,SLO 关键指标 | 客户端或网关采集 |
| Prefill 负载 / KV Cache 使用率 | 长上下文场景下 KV Cache 是最紧的资源 | 引擎内部指标 |
| GPU 显存利用率 / SM 利用率 | 硬件层面兜底 | DCGM Exporter |
实现路径:推理引擎暴露 Prometheus 指标 → Prometheus Adapter 转成 Custom Metrics → HPA 按 batch size 或队列长度扩容。
注意点:
- 模型 Pod 启动慢(几十秒到几分钟:拉镜像 + 加载权重 + 预热),HPA 的 15s 决策周期跟不上突发流量,必须预扩容 + 预热池兜底
- 扩容粒度大:一个模型副本可能占 8 卡,扩容步长要控制,避免抖动
- 缩容要保守:
behavior.scaleDown.stabilizationWindowSeconds建议 5-10 分钟,防止流量稍降就缩掉
加分项:完整弹性链路
1 | HPA (Pod 级) → Cluster Autoscaler / Karpenter (节点级) → 云厂商弹性伸缩组 (机器级) |
大模型场景因为节点是 GPU,扩容速度和库存都受限,通常还会配合多集群切流(Karmada / 自研调度器)做跨可用区、跨集群的容量调度。
三、存储与中间件
Q15. MongoDB 和 MySQL 的区别?各自的高可用和扩容方案是什么?
核心定位差异:
| 维度 | MySQL | MongoDB |
|---|---|---|
| 数据模型 | 关系型,行列表结构 + 强 Schema | 文档型,BSON(二进制 JSON),Schema-less |
| 查询语言 | SQL(标准化) | MQL(JSON 风格) |
| 事务 | 完整 ACID,多表 JOIN 强 | 4.0 起支持多文档事务,但不推荐重度使用 |
| 适用场景 | 结构化业务数据(订单、账户、用户) | 半结构化 / 灵活 Schema(日志、内容、IoT、向量) |
| 扩展方式 | 垂直扩展为主,水平扩展靠分库分表中间件 | 原生分片(Sharding),水平扩展友好 |
| AI 时代加分项 | 需借助外部向量库(Milvus / Pinecone) | 内置向量索引(Atlas Vector Search),可直接做 RAG |
MySQL 的高可用与扩容:
- 高可用:主从复制(异步 / 半同步 / 组复制 MGR)、
MHA/Orchestrator做自动故障转移、云上一般用 RDS 三节点企业版 - 读写分离:中间件(MyCat / ShardingSphere / ProxySQL)或应用层路由
- 水平扩容:分库分表——按业务垂直拆分(订单库、用户库)+ 按 hash / range 水平拆分(
user_id % 32) - 痛点:分片键选择难,跨分片 JOIN 和分布式事务复杂
MongoDB 的高可用与扩容:
1 | ┌────────────┐ ┌────────────┐ ┌────────────┐ |
- mongos:路由进程,客户端连它,它查 Config Server 决定去哪个 Shard
- Config Server:存分片元数据,本身也是副本集
- Shard:每个 Shard 是一个独立的副本集(Primary + Secondary + Arbiter),保证单分片高可用
- 扩容:加 Shard → 在 Config Server 注册 → mongos 自动感知 → 数据按 chunk 迁移(balancer 后台均衡)
- 分片键:一旦选定不可更改,选不好会导致数据倾斜(jumbo chunk)
选型建议:交易、账务等强一致 + 复杂关联用 MySQL;日志、内容、行为埋点、AI 向量检索等灵活 Schema + 水平扩展用 MongoDB。
Q16. Redis 和 InfluxDB 分别是什么?各自的应用场景?
Redis:内存 KV 数据库 / 缓存中间件
- 数据结构:String、Hash、List、Set、ZSet、Bitmap、HyperLogLog、Geo、Stream
- 典型场景:
- 缓存:热点数据(用户信息、配置、Session),降低数据库压力
- 分布式锁:
SETNX+ Lua 保证原子性(Redlock 有争议,一般用单点 + 短 TTL) - 限流计数:
INCR+EXPIRE或 Lua 脚本实现滑动窗口 / 令牌桶 - 排行榜:ZSet 天然支持排序
- 消息队列:List / Stream(轻量场景)
- 发布订阅:Pub/Sub
InfluxDB:时序数据库(TSDB)
- 数据模型:以时间戳 + tag + field 组织,写入即追加、极少更新
- 典型场景:
- 监控指标存储:Prometheus 自带 TSDB 默认存 15 天,长期存储接 InfluxDB / Thanos / VictoriaMetrics / M3DB
- IoT 设备数据:传感器、车联网、智能家居
- 业务指标:QPS、订单量、GMV 的时间序列分析
- 优势:高写入吞吐、按时间范围压缩、内置降采样(continuous query)
Redis 的高可用与扩容架构:
| 形态 | 说明 | 适用场景 |
|---|---|---|
| 主从(Master-Slave) | 主写从读,异步复制 | 读多写少,容量单机可容纳 |
| 哨兵(Sentinel) | 主从 + 自动故障转移,哨兵集群监控主节点 | 需要高可用但容量单机够 |
| Cluster(集群) | 数据分片(16384 slot)+ 每个分片主从 + 自动 failover | 大容量、高并发,突破单机内存限制 |
| 云 Redis | 一般提供标准版(主从)/ 集群版 / 读写分离版 | 免运维 |
分片的价值:
- 突破单机内存:数据按 slot 分散到多个分片
- 抗热点:把大 key / 热 key 的影响半径限制在单个分片
- 提升并发:多分片并行处理请求
分片键设计:Redis Cluster 用 CRC16(key) % 16384,可以用 hash tag({user:123}.profile)把相关 key 强制分到同一 slot 支持多 key 操作。
Q17. 缓存穿透、击穿、雪崩是什么?怎么规避?
三个概念很容易混,用一张表拉清楚:
| 类型 | 现象 | 根因 | 影响 |
|---|---|---|---|
| 穿透(Penetration) | 请求的 key 数据库里也不存在,每次都直查 DB | 恶意攻击 / 数据本身不存在 | DB 被无效查询压垮 |
| 击穿(Breakdown) | 某个热点 key 突然过期,大量请求同时打到 DB | 单点热 key TTL 到期 | DB 瞬时压力激增 |
| 雪崩(Avalanche) | 大量 key 同时过期(或 Redis 宕机),请求全部打到 DB | TTL 设置雷同 / 集群故障 | DB 被打死 |
穿透的规避:
| 手段 | 说明 | 权衡 |
|---|---|---|
| 布隆过滤器(前置) | 请求先过 Bloom Filter,判定”一定不存在”的直接拒绝 | 有误判率(判无必无、判有可能无),需处理删除(用 Counting Bloom) |
| 空值缓存 | DB 查不到时把 null 写入 Redis,TTL 短(如 60s) |
占内存,短期脏数据 |
| 接口鉴权 + 限流 | 拦截明显异常的请求(未登录、频率异常) | 治标不治本 |
| 参数校验 | 前置校验 ID 合法性(如 UUID 格式、范围) | 只解决部分场景 |
布隆过滤器原理速记:多个 hash 函数把元素映射到位数组,位为 0 一定不存在,位为 1 可能存在(不同元素的位可能重叠)。
击穿的规避:
| 手段 | 说明 |
|---|---|
| 互斥锁(Mutex) | 热 key 过期时用 SETNX 抢锁,只放一个请求去查 DB 重建缓存,其他请求等待 |
| 热 key 不过期 | 逻辑过期(value 里存过期时间)+ 后台异步刷新,物理上永远不过期 |
| 提前预热 | 大促前把热 key 主动加载到 Redis |
| 多级缓存 | 本地缓存(Caffeine)+ Redis,本地缓存挡住大部分请求 |
雪崩的规避:
| 手段 | 说明 |
|---|---|
| TTL 加随机值 | 基础 TTL + random(0, 600) 秒,避免同时失效 |
| Redis 高可用 | 哨兵 / Cluster,防止单点故障 |
| 限流熔断 | 应用层 Sentinel / Hystrix,DB 侧连接池上限 |
| 多级缓存 + 降级 | Redis 挂了自动降级到本地缓存 + 兜底默认值 |
| 数据预热 | 服务启动或大促前预加载热点数据 |
一句话记忆:穿透是查不存在的东西、击穿是单个热 key 挂了、雪崩是一大批 key 同时挂了。
Q18. Redis 缓存和数据库如何保证一致性?
面试时答了”先更新 DB 再删缓存”,但表达有点乱,被面试官打断纠正。系统化整理:
先明确一致性的等级:
- 强一致性:读写实时同步,性能代价大,通常需要分布式锁 + 事务,一般不用
- 最终一致性:允许短时间窗口内不一致,最终收敛。绝大多数业务的选择
四种经典策略对比:
| 策略 | 流程 | 问题 |
|---|---|---|
| 先更新 DB,再更新缓存 | 写 DB → 写 Redis | 并发下缓存写入顺序错乱,容易残留旧值;写多读少时浪费 |
| 先更新缓存,再更新 DB | 写 Redis → 写 DB | DB 失败时缓存脏了;同样有并发问题 |
| 先删缓存,再更新 DB(Cache Aside 变种) | 删 Redis → 写 DB | 删除后写 DB 前,另一个请求读缓存 miss → 从 DB 读旧值 → 写回缓存,长时间脏数据 |
| 先更新 DB,再删缓存(Cache Aside 标准做法) | 写 DB → 删 Redis | 极端情况下也可能不一致,但概率极低 |
推荐:Cache Aside Pattern(旁路缓存)
1 | 读: 先读 Redis → miss 则读 DB → 回填 Redis(带 TTL)→ 返回 |
**为什么是”删”而不是”更新”**:
- 更新可能存在并发覆盖(A 更新完 B 又更新,但 A 后写入)
- 有些缓存是多表 JOIN 计算出来的,更新代价高,删了让下次读时懒加载更划算
- 删除是幂等的,失败重试也安全
为什么”先删缓存 + 后写 DB”不安全:
1 | 时间线: |
“先更新 DB + 后删缓存”的极端场景(发生概率极低):
1 | T1: 线程 A 读缓存 miss |
工程加固手段:
| 手段 | 说明 |
|---|---|
| 延迟双删 | 更新 DB → 删缓存 → 睡一小段时间(如 500ms)→ 再删一次,兜底上面的极端场景 |
| 订阅 binlog(Canal / Debezium) | 通过 MySQL binlog 异步同步缓存,业务代码只写 DB,缓存由订阅者维护,解耦 + 顺序保证 |
| 消息队列 + 重试 | 删缓存失败时进 MQ 重试,保证最终成功 |
| TTL 兜底 | 缓存都带 TTL,即使某次删除失败,最迟 TTL 到期也会自愈 |
| 分布式锁 | 强一致场景下用 Redisson 锁住 key,读写串行化,性能差 |
面试话术模板:
“一般做最终一致性,采用 Cache Aside 模式:读走缓存,miss 回填;写先更新 DB 再删缓存。极端场景下用延迟双删或订阅 binlog(Canal)来兜底。强一致场景才考虑加分布式锁,但会牺牲性能,一般业务不这么做。”
Q19. Kafka / RocketMQ 这类消息队列如何实现高性能?
面试时答了零拷贝、Epoll、分区、批处理、压缩,其他没答上。系统化整理:
Kafka 高性能的核心手段:
| 手段 | 说明 |
|---|---|
| 顺序写磁盘 | 消息追加到 partition 的 log 文件末尾,顺序写比随机写快 1000 倍以上(机械盘尤其明显,SSD 也受益) |
| 零拷贝(sendfile) | 消费者拉消息时,数据从 page cache 直接送到网卡,不经过用户态,减少 4 次拷贝到 2 次 |
| Page Cache | 依赖 OS 的页缓存做读写加速,不在 JVM 堆内维护消息,避免 GC |
| 分区(Partition) | 一个 Topic 拆成多个 Partition 分布到多个 Broker,并行读写,横向扩展吞吐 |
| 批量发送 | Producer 攒批(batch.size + linger.ms)后一次发送,摊薄网络开销 |
| 压缩 | Producer 侧压缩(Gzip / Snappy / LZ4 / Zstd),Broker 直接存压缩后的 batch,Consumer 解压。LZ4 / Zstd 是主流(压缩比高 + CPU 开销低) |
| 稀疏索引 | 每个 segment 配一个 .index 文件,按 offset 稀疏索引,二分查找定位消息 |
| Epoll + Reactor | 网络层用 epoll(Linux)多路复用,少量线程处理大量连接 |
| 副本机制 | Leader/Follower 副本,写入走 Leader,Follower 拉取同步,保证可靠性不影响吞吐 |
RocketMQ 的差异:
- CommitLog 单一存储:所有 Topic 的消息都写到同一个 CommitLog,然后异步分发到 ConsumeQueue(索引)。好处是磁盘写入完全顺序化,坏处是读放大(需要按索引跳到 CommitLog 读)
- 消息过滤下推:支持 Tag / SQL92 过滤,Broker 侧过滤后返回,减少网络传输
- 事务消息 / 顺序消息 / 定时消息:内置支持,比 Kafka 更贴近业务
零拷贝的四种实现:
1 | 传统 read + write(4 次拷贝,2 次系统调用): |
Kafka 的架构关键点:
1 | Producer → Broker Cluster (多 Partition 多副本) → Consumer Group |
- Producer 按 key 分区(默认 hash),保证同 key 消息顺序
- Consumer Group 内 partition 均分,一个 partition 只能被 group 内一个 consumer 消费(决定了并行度上限)
- Rebalance 是常见性能坑:Consumer 上下线触发全组重分配,短暂停顿
Q20. 用 Redis / Kafka / MySQL / Nacos 等组件设计一个高可用系统,各起什么作用?
这是开放性架构题,考察对常见组件的整体把握。按”入口 → 服务 → 数据 → 观测”四层展开:
1 | ┌─────────────────┐ |
各组件作用详解:
| 层次 | 组件 | 作用 |
|---|---|---|
| 入口层 | DNS / GSLB | 全局调度、跨机房切换 |
| CDN | 静态资源加速、边缘缓存 | |
| WAF | 防 SQL 注入、XSS、CC 攻击 | |
| LB(LVS / SLB) | 4/7 层负载均衡,收敛连接 | |
| 应用层 | K8s | 容器编排、自愈、滚动更新、弹性伸缩 |
| Ingress | 集群入口路由(域名/路径) | |
| Service / Pod | 服务发现与流量分发 | |
| HPA | 按指标自动扩缩容 | |
| 中间件层 | Nacos | 服务注册发现 + 配置中心 |
| Sentinel | 限流熔断降级 | |
| Redis | 缓存 + 分布式锁 + 计数 | |
| Kafka / RocketMQ | 异步解耦 + 削峰填谷 + 日志聚合 | |
| 数据层 | MySQL | 关系型数据主存 |
| MongoDB | 半结构化 / 灵活 Schema 数据 | |
| OSS / NAS | 对象存储(图片、视频、备份) | |
| Elasticsearch | 全文检索 / 日志分析 | |
| 观测层 | Prometheus + Grafana | 指标监控与可视化 |
| Loki / EFK | 日志聚合与查询 | |
| SkyWalking / Jaeger | 分布式链路追踪 | |
| Alertmanager | 告警路由与通知 |
高可用设计原则:
- 无单点:每一层都做冗余(多副本、多可用区、多集群)
- 无状态:应用无状态化,Session 放 Redis,才能自由扩缩容
- 故障隔离:舱壁模式(线程池隔离)、限流熔断、按业务分集群
- 降级预案:非核心功能可关闭(大促时的推荐、评价)
- 异步解耦:非核心链路走 MQ,避免同步阻塞
- 可观测:Metrics / Logging / Tracing 三件套齐全,故障可定位可复盘
- 演练验证:定期做故障演练(Chaos Engineering)、多活切换演练
回答技巧:面试官问这题不是要听你背组件清单,而是看你有没有系统性思维——能不能按流量走向把组件串起来,能不能讲清每个组件解决什么问题、不用会怎样。
四、大模型 SRE 与 AI Agent
Q21. 大模型服务常见的限流手段有哪些?如何应对客户突发流量?
这题是模型 SRE 岗位的核心考点。分限流维度和突发流量处置两部分讲。
限流维度(对客户可见的配额):
| 维度 | 说明 | 典型场景 |
|---|---|---|
| TPM(Tokens Per Minute) | 每分钟消耗的 token 总量 | 长文本应用的主要约束 |
| RPM(Requests Per Minute) | 每分钟请求数 | 短文本、高频调用场景 |
| 并发数(Concurrency) | 同时在处理的请求数 | 保护后端推理引擎不被打爆 |
| 日/月配额 | 总量控制 | 商务合约约束 |
| 模型级配额 | 每个模型独立配额 | 稀缺资源(如 GPT-4 级别)单独管 |
保护性限流(对客户不可见,系统内部):
| 维度 | 说明 |
|---|---|
| Burst 增速 | 单位时间内的增长速率(如每秒新增请求数),防止瞬时突刺 |
| 步长/爬坡 | 从 0 到峰值不允许一步到位,必须逐步爬升 |
| 排队时长 | 请求在队列中等待超过 X 秒直接拒绝 |
| 单连接 QPS | 防止单客户端建大量连接绕过限制 |
这些是网关的自我保护,客户看不见但真实存在。任何一家大模型厂商(火山、百炼、OpenAI)都有类似机制。
客户突发流量的处置策略(按优先级):
① 首选:让客户做流量整形(Client-Side)
- 平滑上量:不要瞬间从 100 QPS 拉到 10000 QPS,按分钟级逐步爬坡
- 客户端限流:应用侧用令牌桶 / 漏桶自控
- 网关侧:客户自建 API 网关做前置限流
- 重试策略:指数退避 + 抖动,不要死循环重试放大流量
② 推荐升级产品形态
对于流量稳定且量大的客户,推公有 API 不如推:
| 产品形态 | 特点 |
|---|---|
| PTU / TPM 预留 | 预留固定算力,独享,无 burst 限流 |
| MU(Model Unit) | 按模型单元计费,容量保障 |
| 独立部署 / 专属实例 | 完全隔离,客户自主控制 |
这类产品没有 burst 限流(因为容量本来就是独享的),是稳定大流量客户的首选。
③ 内部调整限流阈值(危险操作)
如果客户拒绝流量整形、也不用预留产品,前线又非常强硬,最后手段是调整该客户的 burst 限流配置:
- 后台可以调增长量、步长、增长比例
- 风险极大:曾经出现过调整后其他大客户突增流量把整个集群打爆的情况
- 现在的做法:只调额度(TPM/RPM),不调 burst 配置,因为额度影响面可控,burst 影响面是整个池子
④ 兜底:切流 + 扩容
如果已经打挂了:
- 按长度分桶把流量调度到其他部署
- 扩容 GPU 实例(HPA + 手动补副本)
- 极端情况下对该客户完全限流
回答技巧:这题面试官想听的不是”有哪些限流算法”,而是你对客户工况的理解——什么时候该推产品升级、什么时候该让客户改代码、什么时候自己扛。体现的是”技术 + 商务”的综合判断。
Q22. 你处理过最复杂/最难的故障是怎样的?整体流程是什么?
这是开放题 + 项目深挖,考察的是流程规范性和你在其中的角色。以云上重大故障为例讲流程:
故障生命周期:
1 | 1. 告警触发 → 2. 应急拉起 → 3. 定级 → 4. 止血/恢复 → 5. 复盘 → 6. 改进跟踪 |
① 告警与拉起
- F0 预警:所有告警最初都是 F0,由应急中心调度员(GOC)统一接手
- 调度员根据告警内容拉起相关人员:
- SRE:定位、止血
- 产研(RD):根因分析
- 应急接口人:跨团队协调
- PR / 法务(对客故障):对外沟通口径
- 销售 / 服务:客户侧安抚
② 故障定级
按事先定义的故障矩阵评估:
| 维度 | 举例 |
|---|---|
| 影响产品数 | 单个产品 / 多个产品 / 全站 |
| API 可用率 | < 99% → P4,< 80% → P3,< 20% → P2,接近 0 → P1 |
| 持续时长 | 5 分钟内 / 30 分钟内 / 超过 30 分钟 |
| 影响客户数 | 单个客户 / 头部客户 / 大量客户 |
| 业务损失 | 是否有资金损失、数据丢失 |
③ 止血与恢复(SRE 的三把斧)
以大模型故障为例:
| 手段 | 说明 |
|---|---|
| 切流 | 按长度分桶调度:某个模型的长文本请求突增打挂集群,把这部分流量切到其他部署 |
| 扩容 | HPA 自动扩 + 手动补副本,把实例数拉上去 |
| 限流 | 保护性限流兜底,把异常客户限住,防止扩散 |
传统服务的三板斧是:切流、扩容、限流,本质一样。
④ 时间要求(内部标准)
- 5 分钟定位:告警发生后 5 分钟内明确”是什么问题”
- 10 分钟定界:明确”影响范围有多大、涉及哪些组件”
- 30 分钟恢复:完成止血,业务恢复
⑤ 各角色分工
| 角色 | 职责 |
|---|---|
| 调度员(GOC) | 拉群、通报、协调、时间线记录 |
| SRE | 监控看板、切流扩容限流、执行 SOP |
| 产研 | 分析请求特征、定位根因、修复代码 |
| 对客团队 | 客户侧沟通、逃逸方案、补偿方案 |
⑥ 复盘与改进
- 恢复后输出故障报告:时间线、根因、影响面、处理过程、改进项
- 对客故障:还要出对客报告(客户侧可优化点,比如客户自己没做流量整形、没做熔断降级)
- Action Item 跟踪闭环:每条改进项要有责任人、截止日期、验收标准
回答技巧:面试官问这题不是要听你讲一个具体故障多牛,而是看你有没有规范化处理故障的能力——能不能讲清角色分工、时间要求、SOP 步骤。有实战经验的人会自然带出”5 分钟定位、10 分钟定界、30 分钟恢复”这类内部标准,以及”切流/扩容/限流”三板斧这种行业共识。
Q23. AI 运维诊断 Agent 是怎么做的?踩过什么坑?
这题是差异化亮点,重点讲数据来源、Agent 架构、部署选型三块。
核心认知:AI 运维诊断的关键是”数据”,不是”模型”
如果人工都要排查很久(数据分散、看板不齐全),凭什么指望 AI 在没有数据的情况下帮你诊断?先把可观测做好,再谈 AI Agent。
前置条件:可观测三大支柱
| 支柱 | 数据 | 工具 |
|---|---|---|
| Metrics | 时序指标(QPS、延迟、错误率、资源使用) | Prometheus / VictoriaMetrics |
| Logging | 结构化日志 | Loki / Elasticsearch / SLS |
| Tracing | 分布式调用链 | Jaeger / SkyWalking / OpenTelemetry |
三者通过 TraceID 串联:告警带 TraceID → 反查日志 → 定位调用链 → 关联指标。
Agent 工作流程:
1 | 告警触发(含 TraceID / 服务名 / 时间窗) |
技术实现路径:
方案 A:Claude Code SDK / Cursor Agent 模式
- 优势:现成的 ReAct 循环、工具调用协议、上下文管理
- 劣势:沙箱部署难,生产网 / 客户侧不方便直接用;数据出域风险
方案 B:AgentScope / LangGraph / LangChain 自建
- 优势:可控性强,能定制 ReAct 逻辑、工具集、记忆
- 劣势:MCP 工具要自己封装(每个数据源都要写适配器);部署链路长
方案 C:MCP(Model Context Protocol)+ 现成 Agent
- 优势:工具生态标准化,写一次 MCP Server 可以被任何 MCP Client 使用
- 落地方式:把 Prometheus、Loki、Jaeger、K8s API 都封装成 MCP Server,Agent 通过 MCP 协议调用
生产落地的坑:
| 坑 | 说明 |
|---|---|
| 数据源集成难 | 每个监控系统都有自己的查询语法,工具封装成本高 |
| 模型选型 | 生产网数据不能出域 → 用私有化模型(Qwen、Llama 自部署);开发环境可以用云上模型 |
| 权限与审计 | Agent 的操作要能审计,特别是执行类工具(重启 Pod、扩容) |
| 幻觉与误导 | LLM 可能编造根因,必须让 Agent 强制引用证据(哪个指标、哪条日志) |
| 成本 | 一次诊断可能消耗几万 token,高频告警下成本失控 |
| 收敛时间 | Agent 多轮 ReAct 可能耗时几分钟,紧急故障场景等不起 |
关键设计:AI Agent 只做辅助决策,不做自动执行。
- 只读工具(查指标、查日志):Agent 自由调用
- 写工具(重启、扩容、切流):Agent 输出建议 → 人工确认 → 另一个执行系统去做
AI 与执行系统之间必须做隔离:Agent 只能从预定义的 SOP 库中选择步骤,SOP 由另一个程序按顺序执行,Agent 没办法直接调用底层 API。
Q24. LLM 有哪些场景不适合使用?
这题面试官问得非常好——**”更重要的是它什么时候不能用,你用错了代价是很惨重的”**。
核心原因:LLM 输出本质不稳定
即使 temperature=0、top_p=1,同一个 prompt 在不同时间、不同模型上输出也可能不同。这是推理机制决定的(自回归采样 + 浮点精度 + KV Cache 实现差异),不是工程问题。
不适合的场景:
| 场景 | 为什么不适合 | 替代方案 |
|---|---|---|
| 强结构化输出且下游强依赖 | JSON Schema 约束下模型仍可能输出不合法 JSON,下游解析崩溃 | 用约束解码(xgrammar / outlines)+ 校验兜底;或用传统规则引擎 |
| 确定性计算(数学、逻辑) | LLM 不是计算器,会算错 | 调用 Python / SQL / 计算器工具 |
| 精确数据查询 | 幻觉问题,会编造不存在的记录 | RAG + 强引用 + 数据库查询 |
| 高危运维操作(故障注入、删库、切流) | 输出不确定 → 结果不可预期 → 背锅 | 只能做辅助,人工必须确认;用预定义 SOP 而不是让 AI 自由发挥 |
| 核心业务代码全权生成 | 出了故障责任归属不清 | AI 辅助编写,人工 Code Review;关键路径必须人审 |
| 实时性要求极高 | 推理延迟几百 ms 到几秒 | 传统规则引擎、缓存 |
| 成本敏感的高频调用 | 每次几万 token,成本失控 | 用小模型 / 蒸馏模型 / 传统方法 |
| 法律 / 医疗 / 金融决策 | 责任问题 + 幻觉风险 | 只能做辅助分析,最终决策必须人工 |
JSON Schema 约束输出的坑(真实故障案例):
- 客户用 JSON Schema 约束模型输出,下游业务强依赖字段
- 模型偶尔输出不合法 JSON(多字段、少字段、类型错误)
- 下游解析失败 → 业务异常
- 更糟的情况:JSON Schema 过于复杂导致推理引擎本身出问题(编译慢、内存暴涨、GPU 卡死)
应对方式:
- 约束解码(Constrained Decoding):xgrammar、outlines、guidance 等库在解码阶段强制符合语法
- 校验兜底:输出后用 JSON Schema 校验,失败重试或降级
- 简化 Schema:避免深度嵌套、复杂正则、动态模式
- 分桶缓存:相同 Schema 复用编译结果,避免重复编译
面试话术:
“LLM 的核心特点是输出不确定,所以任何对确定性有强要求的场景都要慎用。比如让模型输出严格 JSON 且下游强依赖,即使加了 Schema 约束也可能出问题;再比如让 AI 自动做故障注入这种高危操作,出了事谁背锅?我们的原则是:AI 做辅助分析和推荐,人工做最终决策和执行。核心代码可以让 AI 写 80%,但 Code Review 必须回归到人。”
加分回答:主动提”约束解码“和”JSON Schema 编译缓存“这类工程细节,能体现出你不只是知道”LLM 不稳定”,还知道具体怎么在工程上兜底。
反问
面试最后的反问环节,两场都问了对方团队的一些情况,作为参考:
基础面(0914):
| # | 问题 | 面试官答复要点 |
|---|---|---|
| 1 | 目前应急流程和基建情况? | 各组件监控告警 + 定期演练 + SOP 沉淀成 skills |
| 2 | AI 在运维中的应用程度? | 知识库召回、故障定位(多数据源分析)、SOP 挑选与执行 |
| 3 | AI 自动化操作怎么做安全隔离? | Agent 只能选 SOP,SOP 由独立程序按步骤执行,Agent 无法直接操作 |
| 4 | 有没有遇到过 AI 相关的重大故障? | 有:AI 反复重写同一个 bug、误删分支历史、参数达到上限 |
| 5 | 团队用什么云? | 内部为主,公有云用集团子公司,流程偏传统,AI 提单未成体系 |
模型 SRE 面:
| # | 问题 | 面试官答复要点 |
|---|---|---|
| 1 | 团队的角色定位?是 SRE 吗? | 是模型 SRE |
| 2 | 内部运维平台能做哪些操作? | 切流、扩容、新建部署,不涉及底层修改 |
| 3 | 团队规模? | 模型 SRE 团队规模不小 |
| 4 | 遇到过最大的问题是什么? | 资源问题——卡不够、卡型不匹配、突增流量打爆集群 |
| 5 | 火山模型”从不出问题”是真的吗? | 不好说,但稳定性工作大家都做了很多;限流是共同手段 |
| 6 | 长时间的重大故障? | 影响时间超过 30 分钟的比较少 |
反问的价值:反问不是走过场,是双向评估——你能通过反问判断这个团队的成熟度(有没有 SOP、有没有演练、有没有 AI 落地)、技术栈(自建 vs 云上)、风险点(手动切流 vs 自动切流)。这些信息反过来决定了你入职后的工作体验和成长空间。
AI总结
两场面试下来最大的感受是:日常做的时候都能做,但让自己系统讲一遍就磕巴。
具体表现在:
- 概念混淆:把 Namespace 的”隔离”讲成 CGroup 的能力;把 Pending 的排查方向说成探针问题(探针影响的是 Ready)
- 细节遗忘:三次握手说不出 SYN/ACK 标志位,拥塞控制说不出 CUBIC/BBR,归并排序讲不清合并过程
- 表达松散:Cache Aside 讲成”先删缓存再写 DB”,被面试官纠正后才反应过来
这些东西不是不会,是没有系统整理过。日常运维更多是”遇到问题 → 搜 → 解决”的即时模式,缺少把知识点串成体系的输出。
后续准备方向:
- 基础八股回炉:TCP/IP、操作系统、数据结构与算法这些”面试必考但日常少用”的东西要定期复习
- K8s 深入原理:不能只停留在”用过”,要理解 QoS、驱逐、调度器打分、CGroup v2 的实现细节
- 系统化输出:每个知识点写一篇博客,用输出倒逼输入
- AI + 运维的落地经验:这是差异化优势,要把项目细节、踩坑、选型权衡讲透
基础不牢,地动山摇。持续学习。