写在前面
本系列博文为博主在学习《高阶分布式系统》这门课的过程中写就。目的有二,第一是记录自己学习分布式系统的过程和心得,为后续从事分布式系统或者并行计算相关的研究打下较为夯实的基础。第二则是锻炼自己的逻辑与写作。本系列博文的写作目标不是教科书式一板一眼的教学,而是一种介绍和导引。主要参考的写作应当是牛津大学出版社的“牛津通识读本”系列或者吴军博士所著的《数学之美》与《浪潮之巅》等。
本系列博文主要包括以下内容:
- 课堂内容笔记的整理(Lecture Notes)
- 论文精读(Paper Review)
- 作业记录(Homework)
- 课程项目的构思和实现(Course Project)
如果要评选世界上分布式系统建设的最好的公司,那么谷歌公司一定榜上有名。谷歌公司的业务遍布全球,其搜索服务能够为世界上任何一处使用它的用户提供相似的体验,并且底层提供计算能力的机器也不是现今最先进的超级计算机,这都要归功于谷歌建立的规模庞大的分布式基础设施。图1是一个非常简化的谷歌的技术分层架构,在用户直接使用的各种谷歌服务和底层提供计算能力的计算平台之间,有着一个不可忽视的分布式系统基础设施。
谷歌的Map/Reduce执行流程
从用户的视角来看,使用谷歌的搜索服务只需要在谷歌搜索主页的搜索框中输入搜索关键词,然后经过几毫秒到几百毫秒不等的时间,便可以获得搜索的结果。然而,表面上看似简单快速的搜索过程,在谷歌的服务器中执行的过程可一点都不简单,这背后的一整套流程由被称作Map Reduce的技术来支持。从概念上来说,在分布式系统的层面,用户的查询进程(就是浏览器)会向三个部分的分布式节点fork这个查询请求(如果不了解fork的读者可以简单的理解为用户发送给了服务器查询请求),分别是master节点(主节点)、负责map的节点(map节点)和负责reduce的节点(reduce节点)。主节点收到用户的查询请求之后,会为map节点分配查询任务,每一个map节点只负责对一部分数据的查询,这样多个map节点可以并行地对整个数据库进行查询,从而提高效率。每个map节点对自己负责的数据查询完毕之后,会将查询到结果写入本地的磁盘的中间文件里,供reduce节点读取。reduce节点在map节点查询完成后就通过网络远程读取map节点形成的中间文件,去到各个map节点的查询结果并作合并和排名等后处理操作,最终写入到输出文件中,返回给用户查询结果。图2展示了整个Map Reduce的流程。
什么是分布式系统?——一个没有回答完的问题
到这里我们或许可以通过上述场景思考一个十分重要的问题了,即什么是分布式系统?谷歌的Map Reduce系统当然算是一个分布式系统,我们能从中总结出来一些什么特点,将其作为分布式系统的定义呢?比如有多个节点,它们相互协作,等等。而这只是从系统本身的角度来看的,如果从用户的角度来看,用户肯定不希望每次查询的时候都要看一遍上述的执行流程,因此,对于用户来说,分布式系统应该表现得像是一台计算机一样。而从系统的角度来说,主节点、map节点和reduce节点都必须做到相互配合协作才能够准确无误的完成上述流程,这其中就涉及到非常多复杂的因素了。
那分布式系统有没有一个完整的定义呢?事实上,许多分布式系统领域的学者和大咖都曾在自己的著作中尝试为分布式系统下一个定义,比如Distributed systems principles and paradigms一书的作者Andrew Tanenbaum给出的定义是“A distributed system is a collection of independent computers that appear to the users of the system as a single computer.”,而Needham–Schroeder协议的发明人Michael Schroeder给出的定义则是“A distributed system is several computers doing something together. Thus, a distributed system has three primary characteristics: multiple computers, interconnections, and shared state.”尽管上述定义都从某些方面描述了分布式系统的特质,但是没有任何一个能够说服大家,成为一个公认的完美的定义。
我相信,随着学习的深入,每个人心中都会有一个属于自己的完美的分布式系统的定义。但是在本系列博文中,一个大致可以概括我们所讨论的内容的定义或许是这样的。它概括了我们即将讨论的若干议题。
A distributed system is a collection of entities, each of which is autonomous, programmable, **asynchronous **and failure-prone, and which communicate through an **unreliable **communication medium.
一个分布式系统是一组实体的集合,这组实体是自治的、可编程的、异步的和能够容错的,并且通过不可靠的媒介进行通信。这个定义给出了分布式系统应当满足的一些基本的特点,目前我们生活中接触绝大多数分布式系统都满足这些特点。
所谓自治,指的是每一个实体都可以决定是否加入到分布式系统的工作任务或者决策中来而不受到其他实体的影响,而可编程,则表示每个实体都可以根据自己的逻辑和配置运行,异步性则更多讨论的是通信,即通信可以在任意时刻发生,且不保证消息的最重可达,也不保证消息到达的时间上限,能够容错则比较好理解,即如果分布式系统中的一些实体崩溃或者因为网络问题失去了联系,这个分布式系统仍能够正常工作。不可靠的通信媒介意味着实体之间的消息传递可能会出现丢失、延迟、重复或顺序错乱等问题。这就是分布式系统自身需要满足的要求和必须面临的不可靠的环境。在这些看似合情合理却又十分苛刻的条件下,构建一个能够正常稳定运行的分布式系统,并不是一件简单的事情。
分布式系统设计的目标
前文大致描述了分布式系统应该是什么样的,这一部分详细介绍一下设计分布式系统的目标。总的来说,设计一个分布式系统,需要考虑九个方面的指标。它们分别是鲁棒性、可用性、透明性、异质性、并发、高效、可扩展性、安全性和开放性。遗憾的是,目前没有任何一种分布式系统能够在上述九个目标上全部达到较好的表现。很多指标之间甚至是存在冲突的,比如安全性和开放性,鲁棒性和可扩展性等等。以我们熟知的分布式系统——互联网为例,互联网的设计目标就只有一个,那就是可扩展性,而其他的指标对于互联网而言,都是尽可能做(best effort)。下面分别介绍这九大目标的具体含义。
- 鲁棒性:系统是否能适应节点的故障甚至崩溃,或者信道中消息的丢失?
- 可用性:数据和服务是否总是能够获取
- 透明性:用户是否对分布式系统的工作过程有所感知?
- 异质性:系统是否能够容纳不同类型的节点(比如设备)?
- 并发:服务器是否能够同时处理多个客户端的请求?
- 高效:系统是否足够快?
- 可扩展性:系统是否能够容纳足够多的节点?
- 安全性:系统是否能够抵御攻击?
- 开放性:系统是否能够接纳新的服务或者设备的接入?
这里值得一提的是,虽然互联网在设计的时候就只考虑扩展性,但是我们知道,计算机网络是分层的架构,在不同的层次可以保证不同的性质,而这是通过不同的协议来保证的,比如大家熟知的TCP协议和UDP协议,这是两个传输层协议,但是设计的目标却不一样。TCP协议尽可能保证鲁棒性和可用性,即总是让对方确定收到了消息,而UDP协议则牺牲掉了鲁棒性转而追求高效。这也是为什么对实时性要求高的应用会在传输层选择UDP协议的原因,这其中其实没有什么优劣次第,只是对不同应用有相应的取舍(trade-off)而已。
总结
- 谷歌的map reduce
- 分布式系统的一种定义
- 分布式系统的设计目标