文章目录
一、总体系
- 三者之间的关系
- 整体分层视角
二、分布式:解决“扩展性”问题
- 简要说明
- 学习重点 & 面试点
三、高性能:解决“吞吐量/延迟”问题
- 简要说明
- 学习重点 & 面试点
四、高可用:解决“故障容错”问题
- 简要说明
- 学习重点 & 面试点
五、补充
- 消息队列
- 概览
- MQ 整体知识体系模块
- 学习重点
- MQ 高频面试点
- 学习顺序
最近在学 分布式、高性能、高可用这块内容,知识点比较多,特此简单梳理一下 相关知识体系、学习重点、常见面试点等。
一、总体系
“分布式、高性能、高可用”可以理解成后端架构能力的三根主线,他们不是三个独立模块,而是一套围绕规模与故障设计的系统体系,也是一套系统从“能拆开跑、跑得快、坏了还能跑”三个角度建立起来的能力体系:
分布式解决“单机装不下、扛不住”;高性能解决“处理得够不够快”;高可用解决“出故障还能不能服务”。
三者之间的关系
| 方向 | 核心问题 | 学习重点/常见手段 | 常见面试点 |
|---|---|---|---|
| 分布式 | 单机不够用,如何拆成多个节点协同 | 服务拆分、RPC、注册发现、负载均衡、分布式事务、一致性、幂等、CAP | CAP、BASE、分布式锁、分布式ID、接口幂等、最终一致性、服务治理 |
| 高性能 | 如何承载更高 QPS、更低延迟 | 缓存、异步化、批处理、连接池、索引优化、限流、读写分离、分库分表、消息队列 | Redis 缓存、SQL 优化、线程池、MQ 削峰、慢接口排查 |
| 高可用 | 系统部分故障时如何继续服务 | 多副本、故障转移、熔断降级、超时重试、限流、幂等设计、容灾、监控告警 | 熔断降级、重试风暴、服务雪崩、主从切换、RTO/RPO、故障转移 |
分布式(基础能力)
/ \
高性能 高可用
(通过并发/缓存/异步 (通过冗余/容错/监控
提升处理能力) 保证系统稳定)
- 分布式是"骨架"——先把系统拆开、能横向扩容
- 高性能是"肌肉"——在拆开的基础上让每个节点跑得更快
- 高可用是"免疫系统"——保证任何一个节点挂了整体不受影响。
三者互相支撑,不能孤立设计。
它们也存在冲突:
- 副本越多,可用性越高,但数据同步成本越高
- 强一致性越强,通常延迟越高、可用性越受影响
- 重试可以提高成功率,但可能放大流量并造成雪崩
- 缓存提高性能,但会产生缓存一致性问题
- 微服务方便独立扩容,却增加网络调用和运维复杂度
所以体系设计不是“技术堆得越多越好”,而是根据业务指标做取舍。
整体分层视角
一个典型的高性能高可用系统,可以按请求链路自上而下拆解:
客户端
↓
DNS / CDN
↓
负载均衡(LVS/Nginx)
↓
网关层API Gateway
├─ 鉴权
├─ 限流
└─ 路由
↓
应用服务层
↓
无状态服务集群
├─ 缓存层:本地缓存 / Redis
├─ 消息队列 → 异步消费者
└─ 数据库集群
├─ 主从复制
├─ 读写分离
└─ 分库分表
↓
监控、日志、链路追踪、告警
每一层都要同时考虑三个维度:分布式(横向扩展能力)、高性能(单位时间处理量)、高可用(故障时依然可用)。
外围还要配套:
- 容器编排和自动扩缩容
- 配置中心、服务发现
- CI/CD、灰度发布和回滚
- SLI/SLO、容量规划
- 故障演练和灾难恢复
最终衡量它是否成立,不看用了多少中间件,而看能否回答这些问题:
- 峰值能承受多少 QPS?
- P99 延迟是多少?
- 单个实例、数据库或机房故障会怎样?
- 数据最多允许丢失多少,即 RPO?
- 故障后多久恢复,即 RTO?
- 系统过载时优先保住哪些核心功能?
这几个问题有明确答案,才算真正形成了分布式、高性能、高可用体系。
二、分布式:解决“扩展性”问题
分布式的重点是“多个服务、多个节点、多个数据副本之间如何协作”。
简要说明
核心思路:拆分 + 协同
- 服务拆分
- 垂直拆分:按业务模块拆(订单、用户、商品各自独立服务)
- 水平拆分:同一服务多实例部署,通过负载均衡分流
- 数据拆分
- 分库分表(水平分片按 ID/哈希,垂直分表按业务字段)
- 常用中间件:ShardingSphere、MyCAT
- 分布式协同问题
- 服务发现与注册:Nacos、Eureka、Zookeeper
- 分布式事务:TCC、Saga、本地消息表、Seata
- 分布式锁:Redis/Zookeeper 实现
- 一致性协议:Paxos、Raft(用于选主、数据同步)
- 微服务治理
- RPC 框架:Dubbo、gRPC
- API 网关:统一鉴权、限流、路由
常见拆分方式:
- 业务拆分:用户、订单、支付、消息等微服务
- 数据拆分:分库分表、读写分离、数据分区
- 计算拆分:任务并行、MapReduce、分布式计算
- 部署拆分:同一服务部署多个实例,由负载均衡分发请求
典型链路:
客户端
↓
CDN / DNS
↓
负载均衡 / API Gateway
↓
多个无状态服务实例
↓
缓存 / 消息队列 / 数据库
分布式会带来新的复杂性:
- 网络不可靠、请求超时
- 消息重复或乱序
- 节点状态不一致
- 跨服务事务困难
- 故障定位和链路追踪困难
因此通常还需要超时、重试、幂等、限流、熔断、分布式追踪和最终一致性等机制。
学习重点 & 面试点
需要掌握:
- 分布式理论:CAP、BASE、共识算法、Raft、Gossip、一致性哈希
- 服务拆分:单体拆成用户、订单、支付、消息、库存等服务。
- 服务通信:HTTP、RPC、gRPC、Dubbo、OpenFeign。
- 服务注册发现:Nacos、Eureka、Consul。
- 负载均衡:轮询、权重、最少连接、一致性哈希。
- 分布式事务:2PC、TCC、Saga、本地消息表、事务消息。
- 分布式锁:Redis、ZooKeeper、数据库锁。
- 数据一致性:强一致、最终一致、读写一致。
- 幂等设计:防止重复请求、重复消费、重复扣款。
- 链路追踪:TraceId、日志串联、调用链分析。
面试常问:
- 什么是 CAP?为什么三者不能同时满足?
- 分布式系统为什么需要幂等?
- Paxos、Raft、ZAB 有什么区别,分别用在什么地方?
- RPC和HTTP有什么区别与联系?各自适合什么场景?
- 分布式 ID 如何保证全局唯一、趋势递增和业务可读?
- Redis 分布式锁怎么实现?有什么坑?
- 分布式事务有哪些方案?你怎么选?
- 微服务如何拆分?调用失败怎么办?
- 服务注册发现原理是什么?
- 如何排查一次跨服务调用变慢?
三、高性能:解决“吞吐量/延迟”问题
高性能的核心是“减少等待、减少重复计算、提升并发处理能力”。
简要说明
性能主要看三个指标:
- 吞吐量:每秒处理多少请求,即 QPS/TPS
- 延迟:一次请求耗时多久,重点关注 P95、P99
- 资源效率:完成同等工作消耗多少 CPU、内存、网络和磁盘
常见优化顺序:
减少不必要的工作,例如避免重复查询和重复计算
缓存体系(最关键的一环)
本地缓存(Caffeine) + 分布式缓存(Redis) 多级缓存
缓存穿透/击穿/雪崩的应对方案(布隆过滤器、互斥锁、随机过期时间)
异步化
消息队列削峰填谷:Kafka、RocketMQ、RabbitMQ
异步非阻塞 IO:Netty、Reactor 模式
数据库优化
读写分离(主从复制)
索引优化、SQL 优化
连接池管理
计算与存储优化
池化技术(线程池、连接池)
批量处理、预计算
压缩、序列化协议优化(Protobuf 代替 JSON)
增加服务实例并做负载均衡;数据量继续增长后再分库分表
例如:
请求 → Redis 命中 → 直接返回
↓ 未命中
查询数据库
↓
写入缓存
高性能不等于无限加机器。系统可能卡在数据库锁、热点 Key、连接池、下游接口或网络带宽上,必须通过压测和监控找到真正瓶颈。
学习重点 & 面试点
需要掌握:
- 缓存:Redis、本地缓存、多级缓存。
- 数据库优化:索引、执行计划、慢 SQL、分页优化、读写分离。
- 异步化:消息队列、事件驱动、异步任务。
- 批处理:批量写入、批量查询、合并请求。
- 并发模型:线程池、协程、异步 IO、连接池。
- 水平扩展:多实例部署、负载均衡。
- 分库分表:按用户、订单、时间、Hash 分片。
- 限流:令牌桶、漏桶、滑动窗口。
- CDN 和静态资源优化:前端性能常见方向。
- 性能指标:QPS、TPS、RT、P95、P99、吞吐量。
面试常问:
- 优化高性能系统时,应该先定位哪些指标?
- Redis 为什么快?
- 缓存穿透、击穿、雪崩怎么解决?
- MySQL 索引为什么能提升查询性能?
- 慢 SQL 怎么排查?
- 深分页为什么慢?如何优化?
- 接口响应慢怎么优化?
- 线程池参数怎么设置?
- 四层负载均衡、七层负载均衡分别是什么,有什么区别?
- MQ 如何削峰填谷?
- Kafka/RocketMQ/RabbitMQ 如何保证消息不丢失、不重复、不乱序
- 读写分离解决什么问题,主从延迟会造成哪些业务问题?
- 分库分表后分页、排序、事务怎么处理?
- 综合系统设计:如何设计一个高性能订单系统
四、高可用:解决“故障容错”问题
高可用的核心是“故障一定会发生,系统要能扛住”。
简要说明
高可用的核心是:
消除单点故障,并控制故障传播范围。
常见手段包括:
冗余部署
多机房、多可用区部署,避免单点故障(SPOF)【即多实例:一个实例挂掉,由其他实例接管】
主从/多副本(数据库、缓存都要有副本)【即多副本:数据库主从、Redis Cluster、消息队列副本】
- 灰度发布、快速回滚
容错机制
熔断:Sentinel、Hystrix,防止雪崩
限流:令牌桶/漏桶算法,控制流量
降级:核心链路优先,非核心功能可关闭
超时与重试:避免请求堆积
监控与自愈
全链路监控:Prometheus + Grafana、SkyWalking
日志体系:ELK(Elasticsearch + Logstash + Kibana)
自动故障转移(Failover)、健康检查、自动摘除故障节点
容灾
数据备份与恢复、容灾切换
异地多活架构(最高等级高可用方案)
例如商品推荐服务发生故障时,主链路不应该一起失败:
商品详情请求
├─ 商品信息:必须成功
├─ 库存信息:必须成功
└─ 推荐服务:失败时返回空推荐
这就是降级:牺牲非核心功能,保住核心业务。
学习重点 & 面试点
需要掌握:
- 高可用基础:SLA、可用性指标、单点故障、灰度发布
- 多副本部署:服务多实例、数据库主从、Redis 哨兵/集群。
- 健康检查:服务是否存活、是否可处理请求。
- 故障转移:主从切换、节点摘除、自动恢复。
- 超时控制:避免请求无限等待。
- 重试机制:失败重试,但要防止重试放大。
- 幂等:避免重复写入
- 熔断:下游故障时快速失败。
- 降级:非核心功能临时关闭。
- 限流:保护系统不被流量打垮。
- 隔离:线程池隔离、资源隔离、服务隔离。
- 灰度发布:小流量验证。
- 回滚机制:发布异常快速恢复。
- 监控告警:指标、日志、链路追踪。
- 容灾备份:RTO、RPO、同城双活、异地多活、备份恢复。
面试常问:
- 高可用系统如何定义可用性?几个 9 分别意味着什么?
- 什么是服务雪崩?如何解决?
- 熔断和降级有什么区别,分别解决什么问题?
- 限流有哪些算法?
- Redis 宕机怎么办?
- MySQL 主库挂了怎么办?
- 如何设计一个高可用服务?
- 发布失败如何快速回滚?
- 什么是 RTO、RPO?
- 什么是幂等?HTTP 幂等语义和业务幂等有什么区别?
- 幂等键、唯一索引、Redis、乐观锁和状态机各适合什么场景?
五、补充
消息队列
消息队列属于以上哪一类?消息队列整个体系是怎样的,包括哪些模块?学习重点是什么,面试相关是怎样的
概览
核心结论先说:
消息队列不属于单一类别,它横跨三个体系——本质上是高性能的手段(异步处理、削峰填谷、解耦系统、提升吞吐量),依托分布式架构部署(集群化的中间件),同时又反过来支撑高可用(解耦故障、消息不丢)。这也是 MQ 在面试和实际架构中总被反复提到的原因:它是连接三个体系的枢纽型组件。更准确地说:
| 角度 | MQ 的作用/体现方式 |
|---|---|
| 分布式 | MQ 本身通常是分布式部署的中间件(如 Kafka 的多 Broker 集群),服务之间通过消息解耦,事件驱动协作 |
| 高性能 | 异步化处理、削峰填谷,提升系统吞吐量(这是 MQ 最核心、最常被提及的定位) |
| 高可用 | 通过消息持久化 + 多副本机制 + 死信队列,保证消息不丢失,系统某个下游服务挂掉时上游依然可用(削峰、隔离故障) |
所以面试里不要只说“MQ 属于高性能”。更好的回答是:
消息队列本质上是分布式系统里的异步通信中间件,主要用于提升系统性能和吞吐,同时也承担服务解耦、削峰填谷、最终一致性和故障恢复能力。
MQ 是实现"高性能"的手段(异步/削峰),依托"分布式"架构部署(集群),并反过来增强系统的"高可用"能力(解耦、隔离故障)。
MQ 整体知识体系模块
消息队列体系
├── 基础概念层
│ ├── 生产者/消费者/Broker/Topic/Partition
│ ├── 点对点模式 vs 发布订阅模式
│ └── 消息模型(队列模型 vs 发布订阅模型)
│
├── 核心机制层
│ ├── 消息发送:同步/异步/单向发送
│ ├── 消息存储:顺序写磁盘、页缓存、零拷贝(Kafka)
│ ├── 消息消费:拉模式(Pull) vs 推模式(Push)
│ ├── 消费位移(Offset)管理
│ └── 分区与负载均衡(Consumer Group 再均衡)
│
├── 可靠性保障层
│ ├── 消息丢失场景与应对(生产端确认、Broker 持久化、消费端 ACK)
│ ├── 消息重复消费与幂等性设计
│ ├── 消息顺序性保证(单分区顺序、全局顺序代价)
│ └── 事务消息(半消息机制,RocketMQ 事务消息)
│
├── 高可用与集群层
│ ├── 副本机制(Leader/Follower,ISR 机制 - Kafka)
│ ├── 主从切换与选举
│ ├── 消息堆积处理
│ └── 死信队列(DLQ)、延迟队列
│
├── 性能优化层
│ ├── 批量发送、压缩
│ ├── 顺序 IO、PageCache、零拷贝
│ └── 分区数设计与吞吐量关系
│
└── 主流产品对比
├── Kafka(高吞吐、大数据场景)
├── RocketMQ(金融级、事务消息强)
├── RabbitMQ(轻量、路由灵活、AMQP 协议)
└── Pulsar(存算分离新一代架构)
消息队列整体可以分成这些模块:
| 模块 | 作用 |
|---|---|
| Producer 生产者 | 发送消息的一方 |
| Broker 消息服务器 | 存储、转发、管理消息 |
| Topic / Queue | 消息分类或队列 |
| Consumer 消费者 | 拉取或接收消息并处理 |
| Consumer Group | 消费者组,用于负载均衡消费 |
| Offset | 消费进度 |
| ACK 确认机制 | 确认消息是否处理成功 |
| Retry 重试机制 | 消费失败后再次投递 |
| Dead Letter Queue 死信队列 | 多次失败后进入异常队列 |
| Persistence 持久化 | 防止 Broker 宕机丢消息 |
| Replication 副本 | 提高 MQ 本身可用性 |
| Ordering 顺序消息 | 保证同一业务维度消息有序 |
| Delay Message 延迟消息 | 指定时间后再投递 |
| Transaction Message 事务消息 | 配合本地事务保证最终一致性 |
常见产品:
- Kafka:高吞吐、日志流模型,适合大数据、日志、事件流。
- RabbitMQ:传统队列模型强,路由灵活,适合业务系统。
- RocketMQ:事务消息、顺序消息支持好,电商金融场景常见。
- ActiveMQ:老牌 MQ,现在新项目较少用。
学习重点
先理解模型,再学 API:搞懂 Topic/Partition/Consumer Group 的关系,再去看具体客户端怎么用。
可靠性三个环节要拆开学:
生产端不丢(ack=all / 事务消息)
Broker 不丢(持久化 + 多副本)
消费端不丢(手动 ACK + 幂等处理,而不是自动 ACK)
顺序性是有代价的:只有单分区内保证顺序,全局顺序会牺牲并发度,要理解这个 trade-off。
Kafka 的高性能原理要吃透(面试高频):顺序写、PageCache、零拷贝(sendfile)、批量发送 + 压缩。
动手实践:至少本地跑一遍 Kafka/RocketMQ,手写一个生产者-消费者 Demo,体会 offset 提交时机对消息丢失/重复的影响。
MQ 核心问题
学习 MQ 时,重点不是只会用 API,而是要理解这些问题:
1)为什么用 MQ?
核心场景:
- 异步:下单后发短信、发邮件、同步积分,不必阻塞主流程。
- 解耦:订单服务不直接调用库存、积分、通知服务。
- 削峰:秒杀流量先进 MQ,消费者按能力慢慢处理。
- 最终一致性:本地操作成功后,通过消息驱动其他系统补齐状态。
2)MQ 会带来什么问题?
引入 MQ 后,系统复杂度会上升:
- 消息可能丢失。
- 消息可能重复。
- 消息可能乱序。
- 消费可能失败。
- 消息可能积压。
- 生产者、Broker、消费者都可能宕机。
- 数据不再是强一致,而是最终一致。
3)如何保证消息不丢?
从三段看:
- 生产者到 Broker:发送确认、失败重试、事务消息。
- Broker 内部:消息持久化、副本同步。
- Broker 到消费者:手动 ACK,处理成功后再确认。
4)如何处理重复消费?
靠幂等,不要指望 MQ 永远只投递一次。
常见方案:
- 业务唯一键去重。
- 数据库唯一索引。
- Redis setnx 去重。
- 消费记录表。
- 状态机判断,例如订单已支付就不要重复扣款。
5)如何保证顺序消费?
常见方案:
- 同一业务 key 发到同一个队列或分区。
- 单队列单消费者消费。
- 消费端按业务 key 串行处理。
代价是吞吐量会下降,所以顺序消息只应该用于真正需要有序的场景。
6)消息积压怎么办?
排查方向:
- 消费者是否异常。
- 消费速度是否太慢。
- 是否下游数据库、接口变慢。
- 是否消息量突然暴涨。
- 是否消费者实例太少。
- 是否单条消息处理太重。
解决方式:
- 扩容消费者。
- 批量消费。
- 优化消费逻辑。
- 临时跳过非核心逻辑。
- 拆分 Topic 或队列。
- 对异常消息进入死信队列。
MQ 高频面试点
基础类
- MQ 的作用(解耦、异步、削峰)分别举例说明
- MQ 如何实现异步、应用解耦和削峰填谷
- Kafka/RocketMQ/RabbitMQ 的区别和选型依据
- 什么是消费者组?什么是 offset?ACK 机制是什么
- 你们为什么使用MQ
可靠性类(重灾区)
- 如何保证消息不丢失?(生产端、Broker、消费端三层分别怎么做)
- 如何保证消息不被重复消费?(幂等性设计:唯一键 + 状态判断 / 数据库唯一约束 / Redis setnx)
- 如何保证消息的顺序性?为什么全局顺序很难做?
- MQ 消息积压怎么排查?怎样区分生产流量突增、消费者变慢、分区不足和下游故障?
高可用/集群类
- Kafka 的 ISR 机制是什么?Leader 挂了之后如何选举?
- 消息积压了怎么办?(临时扩容消费者、批量消费、跳过非核心消息等应急方案)
- MQ 宕机怎么办?
- 死信队列的作用和使用场景
深入原理类(中高级面试)
- Kafka 为什么这么快?(顺序写磁盘 + 零拷贝 + PageCache + 批量压缩)
- Kafka 的 rebalance 机制及其可能引发的问题(消费暂停)
- RocketMQ 的事务消息(半消息)实现原理
场景设计类
- 秒杀系统中 MQ 怎么用来削峰?
- 订单超时未支付自动取消,如何用 MQ 的延迟队列实现?
- 如何设计一个可靠的消息系统?
一个比较完整的面试回答模板是:
我们使用 MQ 主要是为了解耦、异步和削峰。生产者发送消息后由 Broker 持久化,消费者异步消费。为了保证可靠性,生产端需要发送确认和失败重试,Broker 需要持久化和副本机制,消费端使用手动 ACK。由于 MQ 通常只能保证至少一次投递,所以业务侧必须做幂等。对于顺序消息,会按业务 key 路由到同一个队列或分区。对于消费失败,会通过重试和死信队列兜底。监控上重点看消息积压、消费延迟、失败率和 Broker 可用性。
学习顺序
学习顺序建议是:
- 先学分布式基础:服务拆分、RPC、注册发现、CAP、幂等。
- 再学高性能:缓存、数据库优化、异步化、限流、线程池。
- 然后学 MQ:异步、削峰、可靠投递、重复消费、顺序消息。
- 最后学高可用:熔断、降级、容灾、监控、故障恢复。
MQ 是连接这三块知识的典型中间件,面试价值很高。重点不是背概念,而是能围绕“为什么用、解决什么问题、引入什么风险、怎么兜底”讲清楚。
- 如果目标是校招/初级面试:重点吃透”基础概念层 + 可靠性保障层“,能讲清楚不丢不重不乱即可。
- 如果目标是中高级/架构面试:需要补齐”高可用与集群层 + 性能优化层“的原理,最好能画出 Kafka 副本同步、ISR 机制的图。
- 建议按上面"总览表"和"MQ 体系图"做成自己的知识卡片,面试前对着标题自测能否讲清楚每一项。
参考:JavaGuide消息队列面试题