分布式面试题
本页只放分布式系统面试标准回答、追问点和知识点跳转。详细原理统一沉淀到知识点页,尤其是 分布式系统从零到生产级掌握。
使用方式
mermaid
flowchart TD
A["面试页<br/>标准回答和追问"] --> B["知识点页<br/>详细原理、流程图、Demo"]
B --> C["项目场景<br/>订单、支付、库存、采集、搜索同步"]高频问题
| 面试题 | 标准回答 | 原理知识点 |
|---|---|---|
| 怎么判断分布式是否真正学懂 | 不能只背 CAP、TCC、Saga、Seata、Redis 锁。真正学懂要能从网络不可靠、远程调用超时状态未知、重复请求、幂等、状态机、CAP/BASE、一致性级别、分布式事务选型、分布式锁边界、缓存/ES/MQ 最终一致、限流熔断和生产排查一路讲下来,并能说明项目里为什么这样设计、不这样会出什么问题。 | 分布式系统从零到精通验收清单 |
| 分布式系统是什么 | 分布式系统是多个进程、服务或数据库通过网络协作完成一个业务目标。它能提升容量、扩展性和团队协作效率,但会引入网络失败、调用超时、重复请求、数据不一致、链路排查复杂等问题。 | 从零到生产级掌握 |
| 分布式系统有哪些硬事实 | 网络调用存在明确成功、明确失败和结果未知;节点宕机与网络分区难以瞬间区分;请求可能重复,状态会短暂分叉,机器时钟不能提供可靠全局顺序;局部成功不等于全局成功,重试会放大故障,任何协调组件本身也有失败边界。 | 分布式系统八个硬事实 |
| 分布式常见组件应该怎样分类 | 通信层有 HTTP、Dubbo、gRPC、MQ;寻址协调层有 Nacos、Consul、ZooKeeper、etcd;流量治理层有 Gateway、负载均衡、限流、熔断;状态一致性层有幂等、事务、缓存、CDC;复制共识层有 Quorum、Raft、ZAB;运行保障层包含发布、观测、补偿和对账。分类的意义是明确组件边界,避免拿共识算法直接解释业务事务。 | 六层知识地图、组件职责全景 |
| Kubernetes服务发现完整链路是什么 | Service提供稳定身份;EndpointSlice Controller根据selector、Pod地址和Ready形成后端快照;CoreDNS解析名称;kube-proxy或eBPF数据面把新连接映射到Endpoint。Readiness和摘流异步传播,已有长连接不会自动迁移。 | 完整原理、面试专题 |
| Service Mesh控制面和数据面怎样协作 | 控制面观察服务、端点和策略,通过LDS/RDS/CDS/EDS/SDS向代理下发配置;数据面按本地已接受快照处理真实请求。配置NACK时代理保留Last Known Good,控制面故障不会立刻切断已有流量,但端点、路由和证书无法持续更新。 | Mesh完整原理、面试专题 |
| Service Mesh 503 的 NR、UH、UF、UO、UT 怎么排查 | 先确定是哪一跳代理返回,再按Flag定位阶段:NR查Listener/HCM/Route/RDS,UH查Cluster/EDS/Endpoint/健康和Subset,UF查网络端口和mTLS,UO查连接池、Pending和Circuit Breaker阈值,UT查Route超时、下游P99、线程池和DB。Flag只是代理视角,写请求仍要按业务幂等键查事实。 | Response Flag速查、Mesh面试题 |
| 服务发现完整链路是什么 | 服务提供者启动后注册服务名、IP、端口、健康状态和metadata;注册中心维护服务表并通过推送或拉取传播给消费者;消费者在本地维护实例快照,LoadBalancer按健康、版本、区域和权重过滤后选择实例,底层HTTP/RPC客户端直连目标。注册中心是控制面,不转发业务请求。 | 服务发现完整原理、服务发现面试题 |
| 注册中心挂了服务还能调用吗 | 运行中的调用方如果已有本地快照,且目标实例数据面可达,短时间可能继续调用;但新实例注册、坏实例摘除、规则变更、新消费者启动和缓存为空场景会受影响。不能把本地缓存当成永久可靠事实。 | 控制面和数据面、本地快照 |
| 分布式ID怎么选型 | 先区分技术主键、业务单号、幂等键和TraceId。普通业务主键常用Snowflake或数据库号段;需要集中审计、多业务Tag和跨语言发号可选号段;需要本地高吞吐和低延迟可选Snowflake,但必须治理WorkerId冲突和时钟回拨。严格连续、全局唯一、高可用和无限吞吐不能同时免费获得。 | 分布式ID完整原理、分布式ID面试题 |
| Snowflake为什么怕时钟回拨和WorkerId重复 | Snowflake唯一性依赖时间戳、WorkerId和同毫秒序列。时钟回拨后继续按较小时间生成,可能复用历史毫秒和序列;两个进程共用WorkerId时,同毫秒从相同序列发号也会重复。短回拨可有界等待,长回拨应拒绝告警;WorkerId要受控分配、续租、冲突检测和启动代际隔离。 | 时钟回拨、WorkerId分配、Snowflake Demo |
| gRPC一次Unary调用怎样走 | 生成Stub通过ClientCalls创建逻辑ClientCall,NameResolver返回地址与Service Config,LoadBalancer的Picker选择Subchannel;ClientCallImpl应用Deadline,RetriableStream可能创建多个物理Attempt,Netty在HTTP/2连接上创建Stream。服务端ServerImpl查找方法、创建Context并切到应用Executor,业务完成后用消息与Trailers返回最终Status。 | Java内部原理、独立面试题 |
| 微服务雪崩怎样形成并治理 | 下游变慢让in-flight、线程、连接和队列增加,多层重试进一步放大流量。应以端到端Deadline限制等待,用Bulkhead隔离资源、并发限制和Load Shedding保护容量、熔断阻断持续故障,并通过有界降级、HALF_OPEN和Warmup控制恢复。 | 稳定性完整原理、面试专题 |
| 熔断器为什么要有最小样本、慢调用比例和HALF_OPEN | 最小样本避免低QPS少量偶发失败导致误熔断;慢调用比例能发现“都成功但很慢”的依赖故障,避免线程和连接被慢请求占满;HALF_OPEN只放少量探测请求验证恢复,防止OPEN后全量放行造成恢复风暴。 | 熔断窗口指标、HALF_OPEN探测、稳定性面试题 |
| 过期请求为什么要丢弃 | 请求在队列中等到Deadline耗尽后,即使继续执行也无法给用户返回价值,却会继续占用线程、连接、数据库锁和下游配额,形成幽灵流量。应在入队前、出队执行前和下游调用前检查剩余Deadline,不足就快速拒绝或降级。 | 基于Deadline的Load Shedding、过载保护面试题 |
| 微服务依赖治理怎么做 | 先画接口依赖图,把下游分为强依赖、弱依赖、可选依赖、异步依赖和外部依赖;再按故障域拆线程池、信号量、HTTP连接池、数据库连接池和队列容量。每个依赖都要有超时、重试、Bulkhead、熔断、降级、补偿和观测策略。弱依赖不能拖垮核心链路,强依赖不能伪装成功。 | 依赖治理完整原理、依赖治理面试题 |
| 强依赖和弱依赖怎么区分 | 强依赖不成功就不能兑现当前业务承诺,例如库存冻结、支付确认;弱依赖失败只影响体验或辅助信息,例如推荐、头像、营销标签。强依赖失败应明确失败或返回UNKNOWN再查询事实,弱依赖应短超时、低并发、快速降级。 | 依赖类型、降级语义 |
| 多租户隔离怎么做 | 多租户隔离不是只加tenant_id字段,而是身份、数据、资源、缓存、消息、数据库和审计全链路治理。Gateway确认可信租户身份并清洗Header,服务层校验资源归属,SQL强制带租户条件,缓存Key、MQ消息、ES文档和审计日志带租户维度,资源池按租户限流和隔离。 | 多租户隔离完整原理、多租户面试题 |
| 一个大租户拖垮全站怎么办 | 先按租户看QPS、P99、错误率、线程池、连接池、MQ分区和Redis热Key;临时降低该租户入口限流和高成本接口并发,暂停或限速批处理;长期做租户配额、Bulkhead、独立队列、大租户独立库或独立集群。 | 热租户治理、热租户Runbook |
| 怀疑租户串数据怎么排查 | 拿traceId、userId、tenantId和资源ID,查Gateway是否清洗Header、Feign/RPC是否白名单透传、Service是否校验资源归属、SQL是否缺tenant_id、Redis Key是否缺租户、ES DSL是否带tenant filter,并用审计日志确认影响范围。 | 串数据Runbook |
| 微服务错误语义怎么设计 | 先把错误分为传输、协议、框架、业务和数据几类;HTTP状态表达协议大类,业务code表达领域结果,异常类用于服务内部控制流。响应要有稳定code、traceId、retryable、state和受控details。写请求超时要进入UNKNOWN并按幂等键查询事实,不能把所有错误都当500或都自动重试。 | 错误语义完整原理、错误语义面试题 |
| 哪些错误可以重试,哪些不能重试 | 可重试必须同时满足瞬时错误、操作幂等或无副作用、剩余Deadline足够、重试预算未耗尽。连接建立失败、503、部分死锁可有限重试;参数错误、权限拒绝、库存不足、解码失败通常不重试;Read Timeout的写请求多半是UNKNOWN,应查事实。 | 重试分类、结果未知 |
| 微服务容量规划怎么做 | 先明确业务峰值、SLO、成功率和错误预算;再画完整调用链,拆Gateway、应用线程池、HTTP连接池、Redis、MySQL、MQ和第三方容量预算。压测时找P99恶化前的单实例安全吞吐,乘以实例数、安全系数和N-1冗余,并用最小下游容量兜底。 | 容量规划完整原理、容量规划面试题 |
| 混沌工程是什么 | 混沌工程不是随机断生产,而是在明确假设、稳态指标、爆炸半径、停止条件和回滚方案下做受控故障注入,验证超时、重试、熔断、限流、降级、幂等、补偿和恢复机制是否真的有效。 | 故障演练完整原理、故障演练面试题 |
| 怎么证明熔断降级真的有效 | 注入下游慢调用、500、连接失败、读超时和恢复场景,观察P99、错误率、线程池、连接池、熔断状态、降级响应和业务事实。若写请求超时,要验证幂等号查询事实,而不是重复副作用。 | 下游慢调用演练、写请求超时演练 |
| 故障演练为什么要控制爆炸半径 | 演练目标是验证韧性,不是制造事故。要从测试、预发、生产单实例、灰度租户、小比例流量逐步扩大,并设置停止条件、负责人、观测面板和回滚方案。 | 爆炸半径设计 |
| 为什么扩容后RT不降 | 扩容只有在瓶颈位于可横向扩展的应用层时才有效。如果瓶颈在MySQL锁、慢SQL、Redis热Key、MQ分区、HTTP连接池、第三方配额或重试风暴,应用实例越多可能只是把更多请求推向共享瓶颈。排查要看每实例QPS、P99、线程池、连接池、DB锁、Redis热Key和MQ Lag。 | 扩容为什么不一定有效、扩容后RT不降 |
| QPS不高为什么线程池也会满 | 并发约等于到达率乘以停留时间。QPS不高但下游慢、锁等待、连接池等待或第三方超时,会让请求长时间占住线程,in-flight不断升高,最终线程池、连接池和队列都满。 | Little定律、线程池满Runbook |
| 微服务Deadline和重试预算怎么设计 | 从入口SLO建立总Deadline,逐层扣减Gateway、服务本地、下游逻辑调用、单次Attempt、连接池等待、DB查询和响应返回预算;每一跳传播剩余预算,不能每层重新给完整超时。重试只能由一个主要层负责,必须受最大Attempt、退避抖动、总Deadline和Retry Budget限制;写操作还要幂等键、状态查询和补偿处理UNKNOWN。 | 分层超时、重试所有权、重试与幂等 |
| OpenTelemetry遥测链路怎样走 | Instrumentation通过API创建Span、Metric等,SDK负责采样、聚合和批量导出,Collector接收后执行内存保护、资源补充、过滤、Tail Sampling与路由,再写入后端。任一层都可能丢数据,因此无Trace不能证明请求未发生。 | 可观测性完整原理、面试专题 |
| Trace断链怎么排查 | 先确定最后一个有Span的服务和第一个缺失的调用边,再逐层查Gateway入口、Header是否被代理清洗、Feign/HTTP/gRPC/Dubbo是否注入上下文、线程池和Reactor是否传播并清理Context、MQ消息属性是否带Trace、SDK队列和Collector是否丢弃、后端查询条件是否正确。 | Trace断链深度排查、可观测性面试题 |
| Trace平台没有数据能证明请求没发生吗 | 不能。没有Trace可能是未采样、上下文没传播、SDK没导出、Collector丢弃、Tail Sampling没保留、后端写入失败或查错环境。请求是否发生要用Gateway日志、应用日志、Metrics、数据库状态机、幂等表、消息表和审计日志交叉证明。 | 采样决策链、ID边界 |
| 多机房故障切换为什么必须先Fencing | 网络分区时旧主可能仍服务本地客户端,只提升备站会让两边同时写。应先在网络、存储、数据库权限或Epoch校验上隔离旧主,记录复制位点和缺口,再提升新主并逐步切流。 | 多活完整原理、面试专题 |
| 微服务接口怎样保证兼容发布 | 把OpenAPI、Proto和事件Schema版本化,明确旧/新Reader与Writer组合;使用Breaking Diff、Consumer Contract和真实序列化测试,数据库与事件字段按Expand–Migrate–Contract迁移,确认旧实例、历史消息和灾备版本退出后才删除。 | 契约治理完整原理、面试专题 |
| API删除字段前怎么确认安全 | 不能靠口头确认。要结合网关日志、Consumer Contract、SDK版本上报、字段级埋点、代码依赖扫描和MQ消费组清单,并确认旧实例、旧SDK、历史消息、死信队列、灾备版本和回滚镜像都不再依赖。删除字段必须有门禁和回滚窗口。 | 消费者清单和删除门禁、破坏性变更分类 |
| 微服务灰度发布完整链路怎么设计 | 发布前先保证API、数据库和MQ事件兼容;Gateway基于可信身份生成灰度标签,Feign或RPC Filter透传标签,LoadBalancer按注册中心metadata过滤版本、区域和权重,底层HTTP/RPC客户端直连目标实例。灰度期间按版本观察QPS、错误率、P95/P99、业务成功率、重试和资源池,越过门禁先切流再处理数据、消息、缓存和外部副作用。 | 发布策略完整原理、发布面试专题 |
| Gateway 在微服务里负责什么 | Gateway 是统一入口,负责路由、认证、粗粒度授权、限流、灰度、Header清洗、Trace和审计。它不能替代业务服务授权、事务和状态机;数据权限、租户权限、资源归属必须在服务层基于事实源校验。 | 网关治理完整原理、网关治理面试题 |
| OAuth2/OIDC 在微服务里怎么落地 | 认证授权中心负责登录和签发Token;Gateway校验JWT签名、过期、issuer、audience和scope,清洗外部身份Header,再透传Token或受控上下文;下游服务作为Resource Server再次校验,并在Service层做方法权限、租户权限和数据权限。 | 统一认证和OAuth2 |
| 分布式会话怎么设计 | 单机Session放JVM内存,多实例后请求打到其他实例会丢登录态。常见方案有粘性会话、Session复制、Redis Session、JWT和Opaque Token。Redis Session服务端可撤销但依赖Redis;JWT横向扩展好但撤销、权限变更、泄露和密钥轮换需要短Token、黑名单、tokenVersion或权限版本。 | 分布式会话完整原理、分布式会话面试题 |
| JWT 为什么不是完全无状态 | JWT减少了中心化Session读取,但登出、改密码、权限收回、Token泄露和密钥轮换都需要服务端状态或版本,例如黑名单、短Access Token、Refresh Token、tokenVersion、权限版本和JWK轮换。 | JWT不是完全无状态 |
| 用户串号怎么排查 | 优先查ThreadLocal、MDC、SecurityContextHolder是否在finally清理;再查异步任务是否复用上下文,Gateway是否清洗外部用户Header,本地缓存Key是否缺少userId或tenantId,是否用静态变量保存用户。 | 用户串号Runbook |
| Gateway 503 和 504 怎么排查 | 503优先查lb://服务名、注册中心实例、namespace/group、健康状态、灰度metadata、LB候选和熔断;504查Gateway超时、下游P99、连接池等待、线程池、慢SQL、锁、GC和重试放大。写请求504不能直接重放,要按幂等号查事实。 | 网关错误语义、网关Runbook |
| 怎么保证本地服务列表最新,调到旧服务怎么办 | 本地列表无法保证任意瞬间绝对最新,只能通过订阅推送、定期刷新、Readiness摘流、优雅停机、健康过滤、连接池回收、短超时和有限重试缩短传播窗口。调到旧服务时先查Trace目标地址和版本,再查注册中心事实、本地快照、LB候选、连接池和灰度标签;写请求不能盲目重放,要按幂等号查询事实后补偿。 | 服务发现新鲜度、旧实例Runbook、发布窗口 |
| 怎么保证每次请求都是最新可用的 | 严格不能保证每次请求拿到全局最新且绝对可用实例,因为注册传播、客户端快照、LB缓存、连接池和在途请求都有窗口。工程上保证当前视角下尽量可用:读本地最新快照,过滤健康、权重、版本、机房和灰度,连接失败或读请求超时在Deadline内有限换实例;写请求必须用幂等号查事实后补偿。 | 每次请求尽量可用、Spring Cloud请求级闭环 |
| P2C为什么要结合Active和EWMA | 只看Active会选到历史很慢但当前空闲的实例,只看EWMA会忽略当前已经排队的实例。P2C随机抽两个候选,用Active、EWMA、权重和错误状态算综合分数,可以低成本避开慢实例和排队实例。但这些统计通常是客户端局部视图,还要配合熔断、Outlier和探测恢复。 | P2C与EWMA Demo、负载均衡面试题 |
| 配置中心为什么是控制面 | 配置中心负责保存、审批、发布、通知和审计;业务请求应读取本地最后成功配置快照,不能每次请求同步查配置中心。否则控制面抖动会直接拖垮数据面,配置中心也会被业务QPS打爆。 | 配置治理完整原理、配置治理面试题 |
| 配置发布成功是否代表全实例生效 | 不代表。发布成功通常只说明配置中心保存了新版本;客户端通知、拉取、校验、Environment更新、Bean刷新和资源切换都有传播窗口。生产要按实例观察配置版本、刷新结果、更新时间、错误率、P99和业务指标。 | 配置发布灰度 |
| 哪些配置不能随便动态刷新 | 数据源、MQ消费组、线程池结构、证书密钥、分片规则等资源型或状态型配置不能简单改字段。需要构建新资源、健康验证、原子切换、排空旧资源和失败回滚;否则可能造成事务中断、重复消费、连接泄漏或状态不一致。 | 动态刷新边界、资源切换 |
| REST、Dubbo、gRPC和MQ怎样选 | 先判断是否立即需要结果和是否要持久堆积;外部API偏REST,成熟Java体系可用Dubbo,多语言强IDL/流式偏gRPC,异步削峰和最终一致用MQ。再明确Gateway、客户端、Kubernetes和Mesh的能力Owner,避免多层重试和双层负载。 | 组件选型、面试专题 |
| 分布式系统为什么比单体复杂 | 单体里很多问题是本地方法和本地事务,拆分后变成跨网络、跨服务、跨数据库。远程调用可能成功、失败、超时或重复;调用方看到超时并不知道下游是否执行成功,所以必须设计超时、查询确认、重试、幂等、补偿和对账。 | 从零到生产级掌握 |
| 微服务边界怎样划分 | 不按表名一表一服务,而是按业务能力、限界上下文、状态机、数据事实源和团队Owner划分。拆分前要验证调用频率、事务范围、容量差异、发布价值和故障隔离收益;边界不稳定时先做模块化单体。 | 限界上下文识别、服务粒度 |
| 共享数据库怎样迁移到微服务 | 先盘点服务账号和SQL,指定每张业务表唯一写入Owner;其他服务改为API、事件、CDC或查询模型读取副本;灰度切读并对账,最后才物理拆库和收口权限。不要直接复制表双写。 | 共享数据库迁移 |
| 远程调用为什么必须设置超时 | 如果不设置超时,上游线程会一直等待下游响应,连接池、线程池会被拖满,最终把故障从一个服务扩散到整个链路。超时是隔离故障的基础,但超时不等于失败,后续还要查询确认和幂等处理。 | 分布式系统基础 |
| 超时后能不能直接重试 | 不能盲目重试。超时只说明调用方没收到结果,下游可能没执行,也可能已经执行成功但响应丢了。重试前要保证下游接口幂等,并尽量支持按业务流水查询真实状态;重试还要有次数、退避和熔断,避免放大故障。 | 从零到生产级掌握、幂等设计 |
| 幂等是什么 | 幂等是同一业务意图重复执行时只产生一次业务效果,并能返回第一次相容结果。它不阻止重复到达,而是通过稳定业务键、请求摘要、唯一约束、状态机、事务和结果记录让重试安全。 | 幂等定义、幂等状态模型 |
| 为什么先查幂等记录再执行业务不安全 | 两个并发请求可能都在对方插入前查到“不存在”,然后同时执行副作用;最后唯一键冲突发生得太晚。应先通过唯一约束或原子操作抢占处理权,再执行业务,并根据 owner_token 判断谁是首次处理者。 | 先查后写竞态、原子抢占 |
| 幂等键怎样设计 | 幂等键应在一次业务意图开始时生成并跨重试保持不变,通常包含租户/用户作用域、操作类型、稳定业务号和协议版本。traceId 只标识一次调用尝试,不能直接替代幂等键;同键还要保存请求摘要,防止参数不同却复用旧结果。 | 幂等键设计、请求摘要 |
| 幂等记录卡在 PROCESSING 怎么办 | 不能看到租约过期就直接重做,因为业务可能已经提交,只是成功状态没写回。应使用 owner_token 和 lease 标记处理者,租约过期后先查订单、支付流水等事实源,再补记成功、原子抢占重试或转人工。 | 独立抢占与租约、生产排查 |
| MQ 消费怎样保证幂等 | 使用稳定业务事件 ID,并包含消费者组/处理器作用域;若消费日志与业务表同库,将原子去重、业务写入和成功状态放在一个本地事务,提交后再 ACK/提交 Offset。只使用 Broker messageId 或 Kafka 生产者幂等不能保证 MySQL、HTTP、短信等外部副作用端到端一次。 | MQ消费幂等、消费事务边界 |
| Redis SETNX 能否保证关键业务永久幂等 | 不能。SETNX 适合短时防抖和降低并发,但 TTL、故障转移、数据淘汰以及业务提交与 Redis 状态之间的窗口都可能让重复再次进入。关键业务仍需要数据库唯一约束、状态机、结果复用和事实源恢复。 | Redis SETNX边界、分布式锁不等于幂等 |
| 注册中心做什么 | 注册中心属于控制面,保存并推送接口地址或应用实例、元数据引用和治理信息,不转发RPC。Consumer把通知对账成本地Invoker快照,再经Router和LoadBalance直连Provider。 | 控制面与数据面、接口级与应用级发现 |
| Dubbo注册中心挂了服务还能调用吗 | 已运行Consumer若有内存Invoker快照且Provider数据面可达,可能继续调用;新进程启动、Provider注册、上下线感知、元数据和动态规则会受影响。答案必须区分启动/运行期、接口级/应用级发现和本地Directory缓存。 | 注册故障矩阵、本地缓存边界 |
| Dubbo一次调用完整链路是什么 | Consumer接口代理把方法转成Invocation并进入Cluster;Directory列出本地Invoker,Router过滤,LoadBalance选址,Filter后由Protocol/ExchangeClient发送。Provider解码和线程派发后按serviceKey找到Exporter,经过Filter调用真实实现;响应携带requestId返回并完成Consumer对应Future。 | Dubbo完整调用链、Provider接收链、响应链 |
| Dubbo的Invoker、Directory、Router、LoadBalance、Cluster分别做什么 | Invoker统一表示可调用对象;Directory维护动态Invoker快照;Router过滤本次允许的候选;LoadBalance为一次尝试选一个;Cluster决定失败后是否重试、并行或快速失败,并把多Invoker包装成一个调用入口。 | Dubbo核心对象、治理层次区别 |
| Dubbo 2和3服务发现有什么区别 | Dubbo 2.x常见按接口注册完整Provider URL;Dubbo 3主线按应用实例发现,并通过接口到应用映射和元数据恢复服务能力,减少注册数据冗余。迁移期可能双注册和双订阅。 | Dubbo发现模型、迁移模型 |
Dubbo retries=2会调用几次 | Failover中通常是首次尝试失败后再重试2次,因此最多3次物理尝试;多层重试还会乘法放大流量。写请求超时状态未知,不能靠重试保证可靠。 | 逻辑调用与物理尝试、重试放大 |
| Dubbo怎样做端到端超时 | 从入口SLO建立Deadline,把时间分给本地处理、RPC和数据库;每次重试消耗同一剩余预算并退避。每一层都设置完整入口timeout会让总时长叠加并拖垮线程池。 | 端到端超时预算、重试预算 |
| Dubbo请求ID和Future怎么工作 | 同一长连接可以并发发送多个请求,响应可能乱序。Consumer按requestId保存待响应Future,解码Response后按ID完成对应Future;正常、超时、写失败和连接关闭都要清理映射。Consumer超时通常不会取消Provider业务。 | RequestId与Future、超时竞态 |
| Dubbo SPI和自适应扩展解决什么 | Dubbo SPI不是简单反射,而是按扩展接口加载name -> class、缓存实例、依赖注入、Wrapper包装,并通过自适应扩展根据URL参数选择具体实现。这样协议、序列化、负载均衡、Filter、Router和Cluster才能可插拔;自定义扩展要关注资源路径、激活条件、顺序、开关、监控和回滚。 | Dubbo SPI扩展点、自适应扩展、扩展排查 |
| Dubbo慢方法拖垮Provider怎么治理 | 先区分Consumer侧actives、Provider方法级executes、Provider线程池threads/queues和连接数限制。慢导出、批处理、外部接口不能和核心短查询无限共享同一执行资源;应按方法看active、P99、queue、reject和线程栈,做方法级限并发、资源隔离、快速拒绝、异步化或拆服务。 | 方法级治理、线程池满证据链 |
| CAP 怎么理解 | CAP 不是简单三选二。分布式系统必须考虑网络分区 P;当分区发生时,只能在一致性 C 和可用性 A 之间取舍。ZooKeeper 更偏 CP,少数派不可写以保证一致性;Eureka 更偏 AP,允许注册信息短暂不一致以保证可用。 | CAP与BASE、从零到生产级掌握 |
| CAP 里的 P 是分库分表吗 | 不是。P 指网络分区,也就是节点之间因为网络、路由、防火墙、机房故障等原因互相不可达。只要系统跨机器通信,就必须面对 P;分区发生时才需要在 C 和 A 之间取舍。 | CAP与BASE |
| CAP 为什么不是简单三选二 | 因为分布式系统里 P 不是可选项,而是必须面对的现实。没有分区时系统还会在延迟和一致性之间权衡;真正发生分区时,才是在继续响应但可能不一致,和拒绝部分请求保护一致性之间选择。 | CAP与BASE |
| CP 和 AP 怎么选 | 资金、权限、核心库存这类错误成本高的场景更偏 CP,不能确认最新状态就拒绝;搜索、缓存、通知、报表这类可补偿场景更偏 AP 或最终一致,先可用再通过消息、补偿、对账修正。 | CAP与BASE |
| BASE 是什么 | BASE 是对强一致的一种工程化折中,包括基本可用、软状态和最终一致。它不是不保证一致,而是允许短暂中间状态,通过重试、补偿、死信、对账和告警最终修正到正确状态。 | CAP与BASE、数据一致性 |
| 最终一致是不是可以不管 | 不是。最终一致必须有完整闭环:本地事务写事实源,记录事件或消息,可靠投递,下游幂等消费,失败重试,超过阈值进死信或异常表,再通过补偿、对账和告警处理。少任何一环都可能永久不一致。 | CAP与BASE、数据一致性 |
| CDC 和 Outbox 分别解决什么 | Outbox 是业务本地事务里同时写业务表和事件表,保证业务事实存在时事件意图也存在;CDC 是从数据库日志捕获已提交变化,把事件可靠搬运到 MQ、ES、Redis 或其他视图。两者解决可靠最终一致,不是跨系统强一致,消费者仍要幂等、版本判断和补偿。 | CDC与Outbox完整原理、CDC面试题 |
| MySQL 更新成功但 ES 更新失败怎么办 | MySQL 是事实源,ES 是可重建搜索视图。写事务提交并写 Outbox,CDC/MQ 异步同步 ES;ES 失败要重试、退避、死信,旧事件按版本忽略,长期不一致按 MySQL 事实源重放或重建。排查看 MySQL版本、Outbox、CDC位点、MQ offset、消费日志、死信和 ES 文档版本。 | MySQL到ES同步、ES失败Runbook |
| 为什么事件里要有 eventId 和 version | eventId 用于消费者去重,防止至少一次投递导致重复处理;version 用于处理乱序,防止旧事件晚到覆盖新状态。没有这两个字段,重试、Rebalance、CDC恢复、历史重放都可能制造脏数据。 | 事件模型、版本幂等Demo |
| 读己之写是什么意思 | 读己之写是用户自己写入后,自己后续读取必须能看到新值。常见做法是写入后本人短时间读主库,或读请求携带版本号;其他用户可以继续读缓存,降低全局强一致成本。 | CAP与BASE |
| 为什么订单状态要用状态机 | 状态机限制数据只能按合法路径流转,防止重复回调、乱序消息、补偿任务把状态改乱。比如支付成功 SQL 必须带 status = 'WAIT_PAY' 条件,更新不到数据就幂等返回或查询确认。 | CAP与BASE、数据一致性 |
| 强一致和最终一致怎么选 | 资金、余额、库存最终确认这类高风险数据更偏强一致;通知、积分、搜索索引、报表、缓存这类可补偿数据更适合最终一致。选型先看业务风险、用户体验、失败补偿能力和对账能力,而不是直接套框架。 | 数据一致性、分布式事务选型 |
| Paxos、Raft、ZAB 解决什么问题 | 它们让多个非拜占庭节点在宕机、网络分区、消息延迟和乱序下对日志顺序安全达成一致。多数派保证 Quorum 相交;Raft 使用 Term、选主和日志复制;Paxos 使用 Prepare/Promise 与 Accept;ZAB 为 ZooKeeper 提供恢复同步和原子广播。它们不自动解决业务幂等和跨服务事务。 | 共识算法全过程、ZooKeeper ZAB |
| ZooKeeper ZAB恢复中的DIFF、TRUNC、SNAP是什么 | 新Leader与Follower同步安全历史时,Follower只缺后缀可用DIFF补齐;保留冲突或不再安全尾部要TRUNC截断;落后太多或日志不足则SNAP同步数据树。同步完成并确认新epoch后才进入正常广播。 | ZAB恢复全过程、DIFF/TRUNC/SNAP |
| ZooKeeper断连后临时节点会立刻删除吗 | 不会。临时节点属于Session而不是TCP连接;客户端可在协商Timeout内连接其他Server恢复原Session。只有服务端确认Session过期或客户端正常关闭后才清理,Expired后旧Session不可恢复。 | Session断连与过期、过期语义 |
| ZooKeeper Watch能保证每次事件都不丢吗 | 标准Watch是一次性状态变化提示,不是持久事件日志。触发后应重新读取完整状态并重新注册;断连和快速变化下不应依赖每个中间事件。3.6持久Watch也不能取消离线后的快照重建。 | Watch语义、重注册窗口、持久Watch |
| ZooKeeper的version、cversion、aversion有什么区别 | version对应节点数据,cversion对应直接子节点集合,aversion对应ACL;更新数据、管理children和修改ACL应使用各自版本做CAS。BadVersion是明确冲突,应重读合并,不能改成无条件覆盖。 | Stat与三类版本、CAS |
ZooKeeper multi是不是分布式事务 | multi只把同一ZooKeeper集群内多个znode操作作为一个ZAB事务原子提交,不能包含MySQL、Redis或MQ。响应ConnectionLoss时是否提交仍可能未知,需要按节点数据、version和业务ID恢复。 | multi边界、结果未知 |
ruok=imok为什么不代表ZooKeeper健康 | 它只证明命令端口有响应,不证明有Leader和Quorum、磁盘可fsync、Follower已追平、Session稳定或业务路径可读写。健康检查要从进程、节点、集群、数据、客户端验证到业务。 | 分层健康模型、四字命令 |
| etcd的Raft index、revision和Key version有什么区别 | Raft index属于共识日志;revision是MVCC键空间修改事务的全局版本,一次Txn改多个Key可共享revision;Key version是当前Key生命周期修改次数,删除重建后重新计数。 | Raft与MVCC、Key元数据 |
| etcd线性一致读和Serializable读区别 | 默认Range执行线性一致读,需要确认Leader领导权并等状态机到安全位置;Serializable可从本地已提交状态读,延迟低但可能陈旧,不应做锁和Leader裁决。 | 线性一致读、Serializable读 |
| etcd Watch被Compaction后怎么办 | List先取得完整Prefix快照和revision R,再从R+1 Watch;若恢复revision已被压缩,停止旧revision重连,重新List并原子替换本地快照。 | List-Watch、Compaction恢复 |
| etcd Compaction和Defrag区别 | Compaction让旧MVCC历史不再可读,物理DB文件不一定缩小;Defrag重建Backend空闲页回收空间,应逐Member执行并观察集群健康。 | Compaction、Defrag |
| etcd Lease能保证服务健康吗 | Lease+KeepAlive只证明注册客户端近期能与etcd续租,不证明业务端口、线程池和数据库健康;服务发现还要readiness、主动探测、超时和熔断。 | Lease、服务发现 |
| etcd锁为什么仍需要Fencing Token | Lease过期后旧客户端可能恢复继续写,新持有者已经取得更大create revision;外部资源必须原子拒绝旧Token,同Token重放再由幂等键处理。 | etcd锁、Fencing |
| Consul的Gossip和Raft分别做什么 | LAN/WAN Gossip用Serf/SWIM类机制传播成员和故障怀疑,允许短暂不一致;单DC Server Raft多数派提交Catalog、KV、ACL和Session。consul members全Alive不证明Raft有Leader。 | Gossip与Raft、Raft |
| Consul服务注册到发现怎么走 | Provider向本地Agent注册Service和Check,Agent同步到Server,Leader经Raft提交Catalog;Consumer通过DNS或Health API获取健康实例,Blocking Query用Index等待变化并更新本地快照。 | 注册流程、Blocking Query |
| Consul Catalog有实例为什么仍发现不到 | Catalog只表示注册,Health查询可能因Check Critical、passing=true、Tag、Meta、DC或Prepared Query过滤;DNS还受Agent、递归DNS、OS/JVM和连接池缓存。 | Catalog与Health、发现Runbook |
| Consul TTL Check和Session TTL区别 | TTL Check由应用定期上报以改变健康状态;Session把Node、Checks、TTL和KV所有权组合,用于锁或选主,失效后按release/delete处理。 | TTL Check、Session |
| Consul Session锁为什么还要Fencing | Session失效和Lock Delay不能阻止暂停旧进程恢复写数据库;外部资源必须原子比较同一锁Key的LockIndex等单调Token,同Token重试还需业务幂等。 | Lock Delay、Fencing |
| Consul多数据中心是不是一个Raft集群 | 不是。每个DC有独立Server Raft和Catalog,通过传统WAN Federation或较新Peering互联;本地DC可独立运行,跨DC查询和数据面受WAN分区影响。 | 多数据中心 |
| Consul Connect解决什么 | Connect用服务身份、CA证书、sidecar/Envoy、mTLS和Intentions实现Service Mesh;它不替代业务授权、幂等和总超时预算。 | Consul Connect、Mesh边界 |
| 为什么多数派能避免两个分区同时提交 | N 个节点的多数派是 floor(N/2)+1,任意两个严格多数集合必有交集。5 节点分为 3 和 2 时,只有 3 节点分区能形成 Quorum;少数派旧 Leader 即使仍存活也不能推进提交。交集还必须配合任期、日志新旧和持久化规则才能保证安全。 | 多数派与Quorum、网络分区与脑裂 |
| Raft 日志什么时候算提交 | Leader 本地追加不等于提交。它要复制给多数投票节点并满足 Raft 提交规则,才能推进 commitIndex、应用状态机并回复客户端。Leader 通常只通过多数计数直接提交当前任期条目;当前任期条目提交后,之前日志前缀也被确定。 | Raft提交规则 |
| 为什么 Follower 不能随便提供强一致读 | Follower 可能落后,直接本地读会返回旧值;Leader 也可能失去多数派但尚未发现。线性一致读通常需要 Leader 确认领导权并确保状态机应用到安全位置,例如 ReadIndex/多数确认,或者在明确假设下使用租约读。 | Raft读一致性 |
| 分布式事务是什么 | 分布式事务解决一次业务操作跨多个服务、多个数据库、多个资源时如何保证结果正确。它不是只有强一致,也不是等于 Seata,而是一类方案,包括 XA/JTA/2PC、TCC、Saga、本地消息表、事务消息、Seata 和最大努力通知。 | 分布式事务总览 |
| 分布式事务协调器为什么必须持久化状态 | 协调器可能在只通知部分参与者后宕机,重启后必须知道全局事务、各分支和最终提交/回滚决议,才能继续重发。已经形成的Commit决议不能因为内存丢失而改成Rollback,所以全局ID、分支状态、决议、重试和错误都要持久化。 | 协调器状态机、失败窗口 |
| 分布式事务怎么选 | 先判断能不能避免跨服务事务,能合并边界就不要拆。必须跨服务时,短事务强一致可考虑 XA/JTA/2PC 或 Seata XA/AT;资源预留适合 TCC;长流程适合 Saga;订单后置通知、积分、ES 同步适合本地消息表或事务消息。无论哪种都要配套幂等、重试、补偿、对账和告警。 | 商业场景训练营、从零到生产级掌握、分布式事务选型 |
| 选分布式事务方案先看什么 | 先看事实源、可逆性、资源能否预留、用户能否接受延迟。能本地事务就不要跨服务;能最终一致就不要强行强一致;能通过状态机和消息补偿解决,就不要拉长全局事务。 | 分布式事务选型 |
| JTA 是不是分布式事务 | 严格说JTA不是分布式事务协议本身,而是Java应用使用事务管理器的API;2PC是先Prepare再统一决议的协议思想;XA定义事务管理器和资源管理器之间的start、end、prepare、commit、rollback、recover等接口。具体TM负责Xid、资源登记、日志和恢复。 | XA、JTA与2PC概念地图、资源加入事务 |
| XA事务的in-doubt是什么 | 参与者已经Prepare并持久化恢复信息,但暂时联系不到协调器,不知道最终应该Commit还是Rollback。它不能自行随意决策,相关锁和事务上下文可能继续保留,直到协调器按日志恢复并重发最终决议或管理员依据可靠证据处理。 | XA与in-doubt |
| XA事务管理器重启后怎么恢复 | TM读取持久化协调日志,为稳定资源重新获得XAResource,调用recover扫描资源中的Prepared Xid,与日志中的分支和最终决议对齐;已有Commit决议就重发Commit,已有Rollback决议就重发Rollback,完成后再清理日志。 | XA恢复扫描、事务管理器日志 |
| XA启发式结果是什么 | 资源没有遵循全局决议而自行提交或回滚,可能形成Heuristic Commit、Rollback、Mixed或Hazard。这意味着自动原子性已被破坏,必须保留Xid和日志、逐资源对账并执行业务补偿,不能简单forget或删除记录。 | Heuristic Outcome |
| 为什么 XA 性能低 | XA/2PC要让多个资源先Prepare并持久化可恢复状态,保留锁或事务上下文,再等待协调器统一Commit/Rollback;还增加多轮网络、TM日志和恢复扫描。参与方慢、网络分区或协调器异常都会拉长资源占用。 | 两阶段提交全过程、容量成本 |
| TCC 是什么 | TCC是业务层资源预留协议。Try把库存、余额或券从可用转为冻结;全局Commit后Confirm消费冻结;全局Rollback后Cancel释放冻结。协调器持久化最终决议并重复调用二阶段,参与者通过事务栅栏和条件SQL保证幂等。 | TCC定义与资源模型、资源模型 |
| TCC为什么不能先查记录再冻结 | 两个并发Try可能都查询到分支不存在并一起冻结,唯一键冲突发生在副作用之后。应先用唯一约束原子建立栅栏所有权,再把资源冻结和栅栏状态推进放进同一本地事务。 | 先查后写竞态、Try全过程 |
| TCC为什么要处理空回滚和悬挂 | Cancel在没有Try记录时也要插入CANCELED空回滚屏障;迟到Try插入同一唯一分支时冲突,读取到CANCELED后拒绝冻结。否则Cancel先到但不留记录,随后Try仍可成功,留下永远不会Confirm或Cancel的悬挂资源。 | 空回滚、悬挂、Try与Cancel竞态 |
| TCC冻结超时后能直接释放吗 | 不能只按本地时间释放,协调器可能已经形成Commit决议,只是Confirm延迟。扫描任务应先查询全局最终状态:Commit补Confirm,Rollback补Cancel,未知则核对协调日志和业务事实并进入待确认或人工状态。 | 冻结超时恢复 |
| Saga 是什么 | Saga把长事务拆成多个快速提交的本地事务,每步持久化结果;后续失败时,对已完成的可补偿步骤按依赖关系执行幂等业务补偿。它不长期持锁,适合履约、审批、物流,但会暴露中间状态并要求状态机、重试、对账和人工接管。 | Saga定义与状态机、Saga状态模型 |
| Saga编排式和协同式怎么选 | 编排式由中央状态机发送命令、保存步骤和安排补偿,复杂分支、并行和排查更清晰,但编排器需高可用;协同式由服务消费事件并发布下一事件,自治性强,但流程分散、事件环路和补偿顺序更难治理。 | 编排式Saga、协同式Saga、两者对比 |
| Saga补偿为什么不是数据库回滚 | 正向步骤已经本地提交,补偿是新的业务动作。退款会新增退款流水,原支付仍存在;取消物流可能因已揽收而失败。补偿必须依据当前事实、幂等执行,并允许失败后重试或人工处理,不能简单覆盖旧字段值。 | 补偿与物理回滚区别、补偿失败 |
| Saga步骤超时后能直接补偿吗 | 不能。参与者本地事务可能已经提交,只是响应丢失。编排器要使用同一stepId查询或重试,参与者通过幂等流水复用第一次结果;只有确认正向事实和全局决议后,才进入补偿。 | 步骤提交与记录窗口、步骤契约 |
| Saga 和 TCC 怎么区别 | TCC先Try冻结资源,再Confirm/Cancel,适合库存、余额、券等自然预留资源;Saga每一步先本地提交,失败后做业务补偿,适合履约、审批、物流长流程。TCC以冻结换更强业务隔离,Saga以显式中间状态换长流程可用性。 | TCC与XA、Saga对比、Saga隔离问题 |
| 本地消息表/Outbox解决什么 | Outbox把业务数据和待发事件写入同一个数据库本地事务,保证业务提交时一定留下可恢复事件意图,关闭“数据库成功但消息未记录”的双写窗口;投递器或CDC随后发送,发送确认未知时允许重复,所以消费者仍要幂等。 | Outbox原理、双写问题 |
| Outbox为什么仍会重复消息 | Broker持久化消息后,投递器可能在把Outbox标SENT前宕机;恢复扫描会再次发送。同理消费者业务提交后ACK丢失也会重投。至少一次系统选择重复而不是静默丢失,业务用稳定eventId和原子消费日志吸收重复。 | 发送确认不确定窗口、消费者全过程 |
| 多个Outbox投递器如何避免同时发送同一行 | 通过数据库锁定领取,或用状态、ownerToken、leaseUntil进行条件更新;影响行数为1才获得发送权。领取在短事务中完成,提交后再调用MQ,不能持数据库行锁等待网络发送。租约过期允许接管但仍可能重复,因此消费者幂等不可省。 | 投递抢占、租约恢复 |
| CDC Outbox和轮询Outbox怎么选 | 轮询实现直观但有扫描延迟、索引和抢占成本;CDC读取数据库提交日志,减少轮询且延迟低,但要运维Connector位点、Schema演进和重复恢复。两者都只是事件搬运方式,都不能取消消费者幂等。 | CDC Outbox、方案对比 |
| 消费日志怎么和业务保持一致 | 消费日志和业务表同库时,在一个本地事务中先用consumerGroup + eventId唯一键原子占位,校验事件版本,更新业务并标SUCCESS,提交后再ACK。业务提交后ACK丢失时,重投消息命中成功记录并重新ACK。 | 消费者流程、消费日志表、先查后写竞态 |
| 消费者调用短信或HTTP怎么保证不重复 | 外部副作用不能与消费日志普通本地事务原子提交。优先让下游支持eventId幂等和结果查询,或在消费事务中再写Command Outbox由独立投递器调用;高风险操作使用稳定业务流水和对账。不能在外部调用前先标消费成功。 | 外部副作用边界 |
| 本地消息表和 MQ 事务消息怎么选 | Outbox依赖数据库表和轮询/CDC,状态可见、便于补偿;MQ事务消息通过半消息、本地事务和Broker回查协调消息可见性,但依赖具体产品。两者都只解决生产端双写,消费者仍可能重复并需要幂等。 | 事务消息流程、方案对比 |
| 支付成功后同步积分、短信、ES 怎么设计 | 支付回调先校验签名和金额,本地事务幂等更新订单为已支付,并写 outbox 事件;事务提交后异步投递 MQ,积分、通知、ES 各自幂等消费。失败进入重试、死信、补偿和对账,不要把远程调用都塞进支付回调事务。 | 分布式事务选型 |
| 3PC 为什么很少用 | 3PC 比 2PC 多了 CanCommit、PreCommit、DoCommit,试图降低阻塞,但仍不能彻底解决网络分区下的不确定性,且实现复杂、生态支持少。商业 Java 系统更常用 XA/JTA、TCC、Saga、可靠消息和 Seata。 | 分布式事务选型 |
| Seata里的TC、TM、RM分别是什么 | TC是独立事务协调器,保存全局与分支状态并推动二阶段;TM位于全局事务发起应用,负责Begin、Commit或Rollback;RM位于访问事务资源的应用,注册分支、申请全局锁并执行分支提交或回滚。一个订单服务既可以是TM,也可以在修改订单库时作为RM。 | TC、TM、RM角色、全局事务生命周期 |
| Seata的XID怎么传播 | TM Begin后将XID绑定到RootContext;Feign、Dubbo等拦截器把XID写入受信任请求上下文,下游入口再绑定到执行线程,DataSourceProxy提交时据此注册所属分支。若自定义客户端、异步线程或网关丢失XID,下游只会形成普通本地事务,无法参与全局回滚。 | XID传播全过程 |
| Seata和Spring本地事务是什么关系 | @GlobalTransactional负责开启全局事务、绑定XID并向TC提交全局决议;@Transactional仍负责当前服务当前数据库连接的本地事务;DataSourceProxy在本地提交前生成前后镜像、undo_log、lockKey并注册分支。全局事务协调多个本地事务,不会让未接入RM的远程资源自动回滚,也不能把长外部调用包进本地事务里拖住数据库锁。 | Spring事务边界 |
| Seata AT第一阶段怎么执行 | RM通过DataSourceProxy拦截SQL,查询前镜像,执行真实SQL,再查询后镜像,生成undo_log和lockKey;本地提交前向TC注册分支并申请全局锁,成功后将业务数据和undo_log在同一本地事务提交。 | AT第一阶段 |
| AT为什么需要前镜像和后镜像 | 前镜像用于知道回滚目标;后镜像用于回滚前确认当前数据仍是AT一阶段提交后的值。若当前值与后镜像不一致,说明存在绕过全局锁的写入或人工改数,直接恢复前镜像可能覆盖合法新数据,所以应停止盲目覆盖并核对业务流水。 | 前后镜像与脏数据、AT二阶段回滚 |
| AT全局锁和数据库行锁区别 | 一阶段本地提交后数据库行锁已经释放,TC继续记录lockKey形成逻辑全局写隔离;其他受Seata管理的全局事务注册同一资源时冲突。普通JDBC、手工连接或DBA SQL不会自动检查TC全局锁,因此AT不能约束所有绕过代理的写入。 | lockKey与全局写隔离 |
| AT是否天然提供全局读隔离 | 不能简单这样说。因为一阶段业务数据已经本地提交,普通SELECT可能看到全局事务尚未最终结束的中间值。需要更强锁定读时可评估当前版本支持的SELECT FOR UPDATE全局锁检查路径,但会增加TC交互、等待和热点竞争。 | AT读隔离 |
| Seata AT、XA、TCC、Saga怎么选 | 简单关系库短事务、SQL受支持且热点低可评估AT;资源支持XA且必须原子提交可评估XA;库存、余额、券有自然预留模型适合TCC;履约、审批、物流长流程适合Saga;积分、通知、ES同步通常更适合Outbox或事务消息。 | Seata模式选型、分布式事务选型矩阵 |
| Seata AT回滚失败怎么排查 | 先按业务键定位XID和branchId,确认undo_log存在且可反序列化,再比较前镜像、后镜像和当前数据;一致时查补偿SQL、主键、权限和锁,不一致时定位绕过代理的写入并停止盲目覆盖。任何情况下都不应直接删除undo_log。 | Seata生产排查 |
| 分布式锁能解决什么 | 分布式锁解决多实例之间的互斥,比如热点缓存重建、多实例任务调度、低频资源互斥。但它不能替代数据库事务、幂等和状态机,关键业务必须用唯一约束、业务状态和补偿兜底。 | Redisson分布式锁、Redis红锁 |
| Redis 锁为什么要校验 token 再释放 | 因为锁可能过期后被别人获得,原线程执行完如果直接删除 key,可能误删别人的锁。释放时必须校验 value 是否等于自己加锁时的 token,匹配才删除,通常用 Lua 保证检查和删除原子性。 | Redisson分布式锁、Redis锁扩展点 |
| 为什么ZooKeeper锁仍需要Fencing Token | 长GC可能让旧客户端Session过期,新客户端已获得锁,但旧线程恢复后仍可直接写数据库。外部资源必须原子保存最大Token并拒绝旧Token;只在客户端检查没有用。同Token重复请求还要业务幂等。 | GC双执行窗口、Fencing Token |
| Redlock 是什么 | Redlock 是 Redis 多节点多数派加锁方案,客户端在多个独立 Redis 节点上尝试加锁,获得多数成功且耗时在有效期内才认为加锁成功。它能降低单节点故障风险,但不是强一致共识算法,关键业务仍需幂等、状态机和数据库约束。 | Redis红锁 |
| 限流、熔断、降级区别 | 限流是限制进入系统的请求量,保护自己;熔断是下游持续失败时快速失败,防止故障扩散;降级是非核心能力不可用时返回兜底结果。三者都是稳定性治理手段,但作用阶段不同。 | 分布式限流、从零到生产级掌握 |
| 固定窗口、滑动窗口、令牌桶、漏桶有什么区别 | 固定窗口简单但边界可能放过双倍突发;滑动日志最精确但每个请求都要保存时间戳;滑动计数用小桶在精度和成本间折中;令牌桶按速率补充令牌并由桶容量允许受控突发;漏桶通过有界队列按固定速率流出,适合流量整形。 | 算法选型对比 |
| QPS 不高为什么仍会线程池耗尽 | 稳定状态下并发约等于 QPS 乘以平均耗时。20 QPS、每次 5 秒就约有 100 个在途请求,因此慢查询、导出和第三方调用还要做并发限制、超时和资源隔离,不能只限制每秒请求数。 | 容量、并发与Little定律、并发限制 |
| Redis Lua 限流为什么原子 | Lua 在 Redis 中作为一个整体执行,使读取、判断、递增或扣令牌、设置 TTL 不被其他命令穿插,避免客户端多命令的并发竞态。但它只保证 Redis 侧状态转换原子,不保证后续业务成功,也不能消除主从切换、跨地域和热点 Key 的边界。 | Redis Lua原子限流 |
| 本地限流与分布式限流怎么选 | 本地限流延迟低且不依赖 Redis,但总配额会随实例数和流量分布变化;集中式限流更接近全局额度,却增加网络依赖和热点。生产可采用全局粗预算加本地子配额,限制预取量并准备集中服务故障时的本地保守上限。 | 本地与分布式限流 |
| Redis 限流器挂了应该放行还是拒绝 | 按业务风险决定。查询类可 Fail-open 但切换本地保守上限;验证码、登录、支付更偏 Fail-closed 或待处理。不能无限全放或全拒,应设计极短超时、有界降级、核心链路保留预算、监控和灰度恢复。 | 限流器故障策略 |
| 明明做了限流系统为什么仍然崩 | 可能保护点在昂贵操作之后、令牌桶容量允许过大突发、多实例本地阈值导致总额倍增、重试放大流量,或者真实瓶颈是数据库锁、连接池、热点 Key。要同时看放行速率、in-flight、P99和下游资源,而不能只看配置的 QPS。 | 限流生产排查 |
| Redis 和数据库一致性怎么做 | 常见 Cache Aside 是读缓存,未命中查库并写缓存;写操作先更新数据库,事务提交后删除缓存。删除失败要重试、告警和补偿,缓存设置 TTL 兜底。关键交易状态不能只信缓存,要回数据库事实源。 | 缓存一致性 |
| MySQL 和 ES 一致性怎么做 | MySQL 是事实源,ES 是搜索视图。常见方式是 MQ 或 Binlog CDC 异步同步,写 ES 失败要重试、死信和补偿,严重时按 MySQL 重建索引并用别名切换。不要同步失败后静默丢弃。 | MySQL与ES一致性 |
| 消息堆积怎么排查 | 先看生产 TPS、消费 TPS、总 Lag、最老消息等待时间,再看 Lag 分布。Kafka 看 Partition Lag,RocketMQ 看 MessageQueue Diff,RabbitMQ 看 Ready 和 Unacked。然后判断是整体消费能力不足、下游慢、热点 key、慢消息、顺序阻塞还是重试风暴。 | 消息堆积与背压、Lag分布与定位 |
项目话术
text
在医疗数据采集与资产平台里,分布式能力主要体现在采集任务调度、接口调用、消息异步入库、ES 同步、缓存更新和多实例部署。比如采集任务要有 taskId、sourceId、batchNo 做幂等;医院接口调用要设置超时和 traceId;清洗入库要靠唯一约束防重复;资产变更通过 MQ 同步 ES,失败进入重试和死信;Redis 只做缓存,数据库是事实源;XXL-JOB 多实例调度时任务本身也必须幂等。常见追问
| 追问 | 回答方向 | 跳转 |
|---|---|---|
| 为什么超时不等于失败 | 下游可能已经执行成功,只是响应丢失。 | 远程调用不确定状态 |
| 为什么最终一致也要对账 | 重试和补偿可能长期失败,必须有兜底发现差异。 | 数据一致性 |
| 为什么分布式锁不能替代事务 | 锁只控制并发入口,不保证提交、回滚和补偿。 | Redisson分布式锁 |
| 为什么扩容后仍然慢 | 可能瓶颈在数据库、MQ 分区、热点 key、慢消息、全局锁或下游。 | MQ Lag分布 |
| 分布式事务失败后怎么查 | 查事实源、业务状态机、事务日志、消息日志、补偿任务和对账结果。 | 分布式事务选型 |
面试回答模板
text
分布式系统我会从“网络不可靠、状态分散、一致性有代价”这条主线回答。远程调用必须有超时、重试、幂等、熔断和查询确认;服务治理需要注册发现、负载均衡和健康检查;数据一致性要按业务风险选择强一致或最终一致;分布式事务不是只有 Seata,而是 XA、TCC、Saga、可靠消息、本地消息表等方案的取舍。生产落地还要有日志、指标、链路追踪、补偿、对账和告警,否则出了问题无法闭环。深度验收跳转
如果面试官继续追问“失败了到底怎么闭环”,回到 分布式系统从零到精通验收清单 按阶段复盘:
- 远程调用:超时不等于失败,必须查询确认、幂等和补偿。
- 一致性理论:CAP 不是三选二,BASE 不是不管一致性。
- 幂等状态机:唯一索引、幂等表、状态条件更新、乐观锁。
- 分布式事务:XA/JTA/2PC、TCC、Saga、本地消息表、事务消息、Seata。
- 分布式锁:Redis 锁、Redlock、Fencing Token、ZK 锁和业务兜底。
- 最终一致:Redis/DB、MySQL/ES、MQ 消费和补偿对账。
- 生产排查:超时、消息堆积、重复执行、数据不一致、锁误删。
本章小结
分布式面试不能只背框架名。好的回答要先讲问题本质,再讲方案取舍,最后结合项目说明如何落地和排查。详细原理回到知识点页学习。
