分布式常见面试题整理
一、分布式理论:
-
CAP理论
分布式系统最多同时满足一致性(C)、可用性(A)、分区容错性(P)中的两个,无法三者兼得。 -
BASE理论
对CAP中一致性和可用性的权衡,强调基本可用(BA)、软状态(S)和最终一致性(E),适用于高可用场景。 -
2PC(两阶段提交)
分布式事务协议,分准备(投票)和提交/回滚两个阶段,保证强一致性但存在同步阻塞和单点问题。 -
3PC(三阶段提交)
2PC的改进,增加预提交阶段减少阻塞,但仍可能数据不一致。 -
ZAB协议
ZooKeeper的核心协议,通过选举Leader和原子广播实现数据一致性,用于分布式协调。 -
Raft协议
更易理解的共识算法,通过选举Leader、日志复制保证一致性,替代Paxos用于分布式系统一致性管理。
二、Zookeeper:
-
ZooKeeper是什么?
分布式协调服务,提供数据发布/订阅、分布式锁、集群管理等功能,基于ZAB协议保证一致性。 -
Zookeeper怎么保证主从节点的数据同步?
通过ZAB协议:Leader接收写请求,广播提案(Proposal),Follower/Observer同步日志并ACK,超过半数确认后Leader提交事务。 -
Zookeeper为什么能用做注册中心?
支持临时节点和Watcher机制,服务注册(创建节点)、下线(节点自动删除)、发现(监听节点变化)实时通知。 -
Zookeeper中有哪些类型的数据节点?
-
持久节点(PERSISTENT)
-
临时节点(EPHEMERAL)
-
持久顺序节点(PERSISTENT_SEQUENTIAL)
-
临时顺序节点(EPHEMERAL_SEQUENTIAL)
-
-
Zookeeper中Watcher机制是什么?
事件监听回调:客户端对节点注册Watcher,节点变化(增删改)时服务端触发事件通知,但是一次性的(需反复注册)。 -
Zookeeper集群中有哪些服务器角色?
-
Leader:处理写请求,发起提案和提交。
-
Follower:参与投票和选举,同步Leader数据。
-
Observer:同步数据但不投票,扩展读性能。
-
-
Zookeeper中的领导者选举是如何实现的?
基于ZAB协议:节点启动或Leader崩溃时进入选举状态,投票优先投zxid(事务ID)最大、其次serverid最大的节点,超过半数当选。 -
ZAB协议包括哪些内容?
-
崩溃恢复:选举新Leader,数据同步到最新状态。
-
消息广播:Leader将写请求以提案广播,半数确认后提交。
-
-
Zookeeper能解决脑裂问题吗?
能。基于过半机制(Quorum),写请求需多数节点确认,分裂后仅多数派分区能选举Leader和服务,少数派分区拒绝请求。 -
为什么Zookeeper集群的节点个数要用奇数个?
容错与成本平衡:n节点集群容忍(n-1)/2个故障。奇数节点在相同容错能力下(如3节点和4节点均容错1故障)更节省资源。 -
Zookeeper能用来做什么?
-
注册中心(如Dubbo)
-
分布式锁(临时顺序节点)
-
配置管理(持久节点+Watcher)
-
集群选主(临时节点+选举)
-
-
Zookeeper实现分布式锁的原理?
-
争抢锁:所有客户端在指定目录下创建临时顺序节点。
-
判断最小节点:最小节点获锁。
-
监听前序节点:非最小节点监听前一个节点,释放时触发通知。
-
避免惊群:仅监听前一个节点。
-
-
Zookeeper实现配置中心的原理?
-
存储配置:配置信息存储在持久节点。
-
动态更新:客户端监听节点Watcher,配置变更时服务端通知,客户端拉取新配置。
-
-
Zookeeper和Dubbo的关系?
Zookeeper作为Dubbo的注册中心,服务提供者注册地址到ZK,消费者从ZK发现服务列表,并监听变化实现动态路由。
三、分布式缓存:
-
什么是Redis?
开源内存数据结构存储,用作数据库、缓存、消息队列,支持多种数据结构与持久化。 -
为什么要用缓存?
-
高性能:内存读写快,降低数据库压力。
-
高并发:缓解数据库负载,提升系统吞吐量。
-
-
为什么用Redis不用Map?
-
Redis是分布式缓存,支持多服务共享;本地Map仅单机有效。
-
Redis提供持久化、丰富数据结构、过期策略等。
-
-
Redis线程模型?
单线程Reactor模型(6.0前):单线程处理命令+IO多路复用,避免上下文切换,保证原子性。 -
Redis和Memcached区别?
-
Redis:支持多种数据结构、持久化、主从复制,适用复杂场景。
-
Memcached:只支持KV、多线程、无持久化,纯缓存场景性能更高。
-
-
Redis常见数据结构及使用场景?
-
String:缓存、计数器
-
Hash:存储对象
-
List:消息队列、栈
-
Set:标签、好友关系
-
ZSet:排行榜
-
Bitmap:位统计
-
HyperLogLog:基数估算
-
Stream:消息流(5.0+)
-
-
Redis故障恢复?
通过持久化:-
RDB:快照恢复,数据可能丢失。
-
AOF:日志重放,数据更完整(可配置fsync策略)。
-
-
保证Redis中为热点数据?
设置内存上限+淘汰策略(如LRU/LFU),自动淘汰冷数据。 -
如何实现Redis事务?
-
MULTI
开启事务,命令入队。 -
EXEC
执行(原子性,但无回滚)。 -
WATCH
监控Key(乐观锁)。
-
-
缓存雪崩及解决?
-
问题:大量缓存同时过期,请求直接击穿数据库。
-
解决:随机过期时间、集群高可用、永不过期(后台更新)。
-
-
缓存穿透及解决?
-
问题:查询不存在的数据(如恶意攻击),绕过缓存。
-
解决:布隆过滤器、空值缓存、接口校验。
-
-
缓存击穿及解决?
-
问题:热点Key过期,瞬间高并发查询数据库。
-
解决:互斥锁(如Redis SETNX)、永不过期(逻辑过期)。
-
-
并发竞争Key问题?
-
用WATCH+事务(乐观锁)。
-
或分布式锁(如Redisson)保证串行访问。
-
-
什么是RedLock?
Redis官方分布式锁算法:向多个独立Redis实例申请锁,过半成功才算获取,避免单点故障。 -
缓存与数据库双写一致性?
-
策略:先更新数据库,再删除缓存(延迟双删)。
-
补充:读请求先读缓存,未命中读库+回写。
-
-
单节点实现分布式锁?
SET key random_value NX PX 3000
(原子设值+过期时间),解锁时用Lua脚本校验值再删除。 -
Redis使用场景?
缓存、会话存储、排行榜、消息队列、分布式锁等。 -
Redis功能?
持久化、主从复制、哨兵、集群、事务、Pub/Sub等。 -
Redis为什么单线程?
避免锁竞争和上下文切换,内存操作+IO多路复用已足够高效(6.0后多线程仅处理网络IO)。 -
Redis的Java客户端?
Jedis(同步阻塞)、Lettuce(异步非阻塞)、Redisson(分布式功能封装)。 -
Jedis和Redisson区别?
-
Jedis:轻量级API,直接操作Redis。
-
Redisson:分布式对象(如锁、队列)封装,更高级抽象。
-
-
Redis实现分布式锁?
-
命令:
SETNX
+过期时间(防死锁)。 -
推荐:Redisson的RLock,支持可重入、续期。
-
-
Redis持久化方式?
-
RDB:快照,二进制压缩文件。
-
AOF:日志追加,可配置每秒/每次同步。
-
混合持久化(4.0+):RDB+AOF。
-
-
Redis内存优化?
-
使用合适数据结构(如Hash代替多个String)。
-
配置最大内存+淘汰策略。
-
缩短键值长度,使用整数池。
-
-
Redis分布式锁缺陷?
-
非强一致性(主从切换可能锁失效)。
-
需自己解决续期、原子性等问题(推荐Redisson)。
-
-
Redis性能问题及解决?
-
慢查询:优化命令,避免大数据操作。
-
内存不足:增加内存或优化数据。
-
网络瓶颈:集群分片或客户端优化。
-
-
Redis淘汰策略?
-
volatile-lru/ttl:过期键中淘汰。
-
allkeys-lru/lfu:所有键中淘汰。
-
random:随机淘汰。
-
noeviction:不淘汰(默认)。
-
-
单线程Redis为什么快?
-
内存操作。
-
IO多路复用(epoll)。
-
单线程无锁竞争。
-
-
Redis应用场景?
缓存、会话共享、分布式锁、排行榜、消息队列、地理空间计算等。
四、消息队列:
-
MQ选型考虑因素?
吞吐量(Kafka/RocketMQ)、延迟(RabbitMQ)、可靠性、功能(事务/延迟消息)、生态和运维成本。 -
RabbitMQ消息发送过程?
生产者→交换机(Exchange)→路由绑定(Binding)→队列(Queue)→消费者。 -
RabbitMQ保证消息稳定性?
-
持久化(交换机、队列、消息)。
-
生产者确认(Confirm)、消费者手动ACK。
-
集群镜像队列。
-
-
避免消息丢失?
-
生产者:开启Confirm机制(确认Broker接收)。
-
Broker:持久化+镜像队列。
-
消费者:手动ACK(处理完再确认)。
-
-
持久化缺点?
磁盘IO性能下降(但内存+磁盘组合仍可接受)。 -
消息持久化成功条件?
-
交换机、队列持久化。
-
消息投递模式(delivery_mode=2)。
-
写入磁盘(刷盘策略)。
-
-
RabbitMQ广播类型?
-
直连(Direct)、主题(Topic)、扇出(Fanout)、头(Headers)。
-
-
实现延迟消息队列?
插件(rabbitmq_delayed_message_exchange)或TTL+死信队列(DLX)。 -
RabbitMQ节点类型?
-
磁盘节点(元数据持久化)。
-
内存节点(元数据内存,性能高)。
-
-
每个节点是完整拷贝吗?
不是。仅元数据(队列结构等)同步,消息数据需配置镜像队列才复制。 -
唯一磁盘节点崩溃?
集群无法修改元数据(如创建队列),但内存节点仍可服务(需至少一个磁盘节点存活)。 -
集群节点停止顺序?
先停内存节点,最后停磁盘节点(避免元数据丢失)。 -
RabbitMQ使用场景?
异步解耦、流量削峰、延迟消息、顺序消息(单队列)。 -
重要角色?
生产者、消费者、Broker(服务器)、交换机、队列。 -
重要组件?
连接(Connection)、信道(Channel)、虚拟主机(vhost)。 -
vhost作用?
逻辑隔离(不同业务组独立使用),类似命名空间。 -
什么是Kafka?
分布式流处理平台,高吞吐、持久化、多订阅,用于日志、消息队列等。 -
为什么用消息队列?
解耦、异步、削峰。 -
Kafka中ISR、AR?
-
AR:所有副本。
-
ISR:与Leader同步的副本(含Leader)。
-
ISR伸缩:副本滞后(超过replica.lag.time.max.ms)被踢出,追上后加入。
-
-
Broker作用?
存储消息,处理读写请求。 -
Zookeeper在Kafka中的作用?可不用吗?
-
存储元数据(Broker、Topic、分区信息)、选Controller。
-
2.8.0后支持不用Zookeeper(KRaft模式)。
-
-
Follower同步数据?
拉取(Pull)Leader数据,写入本地日志。 -
Broker被踢出ISR?
同步滞后(如网络慢、宕机)超过阈值(replica.lag.time.max.ms)。 -
Kafka为什么快?
-
顺序读写磁盘。
-
零拷贝(sendfile)。
-
分区并行+批量压缩。
-
-
Producer优化速度?
批量发送(linger.ms、batch.size)、压缩、异步发送。 -
ack含义?
-
0:不等待确认(可能丢失)。
-
1:Leader确认(可能丢失)。
-
-1(all):ISR所有副本确认(可靠)。
-
-
Message格式?
偏移量+时间戳+Key+Value+头部字段。 -
Consumer Group作用?
实现发布订阅(不同Group独立消费)和队列(同Group内竞争消费)。 -
消息丢失和重复消费?
-
丢失:ack配置不当、未处理完消费者宕机。
-
重复:生产者重试、消费者提交偏移量失败。
-
-
为什么不支持读写分离?
Leader处理读写,利用顺序写和页缓存,避免数据不一致和网络开销。 -
消息顺序性?
分区内顺序(同一分区消息顺序消费),但全局不保证。 -
实现延迟队列?
使用时间戳+多个Topic(或Kafka自2.1+支持内部延迟)。 -
事务实现?
跨分区原子写(Producer端),使用事务协调器。 -
选举及策略?
-
Controller选举:基于Zookeeper(临时节点)。
-
Partition Leader:Controller指定(ISR中首选)。
-
-
RocketMQ选型原因?
对比Kafka(高吞吐但延迟高)、RabbitMQ(低延迟但吞吐低),RocketMQ平衡吞吐、延迟、事务消息、中文生态。 -
RocketMQ分布式存储?
主题分多个队列(Queue),分布在不同Broker,每个队列多副本。 -
Broker宕机处理?
-
主从切换(Slave同步数据,自动提升为Master)。
-
集群消费模式(重试其他Broker)。
-
-
发现Broker?
通过NameServer(服务发现)获取Broker路由信息。 -
RocketMQ核心部分?
NameServer(元数据)、Broker(存储)、Producer、Consumer。 -
NameServer部署几台?
可多台(通常2-4),集群部署避免单点,但节点间无数据同步(各存全量数据)。 -
Broker注册到哪个NameServer?
配置的所有NameServer(全部注册)。 -
获取Broker信息?
客户端定时从NameServer拉取路由表。 -
感知Broker宕机?
NameServer心跳检测(Broker定时上报),超时则剔除。 -
Master同步Slave?
异步或同步复制(取决于配置)。 -
Slave挂掉影响?
无直接影响(Master仍服务),但降低可用性(无法故障切换)。 -
Master挂掉?
-
自动切换:Slave提升为Master(需配置Dledger或故障转移)。
-
手动干预:依赖运维脚本。
-
-
Dledger机制?
Raft协议实现,保证多副本数据一致性,自动选主和故障转移。
五、分布式锁:
-
需要使用分布式锁的场景?
秒杀库存扣减、集群定时任务调度、共享资源访问(如文件修改)、防止重复提交等。 -
常见的分布式锁解决方案?
-
基于数据库(唯一索引、悲观锁)
-
基于Redis(SETNX+过期时间)
-
基于ZooKeeper(临时顺序节点)
-
基于Etcd(租约机制)
-
-
Redis分布式锁实现方法?
命令:SET lock_key random_value NX PX 3000
(原子操作设值+过期时间)。
释放:Lua脚本校验值再删除(防误删)。
缺陷:主从切换可能锁失效(可用RedLock算法缓解)。 -
ZooKeeper分布式锁实现原理?
-
争抢锁:所有客户端在锁目录下创建临时顺序节点。
-
判断最小节点:序号最小的节点获锁。
-
监听前序节点:未获锁的客户端监听前一个节点,释放时通知下一个节点。
-
优点:强一致性,无锁失效问题;缺点:性能较低。
-
-
ZK和Redis分布式锁优缺点?
-
Redis:
优点:性能高、实现简单。
缺点:非强一致性(主从同步延迟可能锁失效)。 -
ZooKeeper:
优点:强一致性、可靠性高。
缺点:性能较低、依赖ZK集群。
-
-
Mysql如何做分布式锁?
-
方法1:基于唯一索引(插入成功获锁,删除释放)。
-
方法2:基于悲观锁(
SELECT ... FOR UPDATE
)。
缺点:数据库性能瓶颈,锁无自动失效(需超时机制)。
-
-
业界大公司的分布式锁框架?
-
Google:Chubby(基于Paxos,类似ZK)。
-
阿里巴巴:基于Redis的分布式锁(Redisson封装)。
-
Netflix:基于ZooKeeper的分布式锁。
-
Apache:Curator(ZK客户端,提供分布式锁封装)。
-
六、分布式服务调用:
-
什么是RPC?
远程过程调用,像调用本地方法一样调用远程服务,隐藏网络细节。 -
RPC over HTTP vs RPC over TCP?
-
HTTP:通用、穿透性好(如Rest),但性能较低。
-
TCP:自定义协议(如Dubbo),性能高,但更复杂。
-
-
Dubbo核心组件?
-
Provider:服务提供者
-
Consumer:服务消费者
-
Registry:注册中心(如Zookeeper)
-
Monitor:监控中心
-
Container:服务运行容器
-
-
Dubbo服务调用过程?
消费者通过代理调用→从注册中心获取服务列表→负载均衡选Provider→网络传输(序列化/反序列化)→执行并返回结果。 -
集群容错方案?
-
Failover(默认):失败自动重试其他节点。
-
Failfast:快速失败,立即报错。
-
Failsafe:忽略错误,记录日志。
-
Failback:失败后台记录,定时重试。
-
Forking:并行调用多个节点,取最先返回的结果。
-
Broadcast:广播调用所有节点,任意一个报错则报错。
-
-
服务调用是阻塞的吗?
默认同步阻塞调用,但支持异步调用(Future或回调)。 -
Dubbo支持的协议及场景?
-
dubbo协议(默认):TCP长连接,高性能,适合大并发小数据量。
-
rmi协议:JDK标准,适合短连接大数据包。
-
http协议:基于HTTP,易跨语言。
-
hessian协议:基于HTTP,适合多语言交互。
-
-
Dubbo vs Spring Cloud?
-
Dubbo:性能高(RPC),适合内部服务调用。
-
Spring Cloud:生态全(HTTP+Rest),适合微服务全家桶。
根据团队技术栈和需求选择。
-
-
负载均衡策略?
-
Random(默认):随机选择。
-
RoundRobin:轮询。
-
LeastActive:选最不活跃的节点(请求数最少)。
-
ConsistentHash:一致性Hash,相同参数总是请求同一节点。
-
-
序列化框架?
默认Hessian2,还支持Kryo(高性能)、FST、JSON等。 -
服务降级?
-
配置mock值:强制返回默认值(如null)。
-
容错mock:失败时执行mock逻辑。
-
-
服务暴露过程?
服务提供者启动→向注册中心注册服务→本地暴露服务(启动Netty服务器监听请求)。 -
服务引入过程?
消费者启动→从注册中心订阅服务→获取提供者列表→创建代理对象(用于远程调用)。 -
支持一个服务多个协议?
支持,可在@Service注解中配置多个协议(如dubbo和hessian),不同协议不同端口。 -
支持一个服务多个注册中心?
支持,可配置服务同时注册到多个注册中心(如Zookeeper和Nacos)。 -
支持一个服务多个版本?
支持,通过版本号(version)区分,消费者可指定调用特定版本的服务。
七、微服务:
-
如何理解微服务?
将单体应用拆分为一组小型、独立部署的服务,每个服务围绕特定业务能力构建,服务间通过轻量级通信协作。 -
微服务特点?
-
单一职责
-
独立部署、扩展和技术选型
-
去中心化治理
-
容错性强
-
通过API交互
-
-
SOA vs 微服务?
-
SOA:强调集成(ESB总线)、复用、粗粒度服务。
-
微服务:强调独立、轻量通信(HTTP/RPC)、细粒度服务、快速交付。
-
-
微服务优缺点?
-
优点:灵活技术栈、独立扩缩容、故障隔离、易于迭代。
-
缺点:运维复杂、网络延迟、数据一致性难、测试部署复杂。
-
-
Spring Cloud Netflix组件?
-
Eureka:服务注册发现
-
Ribbon:客户端负载均衡
-
Feign:声明式HTTP客户端
-
Hystrix:熔断降级
-
Zuul:网关(旧版)
-
-
Spring Cloud Alibaba组件?
-
Nacos:注册中心+配置中心
-
Sentinel:流量控制、熔断降级
-
Seata:分布式事务
-
Dubbo:RPC调用
-
-
断路器作用?
防止服务雪崩:当下游服务故障时,快速失败或降级,避免资源耗尽。 -
Spring Cloud实现服务注册?
服务提供者通过@EnableDiscoveryClient
向注册中心(如Eureka/Nacos)注册实例信息。 -
Eureka vs Zookeeper?
-
Eureka:AP架构,保证可用性,适合注册中心。
-
Zookeeper:CP架构,保证一致性,适合分布式协调。
-
-
Ribbon作用?
客户端负载均衡:从注册中心获取服务列表,根据策略(如轮询、随机)选择实例调用。 -
Feign作用?
声明式REST客户端:基于注解和接口定义HTTP请求,整合Ribbon和Hystrix。 -
Hystrix作用?
熔断器:实现服务熔断、降级、线程隔离,提高系统弹性。 -
Spring Cloud Bus作用?
消息总线:用于广播配置变更(配合Config),实现批量刷新配置。 -
网关作用?
-
路由转发
-
认证鉴权
-
限流熔断
-
日志监控
(如Spring Cloud Gateway)
-
-
Spring Cloud vs Dubbo?
-
Spring Cloud:生态全(HTTP+Rest),适合微服务全家桶。
-
Dubbo:性能高(RPC),适合内部服务调用。
-
现在可融合(Spring Cloud Alibaba整合Dubbo)。
-
-
Restful?
一种架构风格:资源用URI标识,通过HTTP方法(GET/POST/PUT/DELETE)操作,无状态、可缓存。 -
如何拆分服务?拆分原则?
-
根据业务领域(DDD限界上下文)
-
单一职责、高内聚低耦合
-
团队结构(康威定律)
-
避免分布式大单体
-
-
服务网格(Service Mesh)?
-
是什么:基础设施层,处理服务间通信(如Istio、Linkerd)。
-
特点:解耦业务代码与通信逻辑(Sidecar代理)。
-
解决:服务发现、负载均衡、熔断、安全、可观测性等。
-
-
DDD(领域驱动设计)?
通过领域模型和通用语言解决复杂业务问题,核心包括:-
限界上下文(Bounded Context)
-
实体、值对象、聚合根
-
领域事件、仓储、工厂
用于指导微服务拆分和架构设计。
-
八、分布式事务:
-
什么是分布式事务?
跨多个数据库或服务的事务操作,需要保证所有操作要么全部成功,要么全部失败。 -
常用解决方案?
-
2PC/3PC(强一致性)
-
TCC(补偿型)
-
消息事务(最终一致性)
-
Saga(长事务)
-
本地消息表
-
-
XA方案流程?
基于数据库XA协议:-
事务管理器(TM)启动全局事务。
-
资源管理器(RM)执行分支事务(预提交)。
-
TM收集所有RM状态,决定提交或回滚。
缺点:同步阻塞,性能低。
-
-
2PC(两阶段提交)?
-
阶段一(准备):协调者询问所有参与者是否可提交,参与者执行事务但不提交。
-
阶段二(提交/回滚):若所有参与者同意,协调者通知提交;否则回滚。
缺点:同步阻塞、单点问题、数据不一致(协调者宕机)。
-
-
3PC(三阶段提交)?
在2PC基础上增加超时机制和预提交阶段:-
CanCommit:询问参与者是否具备条件。
-
PreCommit:预执行事务。
-
DoCommit:提交或回滚。
减少阻塞,但仍可能数据不一致。
-
-
TCC(Try-Confirm-Cancel)?
业务层补偿型方案:-
Try:预留资源(如冻结库存)。
-
Confirm:确认操作(扣减库存)。
-
Cancel:取消操作(释放库存)。
需业务实现补偿逻辑,保证最终一致性。
-
-
Seata解决方案?
-
AT模式(默认):基于undo_log日志,实现两阶段提交(无侵入)。
-
TCC模式:需业务实现Try/Confirm/Cancel接口。
-
Saga模式:长事务补偿流程。
-
XA模式:基于数据库XA协议。
-
-
如何选择方案?考虑维度:
-
一致性要求(强/最终)
-
性能(吞吐、延迟)
-
业务侵入性
-
复杂度与维护成本
-
技术栈兼容性
-
-
Saga模式?
长事务解决方案:将大事务拆分为多个本地事务,每个事务有对应补偿操作。失败时逆向执行补偿。
适用于业务流程长、低一致性要求的场景。 -
常见分布式事务框架及原理?
-
Seata:AT/TCC/XA/Saga模式。
-
RocketMQ事务消息:半消息机制实现最终一致性。
-
LCN(早期):基于代理连接池,模拟两阶段提交。
-
-
消息队列解决分布式事务?
使用事务消息(如RocketMQ):-
发送半消息(对消费者不可见)。
-
执行本地事务。
-
根据本地事务结果提交或回滚消息。
-
消费者消费消息,保证最终一致性。
-