Hadoop生态链已经成为如今大数据实际意义上的实现。因此在Hadoop生态下建设数据仓库需要了解一些Hadoop的基本原理。这会对我们将来为什么这么设计数据仓库提供一些解答。
Hadoop最基础的两块是它的分布式文件存储(HDFS)和MapReduce计算模型(MR)。通过大数据界的"Hello World"——统计一篇文章中每个单词出现的次数,这样一个案例来跟踪一下Hadoop是怎么做的。
HDFS (Hadoop Distributed File System)
首先我们将要统计的文章传入HDFS中。在这个由许多计算机节点(Node)通过网络连接在一起的分布式文件系统中,计算机节点被分为一台NameNode和多台DataNode。DataNode负责数据的存储和读取以及MapReduce的计算,NameNode负责管理和维护等所有其余事务(详见延伸阅读)。
如果我们要统计词频的这篇文章特别长,那么它会被切成一个个数据块(block)进行存储,每个block默认设置为128M,block是读取数据的最小单位。同时为了防止因为单个计算机节点故障而造成数据丢失,默认每个block会被存储为3份副本(replica)。3份副本会分散到不同的节点上存储:第一份直接存储在写入时的DateNode上,第二份存储在不同机架上的DataNode,第三份存储在第二份所在的机架中随机的DataNode。
读数据时会对block做checksums校验,以保证每个block中内容的准确性。如果校验失败了,则会换个备份去获取,同时上报给NameNode。
至此,我们想统计的那篇很长很长的文章被切割成了若干个block,并且总共存了三份副本在分散的机器上。这就是HDFS存储数据文件时做的事情。有了数据,我们就可以开始做统计单词的计算了。
MapReduce
MapReduce(MR)是Hadoop的计算模型,它分为Map任务和Reduce任务。我们把组成Hadoop集群的每台计算机称作节点(Node),这些MR任务通常由YARN分配到某些nodes上运行。YARN(Yet Another Resource Negotiator)是在Hadoop生态中用来做资源管理和调度的。如果某个节点上的任务跑失败了,它会自动换一台节点重新运行。
Map任务
现在我们需要通过Map任务完整的读一遍我们那篇长长的文章,然后记录下来出现的每个单词。如果由一台机器来读,那就不是分布式计算了。分布式计算的想法是,我们要把这篇文章分割成若干份,让每台机器读不同的部分,分别记录那份数据里出现的单词。
具体来看,Map任务首先会将所需处理的数据切分成多个splits,默认一个split的大小也是128M,和block的大小是一致的。
由于节点之间数据传输的带宽被认为是当前最昂贵的开销,map的时候会有一个计算向数据靠拢的优化:map任务会尽可能地在数据所在的节点上运行计算这部分数据,以此避免数据在不同节点之间的传输来节约带宽——这也称作数据本地优化(或计算向数据靠拢)。
当存有该数据块的节点正在运行其他map任务的时候,调度器会寻找同一个机架上有空闲map槽位的节点来运行。极少情况下,当所有同机架上的所有map槽位都不可用的时候,调度器会跨机架调度任务,此时会引起机架间的数据传输。
这也是为什么最好将split的大小设置为HDFS块(block)的大小:它是能保证单份数据split在单个节点上,并且是该节点上所能获得的最大数据。反之,如果一个split大于一个block,跨了两个blocks,那么就无法保证这两个blocks是在同一台节点上的,因此就会需要将其中一个block传到另外个节点中,导致出现数据传输的情况。
Map任务的输出是写入本地磁盘的。由于它是个临时结果,用完就可以丢弃,万一使用之前数据出了问题,Hadoop会自动在其他节点重跑这个map并进行输出。
此时的map并不进行统计任务,它只负责完整地读一遍分配给它的那块文章。它每读到一个单词,就会生成一条记录。该记录是一条键值对<key, value>,它记录下该单词,以及出现了1次,长这个样子<Hello, 1>。因为它并不进行统计,所以当一个map读到几个一样的单词时,会生成多条一样的记录,这些都忠实地传给Reduce去做统计。
shuffle
shuffle这个词用来描述map和reduce之间的数据流——每个reduce的数据都是来自许多map,那么将map的输出分配到各个reduce的过程通常被称作shuffle。shuffle为下一步的再次并行运算(这里是指reduce)而将所有数据重新分配。
shuffle的时候会先对key进行排序,在这里就是按单词的字母顺序排序。reduce任务和map任务使用的是无差别的计算机节点,每个map任务都会为每个reduce任务创建一个分区。不同的reducer各自统计不同的单词,同一个单词必须由一个reducer来统计。所以我们要通过某个叫哈希函数的东西将同样的key,也就是同样的单词shuffle到同一台reduce机器上去。同样的key值一定会被分到同一个reduce任务下。
Reduce任务
Reduce任务是以map任务的输出作为输入,对数据做一些聚合/汇总型操作最终输出结果。所以某个节点获得所有map传过来的大量的<Hello, 1>,然后进行统计,最后输出<Hello, 9999>这样的统计结果。
Reduce是没有数据本地化的优势的,但是它产出的第一个结果集是本地存储的,其余备份则跨机架存储。reduce任务数不由输入数据的大小决定,而是由其逻辑、参数的配置以及当时的资源等因素共同决定的。
通过以上的一系列步骤,我们利用多台机器一起合作,完成了一篇超级长的文章的词频统计!
Hive
最后再提一下Hive——一个基于Hadoop底层,将数据映射成表结构,并能通过SQL进行大数据管理的数据仓库软件。
延伸阅读:
每个block、file、directory都需要消耗namenode上150bytes的内存存储block structure(另外filte structure也需要150bytes),所以受制于内存,文件系统并不是无限扩大的。
Federation可以让NN分开管理namespace volume。NN存储namespace image和edit log。block locations是依靠DN上报来组织的。
hadoop HA会使用secondary NN,共享的edit log。hadoop推荐的共享edit log方式是在journal nodes上运行Quorum Journal Manager,一般需要三台journal nodes使用类似zookeeper的选举机制(但是不是直接用的ZK, NN的选举是用的ZK以保证仅一台NN是活跃的)。失败恢复只需要几十秒,但是确定NN已经失败却需要花费一分钟。
combiner function 这是一个可选的优化器,在map和reduce之间,可以提前做一些汇总操作,以减少传输的数据量。但是它的计算必须能满足交换律和结合律。
Hadoop的网络拓扑是以带宽为“距离”的。
YARN也有Resource Manager 和 Node Manager,YARN分为三种队列:FIFO, Capacity, Fair Scheduler。