本书写作缘由
在2017年,我参与了一个名为“Thirty Meter Telescope”(TMT)的大型光学望远镜软件系统的开发项目。我们的任务是构建供各个子系统使用的核心框架和服务。这些子系统组件必须能够相互发现与检测组件故障,并能够存储有关各组件的元数据。负责这些信息存储的服务必须是容错的。考虑到望远镜生态系统的特殊性,我们不能采用现成的产品和框架,只能从零开始,打造适用于不同软件子系统的核心框架和服务,从本质上说,我们要建立的是一个分布式系统。
我曾设计并构建过依赖于Kafka、Cassandra和MongoDB等产品的企业系统,它们使用AWS或GCP等云服务。这些产品和服务都是分布式的,解决了一系列相似的问题。对于TMT系统,我们必须自行开发解决方案。为了验证和比较这些成熟的产品,我们需要更深入地理解它们的内部机制。了解这些云服务和产品的构建方式及其背后的原因是必要的,它们的官方文档往往太过产品化,不利于达成我们的目标。
关于构建分布式系统的信息分散在各种研究论文中。然而,这些学术资源也有局限,它们往往只关注特定领域而忽略了相关主题。以“Consensus: Bridging Theory and Practice”(Ongaro,2014)这篇精彩的论文为例,它详细解释了实现Raft共识算法的过程。但你不会从中了解到像etcd这样的产品如何使用Raft来追踪集群成员资格和其他产品的相关元数据,如Kubernetes。Leslie Lamport的著名论文“Time, Clocks, and the Ordering of Events in a Distributed System”(Lamport,1978)中讨论了逻辑时钟的使用,但它并未解释像MongoDB这样的产品如何使用逻辑时钟作为版本号来控制数据的版本。
我相信编写代码是验证理解正确与否的最佳方式。正如Martin Fowler所说:“代码就像数学,我们必须消除其中的歧义。”因此,为了深刻理解分布式系统的基础模块,我决定自己动手构建这些产品的简化版本。我从打造一个玩具版的Kafka开始,一旦有了合理的版本,我就用它来探讨分布式系统的一些基本概念。这种方法被证明非常有效。为了验证通过代码来阐释概念的效果,我在Thoughtworks开展了一系列内部研讨会,这些研讨会对我帮助极大。因此,我将这种方法扩展到了Cassandra、Kubernetes、Akka、Hazelcast、MongoDB、YugabyteDB、CockroachDB、TiKV和Docker Swarm等产品。我提取了代码片段来理解这些产品的构建模块。果不其然,这些模块之间存在许多相似之处。几年前,我偶然与Martin Fowler讨论过这个话题,他建议我将其整理成模式。本书便是我与Martin Fowler合作,将分布式系统中的共通的构建模块整理成模式的成果。
本书读者
在当今软件架构和开发的选择丰富多样的背景下,面对众多分布式产品和云服务,架构师和开发者面临着复杂的设计抉择。这些产品和服务的设计折中可能难以直观理解。单凭阅读文档是远远不够的。比如,当我们考虑“AWS MemoryDB通过复制的事务日志确保了数据的持久性”“Apache Kafka现能独立于ZooKeeper运作”或者“Google Spanner通过同步的全球时间来维护外部一致性”这样的句子时,该如何理解这些技术性描述?
为了深入了解,专业人士往往依赖于产品供应商的认证培训。然而,这些认证大多局限于特定产品,关注的是表层特性,而非背后的技术原理。专业开发者需要对这些技术细节有直观的把握,既能具体到在源代码层面描述,又能通用到适应不同场景。这正是模式的价值所在。本书介绍的模式旨在帮助从业者深入理解各种产品和服务的内在机制,以便做出明智且有效的决策。
本书的主要读者将是这些专业人士。除了那些需要与现有的分布式系统打交道的人员,还有一部分读者可能需要构建自己的分布式系统。我期望本书中的模式能够为这些读者提供一些有价值的参考,并帮助他们领先一步。书中引用了许多不同产品的设计方案,这些信息对读者来说同样有益。
关于代码示例的说明
本书中大多数模式都提供了代码示例。这些代码示例建立在我研究这些模式时,对各种产品所做的微型实现基础之上。选择编程语言的依据是它的普及度和可读性—Java便是一个优秀的选择。示例中只用到了Java最基本的语言特性,即方法和类,这在大多数编程语言中都是通用的。即便是只熟悉其他编程语言的读者,也应该能够轻松地理解这些代码示例。不过,需要明确的是,本书并非专为某个具体的软件平台编写。一旦掌握了这些代码示例,你会发现无论是C++、Rust、Go、Scala还是Zig,其代码库中都有这些模式的影子。我期望的是,通过熟悉这些代码示例和模式,你将能更加轻松地阅读和理解各种开源产品的源代码。
阅读指南
本书共分为六部分。首先是两章叙述性章节,这些章节构成了第一部分,它们涵盖了分布式系统设计的基本主题,介绍了分布式系统设计中的挑战及其解决策略,但并未深入讨论这些策略的细节。
第二部分至第六部分提供了按模式结构化的详尽解决方案。这些模式被划分为四个核心类别:复制、分区、集群管理和网络通信。每一类都是构建分布式系统的关键要素。
请将这些模式当作一种参考手册,不需要逐字逐句地阅读。你可以先浏览叙述性章节,以获得对本书内容的整体理解,再根据个人兴趣和实际需求,深入研究各个模式。
我希望这些模式能够协助同行软件专业人员在工作中做出明智的决策。