hadoop的安装分为本地模式、伪分布模式、集群模式。本地模式是运行在本地,只负责存储,没有计算功能,本书不讲述。伪分布模式是在一台机器上模拟分布式部署,方便学习和调试。集群模式是在多个机器上配置hadoop,是真正的“分布式”。本章讲述伪分布模式和集群的安装。
1. 解压缩hadoop
使用WinSCP把压缩包hadoop-1.1.2.tar.gz从宿主机复制到linux的/usr/local目录下,如图3-1。
图3-1
解压缩文件,并重命名为hadoop,方便使用。重命名后,hadoop目录的完整路径是“/usr/local/hadoop”。
设置环境变量HADOOP_HOME,修改文件“/etc/profile”,如下图:
图3-2
请读者与jdk设置时配置文件对照。这里我们设置了一个别名cdha,可以快速转到hadoop的目录。
修改环境变量后,记得执行source命令哦。
现在让我们浏览一下hadoop的目录结构吧
图3-3
我们关注bin目录和conf目录。
2. 修改配置文件
hadoop配置文件默认是本地模式,我们修改四个配置文件,这些文件都位于$HADOOP_HOME/conf目录下。
第一个是hadoop环境变量脚本文件hadoop-env.sh,修改第9行代码为。
export JAVA_HOME=/usr/local/jdk |
保存并关闭。这里设置的是JAVA_HOME,注意去掉前面的“#”。
第二个是hadoop核心配置文件core-site.xml,结果如下
<configuration> <property> <name>hadoop.tmp.dir</name> <value>/home/hadoop/tmp</value> <description>hadoop的运行临时文件的主目录</description> </property> <property> <name>fs.default.name</name> <value>hdfs://book0:9000</value> <description>HDFS的访问路径</description> </property> </configuration> |
第三个是hdfs配置文件hdfs-site.xml,结果如下
<configuration> <property> <name>dfs.replication</name> <value>1</value> <description>存储副本数</description> </property> </configuration> |
第四个是MapReduce配置文件mapred-site.xml,结果如下
<configuration> <property> <name>mapred.job.tracker</name> <value>book0:9001</value> <description>JobTracker的访问路径</description> </property> </configuration> |
这是安装伪分布模式的最小化配置。目前的任务是把hadoop跑起来,先不关注各配置项什么含义,这些配置项还在后文会有详细的解释。
3. 格式化文件系统
hdfs是文件系统,所以在第一次使用之前需要进行格式化。执行命令$HADOOP_HOME/bin/hadoop namenode –format。见图3-4
图3-4
注意:只在第一次启动的时候格式化,不要每次启动都格式化。理解为我们新买了块移动硬盘,使用之前总要格式化硬盘。
如果真的有必要再次格式化,请先把“$HADOOP_HOME/tmp”目录下的文件全部删除。
读者可以自己观察目录”$HADOOP_HOME/tmp”在格式化前后的变化情况。
格式化操作很少有出现失败的情况。如果真出现了,请检查配置是否正确。
4. 启动
格式化完成后,开始启动hadoop程序。
启动hadoop的命令脚本都在$HADOOP_HOME/bin/下,下面的所有命令都不再带有完整路径名称。
这里讲述hadoop启动的三种方式:
第一种,一次性全部启动:
图3-5
执行start-all.sh启动hadoop,观察控制台的输出,见图3-5,可以看到正在启动进程,分别是namenode、datanode、secondarynamenode、jobtracker、tasktracker,一共5个,待执行完毕后,并不意味着这5个进程成功启动,上面仅仅表示系统正在启动进程而已。
我们使用jdk的命令jps查看进程是否已经正确启动。执行以下jps,如果看到了这5个进程,见图3-6,说明hadoop真的启动成功了。如果缺少一个或者多个,那就进入到“Hadoop的常见启动错误”章节寻找原因了。
图3-6
关闭hadoop的命令是stop-all.sh。
上面的命令是最简单的,可以一次性把所有节点都启动、关闭。除此之外,还有其他命令,是分别启动的。
第二种,分别启动HDFS和MapReduce:
图3-7
执行命令start-dfs.sh,是单独启动hdfs,见图3-7。执行完该命令后,通过jps能够看到NameNode、DataNode、SecondaryNameNode三个进程启动了,该命令适合于只执行hdfs存储不使用MapReduce做计算的场景。关闭的命令就是stop-dfs.sh了。
图3-8
执行命令start-mapred.sh,可以单独启动MapReduce的两个进程。关闭的命令就是stop-mapred.sh了。当然,也可以先启动MapReduce,再启动HDFS。这说明,HDFS和MapReduce的进程之间是互相独立的,没有依赖关系。
第三种,分别启动各个进程:
[root@book0 bin]# jps 14821 Jps [root@book0 bin]# hadoop-daemon.sh start namenode [root@book0 bin]# hadoop-daemon.sh start datanode [root@book0 bin]# hadoop-daemon.sh start secondarynamenode [root@book0 bin]# hadoop-daemon.sh start jobtracker [root@book0 bin]# hadoop-daemon.sh start tasktracker [root@book0 bin]# jps 14855 NameNode 14946 DataNode 15043 SecondaryNameNode 15196 TaskTracker 15115 JobTracker 15303 Jps |
执行的命令是“hadoop-daemon.sh start [进程名称]”,这种启动方式适合于单独增加、删除节点的情况,在安装集群环境的时候会看到。
5. 运行简单的MapReduce计算
在$HADOOP_HOME下有个jar包,叫hadoop-example-1.1.2.jar,见图3-9,这里面含有框架提供的很多例子.我们现在学习一下如何运行其中的例子吧.
图3-9
hadoop jar hadoop-example-1.1.2.jar |
执行如下命令
可以看到图3-10的输出信息,可以看到18个输出信息,都是内置的例子程序.我们选择最后一个”word count”来运行,该程序的说明在最后,是统计文件中单词的出现次数的.
图3-10
如何执行这个程序哪?见图3-11,如下
图3-11
根据用法,我们需要补全wordcount的文件输入路径和文件输出路径.我们首先上传一个文件到hdfs中,见图3-12.那么输入文件的路径就是/README.txt了。
图3-12
这时候我们再运行wordcount例子,命令如下
hadoop jar hadoop-examples-1.1.2.jar wordcount /README.txt /wordcountoutput |
在这条命令中,“/README.txt”是我们刚才上传到hdfs中的文件,作为输入路径;“/wordcountoutput”是设定的输出路径,该路径在命令执行前是不存在的。
等到命令执行结束,运行的结果就会存在输出路径的文件夹中,文件名称叫做“part-r-00000”,我们使用命令查看输出内容,如图3-13
图3-13
以上只是显示了一部分。显示结果是按照字符的字段顺序排列的,每一行显示字符及出现次数。
如果读者能够成功运行,那么恭喜你!你看到的就是hadoop的MapReduce做的事情。通过一个简单的命令,就可以把文件中的单词统计一遍出现次数,还是很有意思的。参加工作后,大家会根据输入文件的内容和类型,写这样的算法程序,产生输出结果。
1.1.1. hadoop的核心思想
Hadoop包括两大核心,分布式存储系统和分布式计算系统。
1.1.1.1. 分布式存储
为什么数据需要存储在分布式的系统中哪,难道单一的计算机存储不了吗,难道现在的几个TB的硬盘装不下这些数据吗?事实上,确实装不下。比如,很多的电信通话记录就存储在很多台服务器的很多硬盘中。那么,要处理这么多数据,必须从一台一台服务器分别读取数据和写入数据,太麻烦了!
我们希望有一种文件系统,可以管辖很多服务器用于存储数据。通过这个文件系统存储数据时,感觉不到是存储到不同的服务器上的。当读取数据时,感觉不到是从不同的服务器上读取。如图2-1所示。这就是分布式文件系统。
图2-1
分布式文件系统管理的是一个服务器集群。在这个集群中,数据存储在集群的节点(即集群中的服务器)中,但是该文件系统把服务器的差异屏蔽了。那么,我们就可以像使用普通的文件系统一样使用,但是数据却分散在不同的服务器中。
在分布式存储系统中,分散在不同节点中的数据可能属于同一个文件,为了组织众多的文件,把文件可以放到不同的文件夹中,文件夹可以一级一级的包含。我们把这种组织形式称为命名空间(namespace)。命名空间管理着整个服务器集群中的所有文件。很明显,命名空间的职责与存储真实数据的职责是不一样的。集群中不同的节点承担不同的职责。负责命名空间职责的节点称为主节点(master node),负责存储真实数据职责的节点称为从节点(slave node)。主节点负责管理文件系统的文件结构,从节点负责存储真实的数据,称为主从式结构(master-slaves)。用户操作时,也应该先和主节点打交道,查询数据在哪些从节点上存储,然后再从从节点读取,如图2-2所示。在主节点,为了加快用户访问的速度,会把整个命名空间信息都放在内存中,当存储的文件越多时,那么主节点就需要越多的内存空间。在从节点存储数据时,有的原始数据文件可能很大,有的可能很小,大小不一的文件不容易管理,那么可以抽象出一个独立的存储文件单位,称为块(block)。数据存放在集群中,可能因为网络原因或者服务器硬件原因造成访问失败,最好采用副本(replication)机制,把数据同时备份到多台服务器中,这样数据就安全了,数据丢失或者访问失败的概率就小了。
图2-2
在以上的主从式结构中,由于主节点含有整个文件系统的目录结构信息,因为非常重要。另外,由于主节点运行时会把命名空间信息都放到内存中,因此存储的文件越多,主节点的内存就需要的越多。
在hadoop中,分布式存储系统称为HDFS(hadoop distributed file system)。其中,主节点称为名字节点(namenode),从节点称为数据节点(datanode)。
1.1.1.2. 分布式计算
对数据进行处理时,我们会把数据读取到内存中进行处理。如果我们对海量数据进行处理,比如数据大小是100GB,我们要统计文件中一共有多少个单词。要想把数据都加载到内存中几乎是不可能的,称为移动数据。随着技术发展,即使服务器有100GB内存,那么服务器价格也会很高,不是普通老百姓能够消受得了得。即使数据能够加载到内存,那么加载这100GB的数据到内存也要消耗很长时间。这些问题都在困挠着我们对大数据的处理。也就是说移动计算的处理方式不适合大数据计算。
换个思路,既然移动数据不合适,那么是否可以把程序代码放到存放数据的服务器上哪?因为程序代码与原始数据相比,一般很小,几乎可以忽略的,所以省下了原始数据传输的时间了。现在,数据是存放在分布式文件系统中,100GB的数据可能存放在很多的服务器上,那么就可以把程序代码分发到这些服务器上,在这些服务器上同时执行,也就是并行计算,也是分布式计算。这就大大缩短了程序的执行时间。我们把程序代码移动到数据节点的机器上执行的计算方式称为移动计算。
分布式计算需要的是最终的结果,程序代码在很多机器上并行执行后会产生很多的结果,因此需要有一段代码对这些中间结果进行汇总。Hadoop中的分布式计算一般是由两阶段完成的。第一阶段负责读取各数据节点中的原始数据,进行初步处理,对各个节点中的数据求单词数。然后把处理结果传输到第二个阶段,对中间结果进行汇总,产生最终结果,求出100GB文件总共有多少个单词,如图2-3所示。
图2-3
在分布式计算中,程序代码应该允许在哪些数据节点上,哪些节点运行第一阶段的代码,哪些节点运行第二阶段的代码;第一阶段代码执行完毕后,传输到第二阶段代码所在的节点;如果中间执行失败了,怎么办?等等问题,都需要管理。运行这些管理职责代码的节点称为主节点(master node),运行第一二阶段程序代码的节点称为从节点(slave node)。用户的代码应该提交给主节点,由主节点负责把代码分配到不同的节点执行。
在hadoop中,分布式计算部分称为MapReduce。其中,主节点称为作业节点(jobtacker),从节点称为任务节点(tasktracker)。在任务节点中,运行第一阶段的代码称为map任务(map task),运行第二阶段的代码称为reduce任务(reduce task)。