**答案:**进程是操作系统进行资源分配和隔离的基本单位,拥有独立的虚拟地址空间、文件描述符和系统资源。线程是 CPU 调度的基本单位,同一进程内的线程共享堆、全局变量、文件描述符等资源,但拥有独立的栈、寄存器和程序计数器。
因此,进程之间隔离性强、创建和切换成本较高;线程共享资源、通信成本低,但需要通过锁、原子操作等方式解决并发安全问题。
**答案:**通常不会。死锁必须满足互斥、占有且等待、不可剥夺、循环等待四个条件。这里是单向依赖,没有形成资源等待环,因此不满足循环等待条件。
但如果线程 A 长时间不释放资源、异常退出,或实际存在隐藏的反向依赖,仍可能出现长时间阻塞,表现上类似死锁。因此还要结合锁持有时间、调用链和线程 dump 判断。
**答案:**可能。即使没有死锁,线程也可能因为等待锁、等待 I/O、线程上下文切换、线程池排队或资源竞争而变慢。排查时应关注锁等待时间、线程池队列长度、CPU 使用率、I/O 延迟和上下游调用耗时。
**答案:**可能。线程饥饿是线程长期无法获得 CPU 或所需资源。常见原因包括锁分配不公平、高优先级线程持续占用资源、某线程持锁时间过长,以及线程池队列或调度策略不合理。
可以通过公平锁、缩短临界区、合理设置优先级、拆分任务和监控等待时间来缓解。
**参考答案:**遇到过。接口变慢通常不是单一原因,可能来自慢 SQL、缓存失效、下游 RPC 变慢、连接池耗尽、线程池排队、GC、流量突增或最近发布的代码。我的处理方式是先确认影响范围和时间点,再通过监控和 Trace 拆分耗时,定位根因后采取限流、降级、扩容或回滚,并补充监控避免复发。
**答案:**可以按以下顺序排查:
**答案:**TCP 面向连接,提供可靠、有序、无重复的数据流,并具备确认、重传、流量控制和拥塞控制,但连接和协议开销较大。UDP 无连接、报文边界明确、开销小、延迟低,但不保证到达、顺序和去重,需要业务层自行处理。
**答案:**三次握手用于确认双方的发送和接收能力,并同步初始序列号。客户端发送 SYN,服务端通过 SYN-ACK 表示收到了请求且具备发送能力,客户端再发送 ACK,确认收到了服务端的响应。
两次握手无法让服务端确认客户端已经收到自己的响应,也无法可靠避免历史连接请求造成错误连接,因此需要第三次 ACK 完成双方确认。
**答案:**要看业务目标。文件、订单、接口请求等不能丢数据的场景优先选择 TCP,或使用具备可靠传输能力的 QUIC;音视频、实时游戏等更关注实时性、允许少量丢包的场景可以选择 UDP。不能简单认为 UDP 一定比 TCP 更适合弱网。
**答案:**UDP 可能丢包、乱序、重复、被网络丢弃,也没有拥塞控制和连接状态管理。可以在应用层增加序列号、ACK、超时重传、去重、乱序重排、心跳、拥塞控制和前向纠错;对非关键数据允许丢弃,对关键数据单独保证可靠性。
**答案:**TCP 是有序字节流。一个数据包丢失后,即使后面的数据包已经到达,也必须等待丢失的数据包重传并按顺序交付,因此后续数据被阻塞,这就是队头阻塞。HTTP/2 虽然支持多路复用,但多个流仍共享一条 TCP 连接,仍可能受到 TCP 层队头阻塞影响;QUIC 基于 UDP,可降低这种影响。
答案:
2xx:请求成功,如 200 成功、201 创建成功、204 成功但无响应体。3xx:重定向,如 301 永久重定向、302 临时重定向、304 使用缓存。4xx:客户端请求有问题,如 400 参数错误、401 未认证、403 无权限、404 资源不存在、429 请求过多。5xx:服务端处理失败,如 500 内部错误、502 网关收到无效响应、503 服务不可用、504 网关超时。**答案:**先区分请求是否幂等。幂等请求可以进行有限次数重试,并使用指数退避和随机抖动;非幂等请求必须携带幂等键,避免重试造成重复写入。与此同时要设置超时、熔断、降级、备用节点和本地缓存,并上报错误率、重试次数和链路信息,避免无限重试形成重试风暴。
**答案:**可以将库存预热到 Redis,使用原子自减或 Lua 脚本完成“判断库存并扣减”的操作,避免超卖;请求量过大时增加限流、排队、分片和异步下单。扣减成功后通过消息队列创建订单,数据库作为最终持久化和对账依据,并使用业务幂等键、库存补偿和定时对账处理异常。
**答案:**先把概率转换成整数权重,再计算累计权重。例如三个奖品权重为 10、20、70,总权重为 100,可以生成区间 [1,10]、[11,30]、[31,100]。随机数命中哪个区间,就选择对应奖品。权重较多时可以使用累计数组配合二分查找。
**答案:**先根据用户和活动信息确定奖池,读取奖池的累计权重表,生成 1 到总权重之间的随机数,再通过顺序查找或二分查找定位奖品。命中奖品后还要校验活动有效期、用户资格和库存,库存扣减成功才确认中奖,否则执行重试、兜底奖品或失败处理。
**答案:**先根据用户积分计算档位,例如普通、银卡、金卡,再使用“活动 ID + 档位 ID”选择对应奖池。每个奖池独立维护奖品、权重、库存和有效期,并通过版本号发布配置,避免配置修改过程中读到半成品数据。
**答案:**数据库保存活动、档位、奖池版本、奖品、权重、库存、有效期和发布状态。配置发布后生成不可变版本,缓存按照“活动 + 档位 + 版本”存储;应用启动或配置变更时装配成内存累计权重表。抽奖请求只需计算档位、读取当前版本并在内存中查找,库存和中奖记录仍需落到可靠存储中。
**答案:**取决于业务一致性要求和前置操作是否产生副作用。强一致、可逆的本地操作可以回滚;跨服务调用通常不适合依赖长事务,需要采用补偿或最终一致性。库存、资金等关键数据要优先保证不重复扣减、不丢失,并记录完整执行状态。
**答案:**单库内可以使用本地事务;跨服务场景可以使用 Saga、事务消息或补偿事务。每个节点都需要定义正向操作和幂等的逆向操作,例如扣库存对应补库存。回滚失败时要记录补偿任务,支持自动重试、告警和人工处理。
**答案:**采用最终一致性。通过状态机记录每个节点的执行状态,使用可靠消息通知后续节点;失败事件进入重试队列或补偿表,由后台任务持续处理。再结合幂等键、业务对账、状态查询和人工介入,保证最终能够收敛到正确状态。
**答案:**平台可以分为数据采集、符号化、聚类分析、责任归属、建议生成和修复闭环几个模块。采集崩溃、卡顿、网络失败、设备、系统、版本、用户路径和堆栈;服务端完成脱敏、符号化和问题聚类;再结合代码归属分配负责人,生成带证据的修复建议,并通过工单跟踪验证和发布结果。
**答案:**先对堆栈做符号化和归一化,识别异常类型、关键栈帧、模块路径、业务标识和版本。再将代码路径映射到模块、业务线和负责人,结合最近变更、影响版本和历史处理记录进行综合判断,不能只根据堆栈顶部的一行代码直接认定责任人。
**答案:**可以结合代码仓库、目录规则、模块注册表、CODEOWNERS、提交记录、业务标签和发布系统建立映射。映射关系需要带版本和生效时间,支持模块拆分、负责人变更和历史问题追溯,并允许业务方手动修正。
**答案:**可以根据出错栈帧、顶层业务模块、最近变更、代码归属、影响版本和历史处理记录打分。最接近根因且对该模块有维护责任的人作为主要负责人,其他相关团队作为协同人;同时展示判定依据,支持人工转派,避免误派后无人处理。
**答案:**将归一化堆栈、出错代码上下文、最近提交、设备环境、触发路径和相似历史问题作为输入,输出“可能根因、定位依据、建议改动、验证步骤”四部分。例如指出空指针发生在哪个调用链、哪个参数可能为空,以及需要补充的校验和测试场景。
**答案:**建议必须绑定具体证据,不能只输出“加强判空、优化性能”等泛化结论。可以要求模型引用堆栈行号、代码变更、监控指标或复现条件,并对建议标注置信度;没有足够证据时应明确说明不确定性,交由人工补充信息。
**答案:**将问题生成工单,包含问题指纹、影响范围、责任人、证据、建议和验证步骤。业务方确认根因后关联代码提交和测试结果,修复发布后持续观察同类问题是否下降;如果建议错误,业务方反馈原因,用于修正映射规则和后续建议。
**答案:**先对堆栈地址、行号和动态参数归一化,使用异常类型、关键栈帧、业务场景、版本和设备环境生成问题指纹,再对相似指纹聚类。优先级不能只看发生次数,还应综合影响用户数、崩溃率、业务重要性、版本覆盖、增长趋势和修复成本。新版本回归或根因不同的问题需要单独拆分。
这篇面经的能力考察链路是:
回答系统设计题时,建议始终补充:适用场景、核心机制、异常处理、监控指标和验证方式。