一台存储数据的机器会由CPU、内存、硬盘三部分组成。当数据量逐渐增大后,内存严重不足,并且单机硬盘储存的数据会因为个体异常造成所有用户无法调取数据。因此产生了一系列的大数据生态技术,用于分布式的实现数据处理。

简述HDFS和MapReduce的主要作用 mapreduce hdfs关系_xshell查看hdfs文件目录路径

虽然近几年,Hadoop平台逐渐被Spark等大数据平台所取代。但是分布式存储和Map-reduce处理的思路却是一切大数据技术的基础。这篇文章主要对这两部分进行介绍。

分布式文件系统:

1.数据以“块状”形式储存在多台机器上(32M或者64M)

2.每个数据块重复存于多个机器上

3.保证数据的持续性和随时可取性

简述HDFS和MapReduce的主要作用 mapreduce hdfs关系_hadoop应用开发技术..._02

即通过“备份”,将数据切块。也就是用空间换取数据节点的稳定性,以防止单个服务器挂掉后,数据的加载出现问题。而计算任务则会在每一台服务器上单独运行,以减少IO运行速度的影响。

HDFS

HDFS 是一个Hadoop分布式文件系统,具有高度容错,通常部署在廉价机器上。HDFS能提供高吞吐量的连续数据访问,适合超大数据集的应用。首先HDFS的设计之初就是针对超大文件的存储的,小文件不会提高访问和存储速度,反而会降低;其次它采用了最高效的访问模式,也就是经常所说的流式数据访问,特点就是一次写入多次读取;再有就是它运行在普通的硬件之上的,即使硬件故障,也就通过容错来保证数据的高可用。

HDFS关键元素

Block:大文件的存储会被分割为多个block进行存储。默认为64MB,每一个blok会在多个datanode上存储多份副本,默认为3份。[这些设置都能够通过配置文件进行更改]

Namenode:主要负责存储一些metadata信息,主要包括文件目录、block和文件对应关系,以及block和datanote的对应关系

Datanode:负责存储数据,上面我们所说的高度的容错性大部分在datanode上实现的[还有一部分容错性是体现在namenode和secondname,还有jobtracker的容错等]。

简述HDFS和MapReduce的主要作用 mapreduce hdfs关系_mapreduce复制连接的代码_03

HDFS常见命令

HDFS上的数据,分布在不同的地方,在Linux环境中,我们可以通过一些命令行进行 增加/查看/删除 等数据操作。

#显示/下的所有文件夹信息hadoop fs -ls /#递归显示所有文件夹和子文件(夹)hadoop fs -lsr#创建/user/hadoop目录hadoop fs -mkdir /user/hadoop#把a.txt放到集群/user/hadoop/文件夹下hadoop fs -put a.txt /user/hadoop/#把集群上的/user/hadoop/a.txt拉到本地/目录下hadoop fs -get /user/hadoop/a.txt /#集群上复制文件hadoop fs -cp src dst#集群上移动文件hadoop fs -mv src dst#查看集群上文件/user/hadoop/a.txt的内容hadoop fs -cat /user/hadoop/a.txt#删除集群上/user/hadoop/a.txt文件hadoop fs -rm /user/hadoop/a.txt#删除目录和目录下所有文件hadoop fs -rmr /user/hadoop/a.txt#与hadoop fs -put功能类似hadoop fs -copyFromLocal localsrc dst#将本地文件上传到hdfs,同时删除本地文件hadoop fs -moveFromLocal localsrc dst

MapReduce

通俗说MapReduce是一套从海量·源数据提取分析元素最后返回结果集的编程模型,将文件分布式存储到硬盘是第一步,而从海量数据中提取分析我们需要的内容就是MapReduce做的事了。

下面以一个计算海量数据最大值为例:一个银行有上亿储户,银行希望找到存储金额最高的金额是多少,按照传统的计算方式,我们会这样:

Long moneys[] ...  Long max = 0L;  for(int i=0;i  if(moneys[i]>max){      max = moneys[i];    }  }

如果计算的数组长度少的话,这样实现是不会有问题的,还是面对海量数据的时候就会有问题。

MapReduce会这样做:首先数字是分布存储在不同块中的,以某几个块为一个Map,计算出Map中最大的值,然后将每个Map中的最大值做Reduce操作,Reduce再取最大值给用户。

简述HDFS和MapReduce的主要作用 mapreduce hdfs关系_hadoop读入多个文件_04

MapReduce的基本原理就是:将大的数据分析分成小块逐个分析,最后再将提取出来的数据汇总分析,最终获得我们想要的内容。当然怎么分块分析,怎么做Reduce操作非常复杂,Hadoop已经提供了数据分析的实现,我们只需要编写简单的需求命令即可达成我们想要的数据。

简述HDFS和MapReduce的主要作用 mapreduce hdfs关系_hadoop读入多个文件_05

接下来通过一个在任何的hadoop教材上都会看到的词频统计案例,来学习一下如何Hadoop的map/reduce任务,完成大数据的处理。

咱们来看看对特别大的文件统计,整个过程是如何分拆的。大家想想词频统计的过程,如果是单机完成,我们需要做的事情是维护一个计数器字典,对每次出现的词,词频+1.但是当数据量非常大的时候,没办法在内存中维护这么大的一个字典,我们就要换一种思路来完成这个任务了,也就是我们所谓的map-reduce过程。

大体的过程画成图是下面这个样子:

简述HDFS和MapReduce的主要作用 mapreduce hdfs关系_hdfs复制文件夹_06

也就是想要生成很多的key-value对,并且按照key进行排序,按照value进行聚合。具体分成三个阶段:

Map阶段:主要完成key-value对生成,这里是每看到一个单词,就输出(单词,1)

Shaffer阶段:对刚才的kv对进行排序,这样相同单词就在一块儿了

Reduce阶段:对同一个单词的次数进行汇总,得到(词,频次)对

通过Hadoop streaming,可以直接使用python脚本完成map和reduce过程。

Map阶段代码

map阶段要做的就是把每一个单词和出现1次的信息输出来。我们写一个mapper.py文件,具体内容如下:

#coding: utf-8#!/usr/bin/env pythonimport sys# 从标准输入过来的数据for line in sys.stdin:    # 把首位的空格去掉    line = line.strip()    # 把这一行文本切分成单词(按照空格)    words = line.split()    # 对见到的单词进行次数标注(出现1次)    for word in words:        print '%s\t%s' % (word, 1)

对于输入进来的每一行,我们做完切分之后,都会输出(单词,1)这样一个kv对,表明这个单词出现过。

Shaffer阶段

中间会有一个对上述结果进行排序的过程,以保证所有相同的单词都在一起,不过不用担心,这个过程是系统会自动完成的,因此不用我们编写额外的代码。

Reduce阶段

接下来就是对map排序后的结果进行汇总了,这个阶段我们可以用一个reducer.py的python脚本来完成,具体完成的任务,就是:

对于读入的(单词,1)对

1. 如果这个单词还没有结束(排序后所有相同的单词都在一起了),我们就对单词的次数+1

2. 如果遇到新单词了,那重新开始对新单词计数

可以完成以下的reducer.py脚本:

#coding: utf-8#!/usr/bin/env pythonfrom operator import itemgetterimport syscurrent_word = Nonecurrent_count = 0word = None# 依旧是标准输入过来的数据for line in sys.stdin:    # 去除左右空格    line = line.strip()    # 按照tab键对行切分,得到word和次数1    word, count = line.split('\t', 1)    # 你得到的1是一个字符串,需要对它进行类型转化    try:        count = int(count)    except ValueError:        #如果不能转成数字,输入有问题,调到下一行        continue    # 如果本次读取的单词和上一次一样,对次数加1    if current_word == word:        current_count += count    else:        if current_word:            # 输出统计结果            print '%s\t%s' % (current_word, current_count)        current_count = count        current_word = word# 不要忘了最后一个词哦,也得输出结果if current_word == word:    print '%s\t%s' % (current_word, current_count)

下面我们就可以用hadoop streaming执行map-reduce任务了,命令行执行

user@ubuntu:/usr/local/hadoop$ bin/hadoop jar contrib/streaming/hadoop-*streaming*.jar \-file /home/hduser/mapper.py    -mapper /home/hduser/mapper.py \-file /home/hduser/reducer.py   -reducer /home/hduser/reducer.py \-input /user/hduser/gutenberg/* -output /user/hduser/gutenberg-output

end