粉粉蕉的笔记本粉粉蕉的笔记本
  • JAVA

    • 代码笔记
    • Java8实战
    • 分布式事务实战(Seata)
    • 模板引擎(FreeMarker)
    • SpringSecurity
    • Maven
  • PYTHON

    • 概述
    • python3
    • python3(菜鸟教程)
    • pandas
    • numpy
    • matplotlib
  • 中间件

    • Kafka
    • RocketMQ
    • Redis
    • MongoDB
    • Elastic Search
  • 数据库

    • Mysql
  • 前端

    • HTML
    • CSS
    • Javascript
    • Vue2学习笔记
    • Vue3学习笔记
  • 设计模式
  • 大数据

    • 概览
    • Hadoop
    • Hive
  • 机器学习

    • 机器学习概览
  • openclaw实战
  • claudecode实战
  • RAG
  • 拟人类Agent
  • linux命令速查
  • windows命令速查
  • Docker笔记
  • kubernetes学习笔记
  • kubernetes实操笔记
  • 运维工具大全
  • git操作宝典
  • 概率论
  • 线性代数
  • 统计学
  • 金融知识学习
  • 聚宽
  • 因子分析
  • 后端

    • JAVA基础
    • JAVA多线程
    • JVM
    • 分布式相关
    • 数据库
  • 前端

    • HTML
    • CSS
    • JAVASCRIPT
    • VUE3
    • 网络
    • 前端工程化
    • nodejs
  • AI

    • RAG
  • 健身

    • 笔记
    • 训练计划
  • 读书笔记

    • 《深度学习》
  • 其他

    • RSS
    • 资源导航
    • 医保
    • 装修攻略
我也想搭建这样的博客!
🚋开往
  • JAVA

    • 代码笔记
    • Java8实战
    • 分布式事务实战(Seata)
    • 模板引擎(FreeMarker)
    • SpringSecurity
    • Maven
  • PYTHON

    • 概述
    • python3
    • python3(菜鸟教程)
    • pandas
    • numpy
    • matplotlib
  • 中间件

    • Kafka
    • RocketMQ
    • Redis
    • MongoDB
    • Elastic Search
  • 数据库

    • Mysql
  • 前端

    • HTML
    • CSS
    • Javascript
    • Vue2学习笔记
    • Vue3学习笔记
  • 设计模式
  • 大数据

    • 概览
    • Hadoop
    • Hive
  • 机器学习

    • 机器学习概览
  • openclaw实战
  • claudecode实战
  • RAG
  • 拟人类Agent
  • linux命令速查
  • windows命令速查
  • Docker笔记
  • kubernetes学习笔记
  • kubernetes实操笔记
  • 运维工具大全
  • git操作宝典
  • 概率论
  • 线性代数
  • 统计学
  • 金融知识学习
  • 聚宽
  • 因子分析
  • 后端

    • JAVA基础
    • JAVA多线程
    • JVM
    • 分布式相关
    • 数据库
  • 前端

    • HTML
    • CSS
    • JAVASCRIPT
    • VUE3
    • 网络
    • 前端工程化
    • nodejs
  • AI

    • RAG
  • 健身

    • 笔记
    • 训练计划
  • 读书笔记

    • 《深度学习》
  • 其他

    • RSS
    • 资源导航
    • 医保
    • 装修攻略
我也想搭建这样的博客!
🚋开往

分布式中间件面试题

⭐分布式系统有哪些组件?

一个完整的分布式系统通常由以下核心组件构成:

组件作用常见实现
网关(Gateway)统一入口、路由转发、鉴权、限流Nginx、Kong、Spring Cloud Gateway
微服务(Microservice)按业务领域拆分的独立服务单元Spring Boot、Dubbo
服务注册与发现管理服务实例的注册、心跳、发现Eureka、Nacos、Zookeeper、Consul
消息队列(MQ)异步解耦、削峰填谷、分布式事件Kafka、RabbitMQ、RocketMQ
分布式缓存减少数据库压力,提升读性能Redis、Memcached
分布式锁控制跨节点的并发访问Redis(Redisson)、Zookeeper
分布式事务保证跨服务操作的数据一致性Seata(AT/TCC/XA)、MQ 事务
配置中心统一管理各服务的配置,支持动态刷新Nacos、Apollo、Spring Cloud Config
链路追踪追踪一次请求在多个服务间的调用链SkyWalking、Zipkin、Jaeger

⭐CAP 原则

CAP 是分布式系统设计的基础理论,指以下三者不能同时全部满足:

原则全称含义
CConsistency(一致性)所有节点在同一时刻看到的数据完全一致
AAvailability(可用性)每个请求都能收到响应(不保证数据最新)
PPartition tolerance(分区容错性)网络分区(部分节点断联)时集群仍能继续运行

网络分区(P)在分布式系统中几乎无法避免,因此所有分布式系统都必须保证 P,实际选择是在 C 和 A 之间权衡。

CP vs AP 的典型代表:

系统模型原因
ZookeeperCPLeader 选举期间集群暂时不可用,保证数据强一致
EurekaAP每个节点都是平等的,只要有一台存活集群就可用,但注册表可能短暂不一致
Nacos可切换默认 AP,可配置为 CP 模式

⭐网关

Nginx 的原理及常见配置

Nginx 是基于事件驱动 + 非阻塞 I/O 的高性能 Web 服务器和反向代理,采用 Master-Worker 多进程模型:

  • Master 进程:负责读取配置、管理 Worker 进程
  • Worker 进程:实际处理请求,每个 Worker 使用 epoll 事件循环处理大量并发连接

常用配置场景:

# 反向代理
server {
    listen 80;
    server_name api.example.com;

    location /api/ {
        proxy_pass http://backend:8080/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

# 负载均衡(轮询)
upstream backend_cluster {
    server 192.168.1.10:8080 weight=3;
    server 192.168.1.11:8080 weight=1;
    server 192.168.1.12:8080 backup;   # 备用节点

    keepalive 32;  # 复用长连接
}

# 静态资源缓存
location ~* \.(jpg|png|css|js)$ {
    expires 7d;
    add_header Cache-Control "public, immutable";
}

# 限流
limit_req_zone $binary_remote_addr zone=api:10m rate=100r/m;
location /api/ {
    limit_req zone=api burst=20 nodelay;
}

⭐微服务(Spring Cloud)

Spring Cloud 有哪些核心组件?

组件功能说明
Eureka服务注册与发现AP 模型,适合高可用场景
Nacos服务注册 + 配置中心阿里出品,功能更全,推荐替代 Eureka
Ribbon客户端负载均衡在 RestTemplate 上加 @LoadBalanced
OpenFeign声明式 HTTP 客户端基于接口注解调用远程服务
Hystrix / Sentinel熔断、降级、限流Hystrix 已停止维护,推荐 Sentinel
Zuul / Spring Cloud GatewayAPI 网关Gateway 基于 Reactor 非阻塞,性能更好
Config / Nacos配置中心统一管理配置,支持动态刷新
Sleuth + Zipkin链路追踪追踪跨服务调用链路

Eureka 服务注册与发现流程

1. Eureka Server 启动,初始化注册表(Registry)

2. Eureka Client 启动,向 Server 发起注册(Register)
   → 携带服务名、IP、Port、实例ID 等信息

3. Client 每 30 秒发送心跳(Renew),表明自己存活

4. Client 同时每 30 秒从 Server 拉取最新注册表,缓存到本地

5. 调用时:从本地缓存获取目标服务实例列表,通过 Ribbon 做负载均衡

6. Server 超过 90 秒未收到心跳,将该实例从注册表剔除(Eviction)

自我保护机制:若 15 分钟内心跳正常比率低于 85%,Server 开启自我保护模式——停止剔除实例,防止因网络抖动误删健康节点。

Eureka 服务调用失败处理方案

方案说明
熔断(Circuit Breaker)默认:20 个请求中 50% 失败则触发熔断,后续请求直接返回失败,5s 后重试探测
降级(Fallback)熔断后执行预设的 Fallback 方法,返回兜底数据或友好提示
限流(Rate Limiting)控制请求速率,保护下游服务不被压垮
重试(Retry)对幂等接口(GET)自动重试,非幂等接口慎用

什么是幂等性?如何保证?

幂等性:对同一请求执行一次和执行多次的效果完全一样。

HTTP 方法是否幂等原因
GET✅只读,不修改数据
PUT✅全量覆盖,多次结果相同
DELETE✅删除后再删除结果相同
POST❌每次调用可能创建新资源
PATCH❌部分更新,多次叠加可能不同

保证幂等的常见方案:

  1. 唯一请求 ID(Token 机制):客户端生成唯一 Token 随请求发送,服务端执行前检查 Token 是否已处理过(Redis 存储),处理后删除 Token
  2. 数据库唯一约束:订单号、支付流水号设唯一索引,重复插入直接报错
  3. 状态机控制:判断当前状态是否允许该操作(如"已支付"状态不允许再次支付)
  4. 乐观锁(版本号):UPDATE ... WHERE version = #{version} 确保只成功一次

⭐消息队列

RabbitMQ 核心组件与使用场景

组件:

组件说明
Producer(生产者)发送消息到 Exchange
Exchange(交换机)根据路由规则将消息分发到队列(类型:direct/topic/fanout/headers)
Queue(队列)存储待消费的消息
Consumer(消费者)从队列中取出并处理消息
Binding(绑定)Queue 与 Exchange 的绑定关系 + Routing Key
Virtual Host逻辑隔离,相当于命名空间

典型使用场景:

场景说明
异步处理下单后异步发邮件、发短信,不阻塞主流程
解耦订单服务发消息,库存/物流服务各自消费,互不依赖
削峰填谷秒杀活动:请求先进队列,后端按自身处理能力消费
分布式事务消息事务保证跨服务的最终一致性

Kafka vs RabbitMQ 对比

特性KafkaRabbitMQ
吞吐量极高(百万级/秒)万级/秒
消息顺序分区内有序队列内有序
消费模型拉取(Pull),消费者主动拉推送(Push),Broker 推
消息持久化默认持久化,按 retention 保留可配置,消费后删除
适用场景日志收集、大数据流处理、事件总线业务解耦、任务队列、实时通知
协议自定义协议AMQP

⭐分布式缓存

Redis 常用数据类型及操作

类型适用场景常用命令
String缓存值、计数器、分布式 SessionSET/GET/INCR/EXPIRE
Hash对象缓存(用户信息)HSET/HGET/HGETALL/HDEL
List消息队列、最新 N 条记录LPUSH/RPUSH/LPOP/LRANGE
Set去重、标签、共同好友SADD/SMEMBERS/SINTER/SUNION
ZSet(有序集合)排行榜、延时队列ZADD/ZRANGE/ZREVRANK/ZSCORE
Bitmap签到、布隆过滤器SETBIT/GETBIT/BITCOUNT
HyperLogLogUV 统计(近似去重)PFADD/PFCOUNT

缓存雪崩、穿透、击穿的区别与解决

缓存雪崩:大量 Key 在同一时刻过期,导致请求全部打到数据库。

原因:Key 过期时间相同(如批量导入时统一设置 TTL)
解决:
  1. Key 的 TTL 加随机偏移值(如 TTL = base + random(0, 300))
  2. 热点数据永不过期,由业务逻辑控制刷新
  3. Redis 集群 + 多级缓存(本地缓存 Caffeine 兜底)

缓存穿透:查询根本不存在的数据,缓存和数据库都没有,请求直接透传数据库。

原因:恶意请求、Bug 导致大量无效 ID 查询
解决:
  1. 参数校验,非法 ID 直接拒绝
  2. 缓存空值(查数据库无结果时,缓存一个空值,TTL 设短一点)
  3. 布隆过滤器(Bloom Filter):预加载所有合法 ID,查询前先过滤

缓存击穿:某个热点 Key 恰好在某一瞬间过期,大量并发请求同时打到数据库。

原因:单个高并发 Key 失效
解决:
  1. 热点数据永不过期
  2. 互斥锁(Mutex):只允许一个线程查数据库并回写缓存,其他线程等待
  3. 逻辑过期:数据本身存在(不设 TTL),在 value 中嵌入过期时间字段,
     异步线程负责更新

⭐分布式锁

什么时候需要分布式锁?

当多台机器上部署的服务需要对同一共享资源进行互斥操作时(如库存扣减、防止重复下单),需要分布式锁来替代单机的 synchronized/ReentrantLock。

三种实现分布式锁的方式

1. 基于 Redis(推荐,使用 Redisson 框架)

// Redisson 使用示例
RLock lock = redissonClient.getLock("order:stock:lock");
try {
    // 尝试获取锁,最多等待 3 秒,锁持有最多 10 秒(自动续期)
    boolean acquired = lock.tryLock(3, 10, TimeUnit.SECONDS);
    if (acquired) {
        // 执行业务逻辑
        deductStock(productId);
    }
} finally {
    if (lock.isHeldByCurrentThread()) {
        lock.unlock();
    }
}

底层原理:SET key value NX PX timeout(原子性设置 + 过期时间);
Redisson 额外实现了看门狗(Watchdog)机制:锁持有期间定时续期,避免业务未完成锁就过期。

2. 基于 Zookeeper(临时节点)

原理:在 /locks/order/ 下创建临时顺序节点
最小节点的持有者获得锁;
其他节点监听前一个节点的删除事件(Watch)
节点 Session 断开时临时节点自动删除,锁自动释放

优点:天然解决锁过期问题(Session 断开即释放);
缺点:性能较 Redis 低,Zookeeper 集群本身是 CP 模型。

3. 基于数据库(简单场景)

-- 创建锁表
CREATE TABLE distributed_lock (
  lock_name VARCHAR(64) PRIMARY KEY,
  holder    VARCHAR(64),
  expire_at DATETIME
);

-- 获取锁
INSERT INTO distributed_lock VALUES ('stock_lock', 'node-1', NOW() + INTERVAL 10 SECOND);
-- 若主键冲突则获取失败

-- 释放锁
DELETE FROM distributed_lock WHERE lock_name = 'stock_lock' AND holder = 'node-1';

缺点:依赖数据库性能,锁过期处理复杂,不推荐高并发场景。


⭐分布式事务

有哪些分布式事务解决方案?

强一致性方案(牺牲性能,保证 ACID):

方案原理优缺点
2PC(两阶段提交)准备阶段 + 提交阶段简单,但同步阻塞、存在单点故障
3PC(三阶段提交)CanCommit + PreCommit + DoCommit解决部分单点问题,复杂度高
TCCTry(预留)+ Confirm(确认)+ Cancel(撤销)高性能,但侵入性强,需手写补偿逻辑

最终一致性方案(性能好,异步保证):

方案原理适用场景
本地消息表 + MQ事务提交时写本地事件表,定时任务发到 MQ异步流程、非实时
MQ 事务消息RocketMQ 提供的半消息机制,事务提交后消息才投递跨服务的最终一致
最大努力通知业务方尽力发送通知,允许失败重试 N 次后放弃对一致性要求不高的通知场景

2PC(两阶段提交)详解

阶段一:准备(Prepare)
  事务管理器 → 向所有参与者发送 Prepare
  参与者     → 开启本地事务,执行 SQL,不提交;返回 Ready/No

阶段二:提交(Commit / Rollback)
  若所有参与者返回 Ready → 事务管理器发送 Commit
  若任意参与者返回 No    → 事务管理器发送 Rollback

缺点:

  1. 同步阻塞:Prepare 阶段资源被锁定,其他事务等待
  2. 单点故障:事务管理器宕机,参与者一直阻塞
  3. 数据不一致:Commit 消息发出后部分节点宕机,只有部分节点提交

3PC(三阶段提交)详解

在 2PC 基础上增加 CanCommit(询问) 阶段,并引入超时机制(超时默认提交/中断),降低阻塞风险:

阶段一 CanCommit:询问是否可以执行事务(无锁定操作)
阶段二 PreCommit:锁定资源,执行 SQL(同 2PC 的 Prepare)
阶段三 DoCommit:正式提交

2PC 和 3PC 最终仍可能因网络问题导致不一致,需人工补偿(SQL 脚本检查)。

TCC 模式详解

TCC 适合有非数据库资源参与(如 Redis、文件系统、第三方接口)的场景。以"下单扣库存"为例:

Try 阶段(资源预留):
  - 创建订单,状态标记为"未提交"
  - 检查库存是否充足
  - 冻结 N 件库存(其他业务不可使用)

Confirm 阶段(确认提交):
  - 将订单状态改为"已提交"
  - 冻结库存正式扣减

Cancel 阶段(撤销补偿):
  - 删除未提交的订单
  - 解冻被冻结的库存

TCC 三大问题:

问题说明解决方案
幂等性Confirm/Cancel 可能被重复调用在事务记录表中记录执行状态,重复调用直接返回
空回滚Try 未执行,Cancel 却被调用Cancel 时判断 Try 是否执行过,未执行则直接返回
悬挂(防悬挂)Cancel 先于 Try 执行,Try 之后才执行造成资源永久冻结Cancel 执行后在事务记录表插入标记,Try 发现标记则拒绝执行

Seata 各模式对比

对比项AT 模式TCC 模式XA 模式
一致性最终一致性最终一致性强一致性
性能中等(有全局锁)高(无全局锁)差(资源长期锁定)
侵入性低(自动生成回滚 SQL)高(需手写 Try/Confirm/Cancel)低
适用场景依赖关系型数据库的业务高并发、有非 DB 资源参与现有 XA 兼容数据库
整合方式@GlobalTransactional + undo_log 表@LocalTCC + 三个阶段接口@GlobalTransactional

AT 模式核心原理(2PC 改良版):

区别于传统 XA:AT 模式不长期锁定资源,而是"乐观锁 + 快照回滚":

1. 执行前:生成 before image(数据快照)
2. 直接执行 SQL 并提交本地事务(释放资源)
3. 执行后:生成 after image,申请全局行锁,写入 undo_log
4. 全局提交成功 → 删除 undo_log
   全局回滚     → 用 before image 覆盖当前数据

本地消息表 + MQ 模式

适合异步、无需实时完成的跨服务流程(如 A → B → C 三个步骤):

核心思想:
  - 每个服务维护一张本地事件表(与业务表同库,保证本地事务)
  - 定时任务将事件表中待发送的消息投递到 MQ
  - 下游服务消费 MQ,处理完后再发布自己的事件
  - 若失败则发布失败事件,上游监听并回滚

保证幂等:为每个事件分配唯一 ID,消费时先判断是否已处理

⭐分布式数据库(分库分表)

什么时候需要分库分表?

  • 单表行数超过 1000 万条或数据量超过 100GB
  • 写操作频繁导致锁竞争严重
  • 单机数据库的 CPU/内存/磁盘到达瓶颈

垂直切分 vs 水平切分

垂直切分(按功能划分):

类型说明优点缺点
垂直分库按业务模块将表分到不同数据库(订单库、用户库)业务清晰,解耦跨库 JOIN 复杂,需处理分布式事务
垂直分表将宽表中频繁访问的字段和不常用字段拆分减少 I/O,提升热数据查询性能增加查询复杂度

水平切分(按数据行分散):

类型说明优点缺点
库内分表同一库中将数据拆分到多张结构相同的表(order_0, order_1)简单仍受单机限制
分库分表数据分散到不同机器的不同表中突破单机上限复杂度最高

数据分片(Sharding)策略

策略原理优点缺点
范围分片按 ID/时间范围划分(如 0-100w 一片)扩容方便,冷热数据分离可能存在热点分片
Hash 取模shard_id = hash(key) % N数据均匀分布扩容时需迁移大量数据
一致性 Hash环形 Hash,节点变化只影响相邻范围扩容时迁移数据少实现复杂

分库分表带来的问题及解决方案

问题解决方案
跨库 JOIN全局表(字典表)、字段冗余、应用层数据组装、ER 分片
分布式事务Seata、XA 事务、MQ 最终一致
跨分片分页/排序各分片独立查询后内存排序(成本高),或使用 ES 存索引
全局唯一 ID雪花算法(Snowflake)、Redis INCR、Leaf(美团)、UUID(不推荐)
数据迁移双写策略:新旧表同时写,逐步迁移并验证

常用分库分表中间件:

中间件简介
ShardingSphere当当出品,功能最全,含 JDBC、Proxy 两种接入方式
Mycat阿里系,代理模式,需独立部署
TDDL阿里内部,Druid + 分片规则
Last Updated: 6/26/26, 3:05 AM
Contributors: dongyz8, Fun_zil