本节书摘来自华章计算机《深入理解Hadoop(原书第2版)》一书中的第1章,第1.2节,作者 [美]萨米尔·瓦德卡(Sameer Wadkar),马杜·西德林埃(Madhu Siddalingaiah),杰森·文纳(Jason Venner),译 于博,冯傲风,更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1.2大数据技术背后的核心思想
上文中的例子我们作了诸多假设,要表明的核心问题是虽然我们可以很快地处理数据,但是从持久性的存储设备中读取的速度受到限制,这是整个数据处理流程上的关键瓶颈所在。相对于读写本地节点存储设备上的数据,通过网络来传输数据会更慢。
下面列出了所有大数据处理方法中的一些共同特征:
- 数据分布在多个节点(网络I/O速度<<本地磁盘I/O速度)。
- 计算程序离数据更近(集群上的节点),而不是相反。
- 数据的处理尽量在本地完成(网络I/O速度<<本地磁盘I/O速度)。
- 使用可顺序读取磁盘I/O代替随机读取磁盘I/O(数据交换速度<<数据寻道时间)。
所有大数据计算处理模式都有一个目的,就是使输入/输出(I/O)并行化,从而提高数据处理性能。
1.2.1把数据分发到多个节点
根据定义,大数据是无法仅靠单台计算机资源来处理的。大数据的一个特点就是使用商用服务器。一台典型的商用服务器拥有2TB至4TB的磁盘。因为大数据是指远远超出这个容量的数据集,所以还是要将数据分布在多个节点上。
需要注意的是,我们把要处理的数据分布存放在多个计算节点,并不是因为这些数据的数据量有数十T之巨。你会发现大数据处理系统会有条不紊地在各个计算节点上计算处理所分配的数据。把数据分布到各个服务器节点的最终目的是为了让大量计算节点同时参与到数据的处理计算过程中来。哪怕仅有500GB的数据集,这么大的数据量,集群中的单台计算节点完全可以存储,也会把数据分发到多台计算节点。这样的数据分发有两点好处:
- 每个数据块会在多个节点上有多份拷贝(Hadoop默认是一个数据块有3份拷贝),这使得系统具备容错性,当一个节点发生故障,其他节点还备份有故障节点上的数据。
- 为了达到数据并行处理的目的,多个节点可以同时参与数据处理过程。比如,50GB的数据被分配到10台计算节点,每个计算节点仅处理分配给自己的数据集,可以达到数据处理性能5~10倍的提升。读者可能会问,为什么不把这些数据存放到网络文件系统(NFS)中,这样每个节点可以去读取它要处理的部分。答案是本地存储磁盘的数据读取速度要远远高于通过网络来读取数据的速度。当数据分析任务启动的时候,分析任务程序运行所需的函数库被拷贝到各个计算节点,大数据处理系统会尽量在本地处理计算数据。我们会在后面章节中详谈。
1.2.2把计算逻辑移动到数据附近
对于我们这些精通J2EE编程的人来说,三层架构思想深植脑海。在三层编程模型中,所有的数据会通过网络集中到一起,交由应用层来处理。我们由此形成了固有的观念,就是数据应该是分散的,而程序应该是集中的。
大数据系统无法处理网络过载的问题。传输动辄数T的数据量给应用层,使得网络带宽耗尽,网络拥挤不堪,导致传输效率大幅下降,甚至有可能导致系统故障。从大数据的观念来看,应该把数据分布存放到各个计算节点,程序也要移动到数据附近。要做到这一点,是一件很不容易的事情。除了程序要移动到存放数据的节点,程序运行所依赖的函数库也要移动到数据处理节点才行。如果大数据系统的集群拥有数百个计算节点,显然那将是程序维护/部署人员的噩梦。所以,大数据系统可以让我们集中式地部署程序代码,大数据系统后台会在计算任务启动之前把这些程序移动到各个数据处理节点。
1.2.3计算节点进行本地数据处理
前文提到的大数据系统的两个特点,决定了分配到计算节点的数据要在计算节点本地处理。所有的大数据编程模型都是基于分布式和并行处理的。网络I/O比本地磁盘I/O慢了好几个数量级。数据被分发到各个计算节点,程序运行依赖库也移动到了数据所在节点,计算节点就地计算处理数据的条件完备了。
虽然典型的大数据处理系统都希望把数据处理过程放在拥有数据的节点本地完成,但并不是每次都能实现。大数据系统会把计算任务尽量调度到离数据最近的节点。本章节的后续部分会介绍一些内容,其中大数据系统中某些特定的处理任务需要跨节点获取数据。分布在各个计算节点的计算结果,最终要汇聚到一个计算节点(著名的MapReduce框架的Reduce阶段或其他海量数据并行化处理编程模型的类似阶段),起码这一步是需要跨节点获取数据的。但是,在大多数的用例场景下,数据结果汇集阶段的数据量,相对于计算节点本地处理的原始数据量来说是微不足道的。此过程的网络开销可以忽略不计(但也不总是这样)。
1.2.4优选顺序读,次之随机读
首先,你要理解数据是如何从磁盘上读取的。磁盘头首先要移动到所寻找的数据所在的磁盘位置。这个过程称为寻道(seek)操作,是需要花费很多时间的。一旦磁盘头移动到目的位置后,数据便被顺序地读取出来。这叫做数据的传输(transfer)操作。寻道时间大约需要10毫秒,数据传输速度量级为20毫秒(1MB),这意味着,如果我们从磁盘上彼此不相邻的1MB扇区来读取100MB数据,会花费10(寻道时间)×100(寻道100次)=1秒,再加上20(每兆数据传输所需时间)×100=2秒。读取100MB的数据总共需要3秒钟的时间。如果我们从磁盘上彼此相邻的扇区来顺序读取100MB数据,将花费10(寻道时间)×1(寻道100次)+20×100=2秒(译者注:此处应为2.01秒,疑为作者笔误)。读取100MB的数据总共需要2.01秒时间。
需要注意的是上文数据读取速度计算是基于Jeff Dean博士在2009年发表的文章。不得不承认,这个数字现在肯定有变化,实际上,数据的读取速度更快了。但是,所得结果间的比值没有变化,所以我们仍然可以拿来说明问题。
大多数的数据读取密集型的大数据编程模型都利用了这个特征。数据被顺序地从磁盘上读出,然后在内存中过滤数据。与此不同的是典型的关系型数据库管理系统(RDBMS)模型,它们往往是以随机读写数据为主。
1.2.5一个例子
假设我们要计算2000年美国各州的总销售量,并按州排序,销售数据已经随机分发到各个计算节点。利用大数据计算技术,计算这个总量要分成如下步骤:
1)每个计算节点读取分发给自己的全部数据,然后过滤掉不是2000年的销售数据。计算节点从本地磁盘顺序读取被随机分发到该节点上的数据。在内存中过滤掉不用的数据,而不是在磁盘上过滤,这样做可以避免磁盘的寻道时间。
2)各个计算节点在处理数据时,每发现一个新的州,就为它建立一个新的分组,把销售数据加到对应的已存在的州分组中。(程序会在各个计算节点运行,分别做本地数据处理。)
3)当所有的节点都完成了本地所有数据的磁盘读取工作,按照州编号分别计算了其销售总额,它们会分别把各自的计算结果发送到一个特定的计算节点(我们称之为汇聚(assembler)节点),这个汇聚节点是各个计算节点在计算任务伊始由所有节点协商出来的。
4)这个指定的汇聚节点会从所有计算节点按照州编号汇聚全部结果,把各个州的来自不同计算节点的数据分别相加。
5)汇聚节点按照州把最终结果排序,并输出排序结果。
这个过程演示了一个大数据处理系统的典型特征:关注于使系统吞吐量(单位时间内系统处理的数据量)最大化,而非处理结果延时(请求响应的快慢,这个是评价事务性系统好坏的关键指标,因为我们想尽快获得响应)。