1. 概述
在本教程中,我们将学习分布式系统的基本概念。文章将介绍分布式系统的核心特征、面临的挑战以及常见解决方案。
我们还将简要了解一些流行分布式系统的设计思路,涵盖多个类别。
2. 基本概念
在深入理解不同系统的分布式架构之前,我们先回顾一些基础概念。
虽然不同系统的动机各异,但它们在设计上面临许多共性挑战。
2.1. 什么是分布式系统
分布式系统由多个组件组成,这些组件可能分布在不同的地理位置,通过消息传递进行通信和协调。对外部使用者来说,它看起来像是一个统一的整体系统:
我们有时会混淆“去中心化系统(Decentralized System)”和“分布式系统(Distributed System)”。去中心化系统是一种特殊的分布式系统,其中没有单一组件掌握决策权。每个节点都有部分决策权,但没有节点掌握全部信息,因此任何决策都需要节点之间达成某种共识。
还有一个相关术语是“并行系统(Parallel System)”。虽然两者都旨在提升计算能力,但实现方式不同:
- 并行计算:使用一台机器上的多个处理器同时执行任务,可能共享内存。
- 分布式计算:使用多个独立机器,无共享内存,通过消息传递通信。
2.2. 分布式系统的优势
尽管分布式系统在设计和实现上更复杂,但它带来的好处也非常显著:
✅ 可扩展性:垂直扩展受限于硬件限制(如CPU核心数),而分布式系统理论上可以通过廉价的通用服务器实现无限水平扩展。
✅ 可靠性:数据在多个节点上复制,即使部分节点失效,系统仍可继续运行。
✅ 性能:通过将任务拆分到多个节点并行执行,显著提升复杂任务的处理性能(如矩阵运算)。
2.3. 分布式系统的挑战
当然,分布式系统也带来不少挑战:
❌ 一致性 vs 可用性:根据 CAP 定理,分布式系统必须在一致性和可用性之间做出权衡。
❌ 数据分布:需要将数据或任务分区并分发到多个节点,这需要复杂的算法来高效完成分区与合并。
❌ 协调机制:为实现容错,数据通常在多个节点上复制,节点之间需要复杂的协议来达成一致决策。
在企业级应用中,我们常常需要在事务中执行多个操作(如数据库更新)。在数据集中式场景下这很容易实现,但在分布式环境中就变得复杂。许多系统通过 Paxos、Raft 等协议实现分布式事务语义。
3. 架构与分类
虽然近年来分布式系统重新受到关注,但其基本原理并不新鲜。多年来,分布式系统已经发展出多种架构模式来应对不同场景下的数据处理需求。
本节将介绍一些常见的分布式系统架构模式及其适用场景。
3.1. 分布式系统架构
分布式系统的架构取决于其使用场景和预期目标。但总体来看,有以下两种核心架构模型:
- 主从架构(Master-Slave):一个节点作为主节点,掌握全部信息并负责决策。其余节点为从节点,执行主节点分配的任务。为了容错,主节点可以有备用节点。
- 对等架构(Peer-to-Peer):没有单一主节点,所有节点平等分担主节点的职责。也称为多主架构或多主架构。虽然通信开销和复杂度更高,但系统更具弹性。
实际中,很多系统采用混合架构,结合主从与对等架构的优点。例如,使用对等架构实现数据分布,使用主从架构实现数据复制。
3.2. 分布式系统分类
根据使用场景,我们可以将分布式系统分为以下几类(非穷举):
✅ 数据存储(Datastores)
✅ 消息队列(Messaging)
✅ 计算框架(Computing)
✅ 账本系统(Ledgers)
✅ 文件系统(File-systems)
✅ 应用服务(Applications)
传统关系型数据库逐渐难以满足现代数据的“三V”要求(Volume, Variety, Velocity),于是 NoSQL 数据库凭借其分布式架构崭露头角。
同样,传统消息系统也难以应对现代数据规模,因此分布式消息系统(如 Kafka)应运而生,提供高性能、可扩展和持久化能力。
4. Apache Cassandra
Cassandra 是一个开源的分布式键值系统,采用分区宽列存储模型。它支持多主复制,提供高可用性和低延迟,可线性扩展且无单点故障。
Cassandra 强调高可用性和可扩展性,因此它是一个最终一致性数据库。所有数据更新最终会传播到所有副本,但短期内可能有不一致的版本存在。Cassandra 提供可调一致性级别,允许用户在读写操作时选择不同的一致性策略。
4.1. 数据分布
Cassandra 通过将数据均匀分布到集群中的各个节点实现水平扩展。它使用一致性哈希(Consistent Hashing)来解决节点增减时的重新哈希问题。
一致性哈希的核心是一个虚拟环(Token Ring),表示整个哈希值范围:
每个节点映射到一个或多个 Token 上,数据通过哈希 Key 得到 Token,然后顺时针找到最近的节点,该节点即为此 Key 的拥有者。
Cassandra 还通过复制分区到多个物理节点来实现容错。支持插件式复制策略(如 Simple Strategy 和 Network Topology Strategy)。
4.2. 协调机制
Cassandra 是多主架构,每个节点都可以独立处理读写请求。接收请求的节点作为协调者(Coordinator),负责查找数据所在的节点。
Cassandra 使用 Gossip 协议传播节点状态信息:
Gossip 是一种点对点通信协议,节点定期与其他节点交换状态信息,并使用向量时钟来忽略旧的状态版本。
为解决并发写入冲突,Cassandra 使用 Last-Write-Wins(LWW)模型,每个更新操作都带有时间戳,最新的版本获胜。
5. MongoDB
MongoDB 是一个开源、通用、文档型分布式数据库,以文档为基本存储单元,支持嵌套文档和数组等复杂结构。
MongoDB 支持分片部署,每个分片可以配置为副本集。主副本处理所有写请求,在自动故障转移期间分片不可用,因此 MongoDB 默认是强一致性的。但客户端也可以选择从副本读取,此时数据是最终一致的。
5.1. 数据分布
MongoDB 使用 分片键 将集合中的文档分布到多个分片上。分片键可以由文档中的一个或多个字段组成,其选择直接影响性能、效率和扩展性。
MongoDB 支持两种分片策略:
✅ 哈希分片(Hashed Sharding):对分片键值哈希后分配到不同分片。
✅ 范围分片(Range Sharding):根据分片键值的范围进行分区。
MongoDB 默认每个分片块大小为 64MB。当块超过大小或文档数量限制时,MongoDB 会根据分片键拆分块。系统还运行一个 Balancer 进程 自动迁移分片块以实现均衡。
MongoDB 支持 Zone 概念,用于优化数据本地性,特别适用于跨数据中心部署的场景。
5.2. 协调机制
MongoDB 的分片集群由以下组件组成:
- Shard:数据分片,可部署为副本集
- Mongos:查询路由
- Config Server:元数据和配置信息存储
副本集通过 异步复制 oplog 实现高可用和数据冗余。当主节点失联时,一个从节点可以发起选举成为新主节点。
为减少数据丢失风险,MongoDB 提供 Write Concern 机制。设置为“majority”时,写操作需在多数节点上确认。
6. Redis
Redis 是一个开源的数据结构存储系统,可作为数据库、缓存甚至消息中间件使用。它支持字符串、列表、哈希等多种数据结构,主要基于内存,支持持久化。
Redis 使用主从架构实现高可用,主节点处理写请求,从节点异步复制数据。客户端可通过 WAIT
命令请求同步复制。
Redis 倾向于可用性和性能,而非强一致性。
6.1. 数据分布
Redis 通过将数据分片到多个实例实现水平扩展。支持多种分区方式:
- 范围分区(Range Partitioning)
- 哈希分区(Hash Partitioning)
Redis Cluster 是推荐的分片方案,使用 16384 个哈希槽(Hash Slot),每个节点负责一部分哈希槽。
Redis Cluster 结合了客户端分区和查询路由,自动将请求重定向到正确的节点。
6.2. 协调机制
Redis Cluster 使用 TCP 总线和 Redis Cluster Bus 协议 实现节点间通信,并使用 Gossip 协议传播集群状态信息。
Redis Cluster 采用 异步复制,因此存在写安全窗口。使用“Last Failover Wins”机制,最终以新主节点数据为准。
客户端可以向任意节点发送请求,节点会将请求重定向到正确的节点。随着客户端获取最新的集群信息,最终可以直接访问目标节点。
7. Apache Kafka
Kafka 是一个开源平台,用于构建高吞吐、低延迟的实时数据流系统。支持发布/订阅、持久化存储、实时处理等能力。
Kafka 通过在多个节点上复制数据实现高可用和持久化。只有所有副本都收到消息后,才认为消息提交成功。Kafka 设计上倾向于高一致性和可用性,并提供丰富的配置选项。
7.1. 数据分布
Kafka 将事件组织为主题(Topic),每个主题可以划分为多个分区(Partition),分布在不同节点上,实现并行读写:
每个分区是一个只追加的日志,事件通过偏移量(Offset)唯一标识。Kafka 按配置时间保留事件。
生产者可控制事件写入的分区,消费者可从任意偏移点读取事件。Kafka 支持消费者组(Consumer Group)机制,自动在组内分配分区。
7.2. 协调机制
Kafka 集群由多个 Broker 组成,使用高性能 TCP 协议通信。ZooKeeper 用于存储元数据(如分区位置、主题配置):
每个分区有主副本(Leader)和多个从副本(Follower)。写入和读取都通过 Leader 处理。Leader 负责更新副本数据。主副本失效时,一个从副本自动接管。
Kafka 定义 In-Sync Replica(ISR):能维持与 ZooKeeper 会话且未严重落后 Leader 的副本。写操作只有在 ISR 中所有副本都收到后才算提交。
Kafka 支持多种消息投递语义(At Most Once、At Least Once、Exactly Once)。通过配置 acks
、min.insync.replicas
等参数控制生产端语义,通过 enable.auto.commit
等控制消费端语义。
8. CAP 定理简介
CAP 定理由 Eric Brewer 提出,定义了分布式系统在一致性、可用性和分区容忍性之间的权衡。
CAP 定理指出,分布式系统最多只能同时满足以下三项中的两项:
✅ 一致性(Consistency):每次读操作都能获得最新的写操作结果或错误
✅ 可用性(Availability):每次读操作都能获得非错误响应(但不保证是最新的)
✅ 分区容忍性(Partition Tolerance):网络部分失效时系统仍能继续运行
由于网络分区几乎无法避免,因此实际中分布式系统必须在一致性与可用性之间做出权衡。宣称自己是“CA”系统的分布式系统,必须对其网络环境有高度信心。
但正如我们看到的,很多系统提供了丰富的配置选项,允许用户根据需求灵活选择行为。因此,简单地将系统归类为 CP 或 AP 是不准确的。
9. 总结
本教程我们介绍了分布式系统的基础知识,包括其核心优势、挑战以及一些主流系统的实现方式。
我们重点分析了它们在分布式架构中如何实现数据分布和协调机制。
理解这些系统的设计理念,有助于我们在实际项目中做出合理的技术选型。