分布式
分布式
分布式理论
介绍一下 CAP 理论
CAP 原则又称 CAP 定理, 指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性), 三者不可同时满足。
- 一致性(C) : 在分布式系统中的所有数据备份, 在同一时刻是否同样的值(等同于所有节点访问同一份最新的数据副本)。
- 可用性(A): 在集群中一部分节点故障后, 集群整体是否还能响应客户端的读写请求(对数据更新具备高可用性)。
- 分区容忍性(P) 以实际效果而言, 分区相当于对通信的时限要求. 系统如果不能在时限内达成数据一致性, 就意味着发生了分区的情况, 必须就当前操作在 C 和 A 之间做出选择。
TIP
面试常见问题。
Q:为什么分布式系统必须选择 P?
A:网络分区是物理世界必然现象(光速限制/设备故障)。
Q:BASE 理论与 CAP 的关系?
A:BASE(Basically Available, Soft-state, Eventually consistent)是AP系统的具体实现方法论。
Q:如何设计 CP 系统的可用性补偿?
A:通过:1) 客户端缓存 2) 降级策略 3) 只读副本实现服务连续性。
介绍一下 BASE 理论
BASE 理论强调分布式系统的基本可用性(Basically Available)、允许中间软状态(Soft state)和最终一致性(Eventual consistency),是对传统 ACID 强一致性要求的补充,更适合高可用、大规模分布式场景。
分布式锁
用 Redis 怎么实现分布式锁?
分布式锁是用于分布式环境下并发控制的一种机制,用于控制某个资源在同一时刻只能被一个应用所使用。
Redis 实现分布式锁见 Redis 小节内容。
还有没有其他方法实现分布式锁?
还可以基于 Zookeeper 来实现分布式。
Zookeeper 实现分布式锁见 Zookeeper 小节内容。
分布式事务
2 PC
两阶段提交(Two-Phase Commit,简称 2PC)是一种经典的分布式一致性协议,用于确保分布式事务的原子性。它通过协调者(Coordinator)和参与者(Participant)的交互,保证所有参与节点要么全部提交事务,要么全部回滚事务。
协议流程
第一阶段:准备阶段。
- 协调者向所有参与者发送"准备请求"(Prepare)。
- 每个参与者执行事务操作但不提交,记录 undo/redo 日志。
- 参与者向协调者反馈响应。
- 3.1 成功(Yes):事务可以提交。
- 3.2 失败(No):事务需要中止。
第二阶段:提交/中止阶段。
- 协调者根据参与者反馈决定。
- 1.1 如果所有参与者都返回 Yes:发送"提交命令"(Commit)。
- 1.2 如果有任一参与者返回 No 或超时:发送"回滚命令"(Abort)。
- 参与者根据协调者指令执行提交或回滚操作。
- 参与者完成操作后向协调者发送确认(Ack)。
优缺点
- 优点
- 保证了分布式事务的原子性(All-or-Nothing)
- 概念简单,易于理解和实现
- 适用于需要强一致性的场景
- 缺点
- 同步阻塞:参与者需要等待协调者指令,期间资源被锁定
- 单点故障:协调者故障会导致系统阻塞
- 数据不一致风险:在第二阶段,如果部分参与者收不到指令会导致不一致
- 性能开销:需要多次网络通信和日志记录
实际应用。2PC常用于数据库分布式事务处理,如。
- XA 协议(数据库层面的分布式事务)。
- 某些消息队列的事务消息实现。
- 早期的分布式系统设计。
现代分布式系统通常会结合其他协议(如 3PC)或采用最终一致性模型来避免 2PC 的缺点。
3 PC
3PC(Three-Phase Commit)作为 2PC 的改进版本,在实际分布式系统中较少直接使用,但它的思想影响了多种分布式一致性方案。以下是主要的 3PC 实现和变种方案。
标准 3PC 协议
典型实现:CanCommit、PreCommit、DoCommit 三阶段。
特点。
- 增加预提交阶段解决 2PC 的阻塞问题。
- 超时机制允许参与者自主终止事务。
缺点。
- 网络分区时仍可能不一致。
- 实际工程实现复杂度高。
类 3PC 的改进方案
方案 | 原理 | 典型系统/框架 |
---|---|---|
Paxos | Commit | 基于Paxos算法实现三阶段提交 Google Spanner底层设计 |
ZooKeeper | ZAB | 两阶段提交+崩溃恢复阶段 ZooKeeper |
TCC模式 | Try-Confirm-Cancel三阶段 | 金融支付系统 |
SAGA+超时控制 | 执行-补偿-校验三阶段机制 | 长事务业务流程 |
分布式事务的解决方案
方案 | 事务类型 | 一致性 | 性能 | 复杂度 | 适用场景 | 代码侵入性 | 补充说明 |
---|---|---|---|---|---|---|---|
2PC | 2 PC | 强一致性 | 低 | 中 | 传统数据库、短事务 | 无侵入(数据库层实现) | 存在同步阻塞,单点问题 |
3PC | 2 PC | 最终一致性 | 中 | 高 | 对可用性要求较高的场景 | 无侵入(数据库层实现) | 解决 2PC 阻塞问题,但仍有数据不一致风险 |
TCC | 类 3 PC,补偿性事务 | 最终一致性 | 中 | 高 | 高并发短事务(支付、订单) | 高侵入(需改业务代码实现三阶段) | 需业务实现 Try/Confirm/Cancel |
SAGA | 类 3 PC,补偿性事务 | 最终一致性 | 高 | 中 | 长事务、跨服务业务流程 | 中高侵入(需实现正向/补偿接口) | 需提供补偿机制,可能脏读 |
消息队列 | 类 3 PC,补偿性事务 | 最终一致性 | 高 | 中 | 异步场景(订单创建、库存扣减) | 中侵入(需发消息+消费逻辑) | 依赖消息可靠性,可能重复消费 |
本地消息表 | 类 3 PC,补偿性事务 | 最终一致性 | 中 | 低 | 中小规模系统,数据库和 MQ 结合的场景 | 低侵入(仅需维护消息表) | 需维护消息状态表 |
AT 模式 | 类 3 PC,补偿性事务 | 弱一致性 | 高 | 低 | Seata 框架用户,简单业务 | 无侵入(代理 JDBC) | 无侵入但依赖全局锁 |
XA 协议 | 2 PC | 强一致性 | 低 | 中 | 传统金融系统(银行核心业务) | 资源锁定时间长 |
一些说明如下。
- TCC 虽然有三阶段,但不属于标准 3PC 协议。
- XA 协议本质是基于 2PC 实现的。
- 其他方案(SAGA、消息队列等)属于补偿型事务。
关键对比维度说明。
- 一致性:强一致性(如 XA/2PC) vs 最终一致性(如 TCC/SAGA)。
- 性能:受锁机制、同步阻塞影响(2PC 最差,SAGA/消息队列最优)。
- 复杂度:TCC 需业务改造,SAGA 需设计补偿,本地消息表最简单。
- 适用场景:根据业务特性选择(短事务用 TCC,长事务用 SAGA)。
高频面试考点。
- 2PC:同步阻塞是致命缺点。
- TCC:空回滚、幂等、悬挂问题。
- SAGA:必须实现补偿事务。
- 消息队列:如何保证可靠投递(事务消息+本地表)。
阿里的 Seata 框架了解过吗?
Seata 是开源分布式事务解决方案,支持多种模式。
- AT 模式:是 Seata 默认的模式,基于支持本地 ACID 事务的关系型数据库。在 AT 模式下,Seata 会自动生成回滚日志,在业务 SQL 执行前后分别记录数据的快照。当全局事务需要回滚时,根据回滚日志将数据恢复到事务开始前的状态。
- TCC 模式:需要开发者手动编写 Try、Confirm 和 Cancel 三个方法。Try 方法用于对业务资源进行预留,Confirm 方法用于确认资源并完成业务操作,Cancel 方法用于在业务执行失败时释放预留的资源。
- SAGA 模式:将一个长事务拆分为多个短事务,每个短事务都有一个对应的补偿事务。当某个短事务执行失败时,会按照相反的顺序执行之前所有短事务的补偿事务,将系统状态回滚到初始状态。
分布式组件
RPC 的概念是什么?
RPC 即远程过程调用,允许程序调用运行在另一台计算机上的程序中的过程或函数,就像调用本地程序中的过程或函数一样,而无需了解底层网络细节。
一个典型的 RPC 调用过程通常包含以下几个步骤。
- 客户端调用:客户端程序调用本地的一个 “伪函数”(也称为存根,Stub),并传入所需的参数。这个 “伪函数” 看起来和普通的本地函数一样,但实际上它会负责处理远程调用的相关事宜。
- 请求发送:客户端存根将调用信息(包括函数名、参数等)进行序列化,然后通过网络将请求发送到服务器端。
- 服务器接收与处理:服务器端接收到请求后,将请求信息进行反序列化,然后找到对应的函数并执行。
- 结果返回:服务器端将函数的执行结果进行序列化,通过网络发送回客户端。
- 客户端接收结果:客户端接收到服务器返回的结果后,将其反序列化,并将结果返回给调用者。
常见的 RPC 框架。
- gRPC:由 Google 开发的高性能、开源的 RPC 框架,支持多种编程语言,使用 Protocol Buffers 作为序列化协议,具有高效、灵活等特点。
- Thrift:由 Facebook 开发的跨语言的 RPC 框架,支持多种数据传输协议和序列化格式,具有良好的可扩展性和性能。
- Dubbo:阿里巴巴开源的高性能 Java RPC 框架,提供了服务治理、集群容错、负载均衡等功能,广泛应用于国内的互联网企业。
Zookeeper 拿来做什么-核心的原理是什么
Zookeeper 是分布式协调服务,它能很好地支持集群部署,并且具有很好的分布式协调能力,可以让我们在分布式部署的应用之间传递数据, 保证顺序一致性(全序广播) 而不是 强一致性,以下是其常见的应用场景。
- 配置管理:在分布式系统中,不同节点往往需要相同的配置信息,如数据库连接参数、服务端口等。ZooKeeper 可以将这些配置信息集中存储,当配置发生变更时,能及时通知到各个节点。例如,一个由多个微服务组成的系统,各个服务实例可以从 ZooKeeper 中获取统一的配置,当配置更新时,ZooKeeper 会通知所有相关服务重新加载配置。
- 服务注册与发现:服务注册与发现是微服务架构中的关键环节。服务提供者在启动时将自己的服务信息(如服务名称、地址、端口等)注册到 ZooKeeper 中,服务消费者通过 ZooKeeper 查找并获取服务提供者的信息。当服务提供者发生变化(如上线、下线、故障等)时,ZooKeeper 会实时更新服务列表并通知服务消费者。像 Dubbo 框架就可以利用 ZooKeeper 实现服务的注册与发现。
- 分布式锁:在分布式环境下,多个进程或线程可能会竞争同一资源,为了避免数据不一致等问题,需要实现分布式锁。ZooKeeper 可以通过创建临时顺序节点来实现分布式锁。当一个客户端需要获取锁时,它会在 ZooKeeper 中创建一个临时顺序节点,然后检查自己创建的节点是否是序号最小的节点,如果是,则表示获取到了锁;如果不是,则等待前一个节点释放锁。
ZooKeeper 的数据模型类似于文件系统的树形结构,每个节点称为 Znode。
每个 Znode 可以存储数据,也可以有子节点。Znode 有不同的类型,包括持久节点(PERSISTENT)、临时节点(EPHEMERAL)和顺序节点(SEQUENTIAL)。
- 持久节点:一旦创建,除非主动删除,否则会一直存在。
- 临时节点:与客户端会话绑定,当客户端会话结束时,临时节点会自动被删除。
- 顺序节点:在创建时,ZooKeeper 会为其名称添加一个单调递增的序号,保证节点创建的顺序性。
ZooKeeper 使用 ZAB 协议来保证集群中数据的一致性。ZAB 协议基于主从架构,有一个领导者(Leader)和多个跟随者(Follower)。
- 消息广播:当客户端发起写请求时,请求会先到达领导者。领导者将写操作封装成一个事务提案,并广播给所有跟随者。跟随者收到提案后,将其写入本地日志,并向领导者发送确认消息。当领导者收到超过半数跟随者的确认消息后,会发送提交消息给所有跟随者,跟随者收到提交消息后,将事务应用到本地状态机。
- 崩溃恢复:当领导者出现故障时,ZooKeeper 会进入崩溃恢复阶段。在这个阶段,集群会选举出新的领导者,并确保在新领导者产生之前,不会处理新的写请求。选举过程基于节点的事务 ID 和节点 ID 等信息,保证新选举出的领导者包含了所有已提交的事务。
分布式一致性算法
Raft 一致性协议原理
1.1 基本概念
Raft 是一种分布式一致性算法(Distributed Consensus Algorithm),用于管理复制日志(Replicated Log),保证多个节点间的数据一致性。相比 Paxos 更易理解和实现(Easier to Understand and Implement)。
1.2 核心特性
- 强领导者模式(Strong Leader):所有客户端请求都通过领导者处理
- 领导选举机制(Leader Election):通过投票机制选出领导者
- 日志复制机制(Log Replication):领导者将日志复制到所有跟随者
- 安全性保证(Safety):已提交的日志不会被覆盖
1.3 节点角色
角色(Role) | 职责描述(Description) |
---|---|
Leader | 处理所有客户端请求,管理日志复制 |
Follower | 被动响应领导者/候选者的请求 |
Candidate | 选举过程中的临时状态 |
1.4 关键机制
1.4.1 任期(Term)
- 逻辑时钟(Logical Clock),单调递增的整数
- 每个任期最多一个领导者
- 节点存储当前已知的最新任期
1.4.2 领导选举流程(Leader Election)
- 超时触发(Timeout):Follower 在选举超时(150-300ms 随机值)后成为 Candidate
- 发起投票(Request Vote):
- 自增当前任期
- 向其他节点发送 RequestVote RPC
- 投票规则(Voting Rules):
- 每个节点每任期只能投一票
- 候选者的日志至少要和投票者一样新(Log Completeness)
- 成为 Leader:获得多数票后转为 Leader,定期发送心跳(Heartbeat)维持权威
1.4.3 日志复制流程(Log Replication)
- 客户端请求(Client Request):Leader 将命令追加到本地日志
- 复制日志:通过 AppendEntries RPC 并行发送给所有 Followers
- 提交日志(Commit):
- 当多数节点复制成功后,Leader 提交日志
- 通知 Followers 可以提交(通过后续心跳或日志条目)
1.5 典型面试问题
Q:Raft 如何保证一致性(Consistency)?
A:通过强领导者模式、日志复制到多数节点后才提交、选举时校验日志完整性
Q:网络分区(Network Partition)时 Raft 如何工作?
A:原 Leader 在少数分区会无法提交日志,多数分区会选出新 Leader。分区恢复后,旧 Leader 会识别到更高任期并退位
Q:Raft 相比 Paxos 的优势?
A:更易理解和实现、强领导者简化系统设计、有明确的日志复制机制
Q:日志压缩(Log Compaction)如何实现?
A:通过快照(Snapshot)机制,将已提交的日志状态持久化后清除旧日志
Paxos 分布式共识算法原理
1.1 基本概念
Paxos 是一种分布式共识算法(Distributed Consensus Algorithm),用于在不可靠的节点网络中达成一致性(Agreement)。被广泛应用于分布式系统(Distributed Systems)的状态机复制(State Machine Replication)。
1.2 核心角色
- 提议者(Proposer):发起提案(Proposal)
- 接受者(Acceptor):对提案进行投票表决
- 学习者(Learner):学习最终确定的提案
1.3 算法阶段
1.3.1 准备阶段(Prepare Phase)
- 提议者选择全局唯一提案编号(Proposal ID)
- 向多数派接受者发送 Prepare(n) 请求
- 接受者承诺:
- 不再接受编号小于 n 的提案
- 返回已接受的最高编号提案(若有)
1.3.2 接受阶段(Accept Phase)
- 若收到多数派响应:
- 使用收到的最高编号提案值(Value)
- 或采用自己的提案值(若未收到历史提案)
- 发送 Accept(n, v) 请求给接受者
- 接受者接受提案需满足:
- 未响应过编号大于 n 的 Prepare 请求
1.3.3 学习阶段(Learn Phase)
- 当提案被多数派接受后
- 学习者(Learner)广播最终确定的提案值
1.4 关键特性
- 安全性(Safety):保证只有一个值被选定
- 活性(Liveness):最终能达成共识
- 多数派原则(Quorum):需要 ⌈N/2⌉+1 节点同意
1.5 典型问题
Q:Paxos 如何避免活锁(Livelock)?
A:通过随机超时(Randomized Timeout)和提案编号递增机制
Q:Multi-Paxos 优化了什么?
A:选举稳定领导者(Leader)后跳过准备阶段,提升性能
Q:Paxos 与 Raft 的主要区别?
A:Paxos 更抽象灵活,Raft 强调可理解性和实现友好性
Q:实际系统中如何应用 Paxos?
A:通常用于分布式存储系统(如 Chubby)的元数据管理
采用 Raft 协议的技术框架
1.1 分布式数据库
- etcd:分布式键值存储(Key-Value Store),Kubernetes 的默认存储后端
- TiDB:分布式 NewSQL 数据库,使用 Raft 管理数据分片(Region)
- CockroachDB:云原生分布式 SQL 数据库,多层级 Raft 实现
- YugabyteDB:兼容 PostgreSQL 的分布式数据库,Raft 用于共识层
1.2 分布式存储系统
- Consul:服务发现与配置系统,Raft 用于状态一致性
- NATS Streaming:消息队列系统,Raft 实现消息持久化
- MinIO:分布式对象存储,Raft 管理元数据(Metadata)
1.3 云原生技术栈
- Kubernetes:部分组件(如 kube-scheduler 的调度框架)使用 Raft 变种
- Docker Swarm:早期版本采用 Raft 管理集群状态
- Cloud Foundry:BOSH 部署工具使用 Raft 实现高可用
1.4 区块链与分布式账本
- Hyperledger Fabric:排序服务(Ordering Service)可选 Raft 实现
- Quorum:企业级以太坊客户端,Raft 共识模式选项
- Corda:金融分布式账本,部分版本使用 Raft 变体
1.5 开发框架与库
- HashiCorp Raft:Go 语言实现的标准 Raft 库
- Apache Ratis:Java 实现的 Raft 协议库
- Tikv:Rust 语言的 Raft 实现,被 TiDB 使用
1.6 特殊应用场景
- Netflix:用于分布式配置管理(Edda 项目)
- MongoDB:分片集群的配置服务器使用 Raft
- RabbitMQ:仲裁队列(Quorum Queues)基于 Raft 实现
1.7 技术选型对比
技术名称 | 应用场景 | Raft 实现特点 |
---|---|---|
etcd | 服务发现/配置存储 | 标准 Raft + 快照压缩 |
TiDB | 分布式事务 | Multi-Raft + Region 分裂 |
Consul | 健康检查与 DNS | 内存型 Raft 状态机 |
NATS Streaming | 消息持久化 | 优化写性能的 Raft 变种 |
1.8 典型面试问题
Q:为什么 etcd 选择 Raft 而非 Paxos?
A:Raft 更易实现且提供清晰的成员变更(Membership Change)机制
Q:TiDB 如何优化 Raft 性能?
A:通过批处理(Batching)和流水线(Pipelining)提升吞吐量
Q:Raft 在区块链中的局限性?
A:许可链场景适用,但无法满足公链的拜占庭容错(BFT)需求
Q:自研系统时该用现成 Raft 库还是自实现?
A:推荐使用成熟库(如 HashiCorp Raft),除非有特殊优化需求
分布式场景
常见的限流算法你知道哪些?
- 滑动窗口限流算法。
- 漏桶限流算法。
- 令牌桶算法。