转载自:http://blog.itpub.net/7607759/viewspace-756807/
http://blog.itpub.net/7607759/viewspace-756809/
http://blog.itpub.net/7607759/viewspace-756811/
http://blog.itpub.net/7607759/viewspace-756812/
如今的Hadoop不仅声名远扬,影响力在apache的开源项目中也占据着头把交椅,国内外已有非常的成功应用。就目前来说,我对Hadoop整个体系连个大概的了解都说不上,个人倒是老早就想深入学习这套体系,本地磁盘上的安装包更是早就下载好了,不过文件保存日期久远的我自己都不好意思看。
值此新年伊始,欣喜地看到tigerfish老师第四期hadoop课程开班,我也赶紧报名参与,希望能在tigerfish老师的指导下,专心听课认真做题,争取在课程结业的时候,使自己对hadoop的了解能达到入门的水平。
Hadoop如今已经成长为一套体系,包含的组件众多,要学习的知识很多,目前互联网上的各类参考资料更是浩瀚,遇到这种情况很多朋友可能都在苦恼不知道该从何开始。就我来说倒没有这方面的烦恼,从来这么多年,接触的东西也很多,但不管要学习什么,我的学习路径很像那些爱玩游戏的孩子,接触到一个感兴趣的新东西,第一件事并不翻开它的说明书,而是先拿在手里把玩一番,遇着不懂的就去找专门应对方案。等有大致了解之后,再会系统的阅读官方提供的文档。
就Hadoop来说,在使用之前我们得首先有一套环境,因此这篇文章就算是我初次接触Hadoop的一个记录吧,先跟三思一起来了解到底什么是hadoop,而后我们再亲自动手,部署一套Hadoop集群出来。
听说过Doug Cutting没,听说过Lucene没,听说过Nutch没,什么,都没听过?哎,我真不知道该如何向你解释。GOOGLE听说过没,这个总归有印象了吧。为什么要提GOOGLE呢,按照tigerfish老师所说,Hadoop就是山寨版的GOOGLE搜索。
很多朋友都好奇GOOGLE/BAIDU这类搜索引擎,是怎么实现这么高效的查询速度,用的什么数据库等等,GOOGLE当然不会把自己的核心技术全面公开,即使对它最了解的非GOOGLE人士,也只能用连蒙带猜的方式推测,因此能回答这个问题的人怕是不多的。不过我想说的是,HADOOP实现了一套类似GOOGLE的解决方案,如果你了解了它,那么对于前面的问题想必也就有答案了。
前面提示的Nutch/Lucene又是怎么回事儿呢,这部分内容暂不多扯,待后面我八卦些小道消息再论。如有素材欢迎提供。
Hadoop的核心模块有两个:HDFS(Hadoop Distributed Filesystem)和MapReduce,前者提供存储,后者负责计算,可谓珠联璧合,除此之后还有:
其它也许还有,以后必将更多,Hadoop做为Apache基金会的顶级项目,自身也是高速发展。
Hadoop集群中从大的粒度来看可以分为两种角色:Master和Slave,其中master又可以分为主master和辅助master,一个节点属于什么角色,是由其提供的服务决定的:
正常情况下Hadoop集群是由多个节点组成,每个节点做为其中的一个角色承担不同的任务,比如说某个节点运行namenode,某些节点运行datanode等等,不过,用户也可以将所有的应用都放在一个节点上,这种情况尽管也可以运行,其实就称不上分布式了。可是,这种模式还不算极端,Hadoop还支持一种本地模式。
因此归纳一下,Hadoop集群可以分三种部署方式:
Hadoop运行需要JAVA环境,因此首先需要检查系统中是否安装的Java JDK:
[root@hdnode3 ~]# /usr/local/jdk1.7.0_09/bin/java -version
java version "1.7.0_09"
Java(TM) SE Runtime Environment (build 1.7.0_09-b05)
Java HotSpot(TM) 64-Bit Server VM (build 23.5-b02, mixed mode)如果没有找到java的话,需要先安装jdk。安装包可以到SUN官网进行下载,或者直接通过yum进行安装,我这里是。
编译本地hosts文件:
# more /etc/hosts
127.0.0.1 localhost localhost.localdomain
::1 localhost localhost.localdomain
192.168.30.203 hdnode1
192.168.30.204 hdnode2
192.168.30.205 hdnode3创建用户:
# useradd grid
# passwd grid
Changing password for user grid.
New password:
....................解压缩hadoop安装包到指定目录下:
不知道哪里下载安装包?http://www.apache.org/dyn/closer.cgi/hadoop/common/ 这里瞅一瞅。
修改文件夹的用户属主:
生成节点间密钥,切换到grid用户下操作:
[root@hdnode1 ~]# su - grid
[grid@hdnode1 ~]$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/grid/.ssh/id_rsa):
Created directory ¨/home/grid/.ssh¨.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/grid/.ssh/id_rsa.
Your public key has been saved in /home/grid/.ssh/id_rsa.pub.
The key fingerprint is:
b6:17:4b:7a:e1:7d:04:e6:01:49:bc:61:72:fb:b6:f3 grid@hdnode1
The key¨s randomart image is:
+--[ RSA 2048]----+
| oo. |
| . *. |
| + ++ |
| oo o |
| S +.. . |
| . = =o. |
| o =.... |
| o o. |
| oE |
+-----------------+而后将公钥信息保存到authorized_keys文件中:
注意修改authorized_keys文件权限为600,否则节点间无密码访问仍有可能失败。
配置grid用户环境变量:
增加下列内容:
export JAVA_HOME=/usr/local/jdk1.7.0_09
export HADOOP_HOME=/usr/local/hadoop-0.20.2
PATH=${JAVA_HOME}/bin:${HADOOP_HOME}/bin:$PATH:$HOME/bin
在hdnode2和hdnode3节点上分别重复上面的步骤。
现在咱们先将hdnode2和hdnode3两个节点的公钥信息全部输出到hdnode1的authorized_keys文件中:
[grid@hdnode1 ~]$ ssh hdnode2 cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
The authenticity of host ¨hdnode2 (192.168.30.204)¨ can¨t be established.
RSA key fingerprint is 2d:e3:a1:b8:7e:5e:06:ae:04:55:73:73:13:24:94:c8.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added ¨hdnode2,192.168.30.204¨ (RSA) to the list of known hosts.
grid@hdnode2¨s password:
[grid@hdnode1 ~]$ ssh hdnode3 cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
The authenticity of host ¨hdnode3 (192.168.30.205)¨ can¨t be established.
RSA key fingerprint is 2d:e3:a1:b8:7e:5e:06:ae:04:55:73:73:13:24:94:c8.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added ¨hdnode3,192.168.30.205¨ (RSA) to the list of known hosts.
grid@hdnode3¨s password:修改认证密钥文件的权限为只有属主用户可读写:
然后将authorized_keys文件复制到其它节点,直接执行scp命令就可以:
[grid@hdnode1 ~]$ scp ~/.ssh/authorized_keys hdnode2:/home/grid/.ssh/authorized_keys
grid@hdnode2¨s password:
authorized_keys 100% 1182 1.2KB/s 00:00
[grid@hdnode1 ~]$ scp ~/.ssh/authorized_keys hdnode3:/home/grid/.ssh/authorized_keys
grid@hdnode3¨s password:
authorized_keys 100% 1182 1.2KB/s 00:00接下来,如果有兴趣的话可以在各节点试一下ssh连接其它节点,应该不需要输入密码了:
[grid@hdnode1 ~]$ ssh hdnode1 date
Tue Jan 29 16:09:49 CST 2013
[grid@hdnode1 ~]$ ssh hdnode2 date
Tue Jan 29 16:09:51 CST 2013
[grid@hdnode1 ~]$ ssh hdnode3 date
Tue Jan 29 16:09:53 CST 2013注意喽,第一次访问时会提示,将要访问的节点加入到已知主机列表,这是正常的,输入yes同意,后面再访问就不会再提示了。
至此,咱们这个无密码访问就算配置好了。
我们任选一个节点,比如说就hdnode1吧,使用grid用户登录,而后修改配置文件,详细如下。
配置hadoop的基础环境变量,如JDK位置,hadoop一些配置、文件及日志的路径,这些配置都在hadoop-env.sh文件中:
这里我们先仅修改JAVA_HOME变量值,指定到JDK目录:
提示,本步也可以不做修改,而将JAVA_HOME加到用户的环境变量中。
修改核心站点配置,主要指定NameNode服务器的地址:
修改内容如下:
fs.default.name
hdfs://hdnode1:9000/
true
这样我们就将hdnode1定义为NameNode。注意一个hadoop集群中不管master还是slave,fs.default.name的值必须相同,也就是说一个hadoop只能有一个NameNode。
指定HDFS相关的配置:
修改内容如下:
dfs.name.dir
/data2/hadoop/name
true
dfs.data.dir
/data2/hadoop/data
true
dfs.replication
3
那么这几个参数又都是什么意思呢?别的咱不讲,说一说上文提到的这哥仨:
除了这仨,别的参数还多着呢,后面咱们接触到了再介绍。
接下来配置mapreduce服务相关的参数,修改mapred-site.xml文件:
修改内容如下:
mapred.job.tracker
hdnode1:9001
true
指定JobTracker进程运行的位置,这里指定在hdnode1节点上执行。
指定运行SecondaryNameNode服务的节点:
[grid@hdnode1 ~]$ more /usr/local/hadoop-0.20.2/conf/masters
hdnode1提示:注意哟,这里说的是运行SecondaryNameNode服务的节点,并不是指身份为master角色的节点哟。如果希望SecondaryNameNode运行在非namenode节点上的话,可以在这里指定另外的节点。
指定运行datanode和tasktracker的节点:
[grid@hdnode1 ~]$ more /usr/local/hadoop-0.20.2/conf/slaves
hdnode2
hdnode3剩下的俩节点呗。
这样第一个节点就配置好了,第二和第三个节点怎么处理呢?直接将这些文件复制到第二第三节点即可。
前面各节点参数配置好之后,接下来要先对namenode进行格式化,这个操作仍是在hdnode1节点上执行:
[grid@hdnode1 ~]$ hadoop namenode -format
13/01/30 10:14:36 INFO namenode.NameNode: STARTUP_MSG:
/************************************************************
STARTUP_MSG: Starting NameNode
STARTUP_MSG: host = hdnode1/192.168.30.203
STARTUP_MSG: args = [-format]
STARTUP_MSG: version = 0.20.2
STARTUP_MSG: build = https://svn.apache.org/repos/asf/hadoop/common/branches/branch-0.20 -r 911707; compiled by ¨chrisdo¨ on Fri Feb 19 08:07:34 UTC 2010
************************************************************/
Re-format filesystem in /data2/hadoop/name ? (Y or N) y
Format aborted in /data2/hadoop/name
13/01/30 10:14:39 INFO namenode.NameNode: SHUTDOWN_MSG:
/************************************************************
SHUTDOWN_MSG: Shutting down NameNode at hdnode1/192.168.30.203
************************************************************/在执行格式化时,三思本地的测试环境反复尝试都报错。不过如果我们把hdfs-site.xml中dfs.name.dir那段property给删除掉,那么就能正常执行。可是,我实在是希望能够自定义namenode的存储路径,经过对比hadoop权威指南,该段参数写的也没有问题。
不过最终这个问题还是被解决了,知道怎么解决的吗?泥嘛呀,坑爹了。注意前面输出信息中加粗的部分。最终发现,居然是由于选择Y or N那里,我输入的是小写y,它默认理解非Y就是N,于是就没格式化。
重新执行hadoop namenode -format:
[grid@hdnode1 ~]$ hadoop namenode -format
13/01/30 105:20:07 INFO namenode.NameNode: STARTUP_MSG:
/************************************************************
STARTUP_MSG: Starting NameNode
STARTUP_MSG: host = hdnode1/192.168.30.203
STARTUP_MSG: args = [-format]
STARTUP_MSG: version = 0.20.2
STARTUP_MSG: build = https://svn.apache.org/repos/asf/hadoop/common/branches/branch-0.20 -r 911707; compiled by ¨chrisdo¨ on Fri Feb 19 08:07:34 UTC 2010
************************************************************/
Re-format filesystem in /data2/hadoop/name ? (Y or N) Y
13/01/30 10:20:08 INFO namenode.FSNamesystem: fsOwner=grid,grid
13/01/30 10:20:08 INFO namenode.FSNamesystem: supergroup=supergroup
13/01/30 10:20:08 INFO namenode.FSNamesystem: isPermissionEnabled=true
13/01/30 10:20:08 INFO common.Storage: Image file of size 94 saved in 0 seconds.
13/01/30 10:20:08 INFO common.Storage: Storage directory /data2/hadoop/name has been successfully formatted.
13/01/30 10:20:08 INFO namenode.NameNode: SHUTDOWN_MSG:
/************************************************************
SHUTDOWN_MSG: Shutting down NameNode at hdnode1/192.168.30.203
************************************************************/注意加粗字体,然后就正常了。
激动人心的时刻到了,启动hadoop集群,让我们见识见识传说中的Hadoop到底是怎么个情况吧。
直接执行start-all.sh脚本即可:
[grid@hdnode1 hadoop]$ start-all.sh
starting namenode, logging to /usr/local/hadoop-0.20.2/bin/../logs/hadoop-grid-namenode-hdnode1.out
hdnode3: starting datanode, logging to /usr/local/hadoop-0.20.2/bin/../logs/hadoop-grid-datanode-hdnode3.out
hdnode2: starting datanode, logging to /usr/local/hadoop-0.20.2/bin/../logs/hadoop-grid-datanode-hdnode2.out
hdnode1: starting secondarynamenode, logging to /usr/local/hadoop-0.20.2/bin/../logs/hadoop-grid-secondarynamenode-hdnode1.out
starting jobtracker, logging to /usr/local/hadoop-0.20.2/bin/../logs/hadoop-grid-jobtracker-hdnode1.out
hdnode3: starting tasktracker, logging to /usr/local/hadoop-0.20.2/bin/../logs/hadoop-grid-tasktracker-hdnode3.out
hdnode2: starting tasktracker, logging to /usr/local/hadoop-0.20.2/bin/../logs/hadoop-grid-tasktracker-hdnode2.out这个脚本做了什么呢,查看这个脚本的内容,会发现它其实是调用了start-dfs.sh和start-mapred.sh两个脚本。如果你认真看了屏幕输出的信息,即使不看脚本的内容,也会发现输出的日志已经把什么都告诉我们了。
Start-all首先会启动namenode,而后按照conf/slaves文件中指定的节点各启动一个DataNode,在conf/masters文件指定的节点各启动一个SecondaryNameNode;这时start-dfs.sh的工具就结束了,而后执行的start-mapred.sh与start-dfs.sh类似,它会在本地机器上启动一个JobTracker,在conf/slaves文件中指定的节点上各启动一个TaskTracker。
提示:有start就有stop,若要关闭资源,则有与之对应的stop-mapred.sh、stop-dfs.sh及stop-all.sh用于停止这些服务。
验证服务端节点上的服务进程(有namenode但没有datanode):
[grid@hdnode1 ~]$ jps
7727 Jps
6588 JobTracker
6404 NameNode
6524 SecondaryNameNode验证客户端节点上的进程(有datanode没有namenode):
[grid@hdnode2 ~]$ jps
9581 Jps
9337 DataNode
9409 TaskTracker查看HDFS存储信息:
[grid@hdnode1 ~]$ hadoop dfsadmin -report
Configured Capacity: 211376005120 (196.86 GB)
Present Capacity: 200244994048 (186.49 GB)
DFS Remaining: 200244920320 (186.49 GB)
DFS Used: 73728 (72 KB)
DFS Used%: 0%
Under replicated blocks: 1
Blocks with corrupt replicas: 0
Missing blocks: 0
-------------------------------------------------
Datanodes available: 2 (2 total, 0 dead)
Name: 192.168.30.204:50010
Decommission Status : Normal
Configured Capacity: 105688002560 (98.43 GB)
DFS Used: 36864 (36 KB)
Non DFS Used: 5565505536 (5.18 GB)
DFS Remaining: 100122460160(93.25 GB)
DFS Used%: 0%
DFS Remaining%: 94.73%
Last contact: Tue Feb 31 10:33:51 CST 2013
Name: 192.168.30.205:50010
Decommission Status : Normal
Configured Capacity: 105688002560 (98.43 GB)
DFS Used: 36864 (36 KB)
Non DFS Used: 5565505536 (5.18 GB)
DFS Remaining: 100122460160(93.25 GB)
DFS Used%: 0%
DFS Remaining%: 94.73%
Last contact: Tue Feb 31 10:33:51 CST 2013此外也可以通过浏览器获取服务的信息:
现有环境如下:
192.168.30.203 hdnode1
192.168.30.204 hdnode2
192.168.30.205 hdnode3其中hdnode1是namenode,hdnode2和hdnode3是datanode我们要新增加两个datanode:
192.168.30.206 hdnode4
192.168.30.207 hdnode5那么首先初始化hdnode4和hdnode5两节点,初始化节点部分就不再重复了吧,操作步骤可以参与之前"HADOOP安装"中的内容。
初始化完之后,hdnode4和hdnode5两节点应该都拥有了grid用户,配置好用户环境变量,解压好了hadoop软件包(最好是将原节点中的hadoop文件夹打包复制过来,可以减少配置)。
下面需要进行若干修改了,操作时要注意了,有些操作仅在新增节点执行,还有些操作需要在所有的节点上进行。
修改hosts文件
修改hosts文件配置,所有节点都需要执行,通过vi编辑/etc/hosts文件:
增加两行:
192.168.30.206 hdnode4
192.168.30.207 hdnode5配置节点间节密码访问
注意本步都在grid用户下操作的哟。首先在hdnode1端执行:
$ ssh hdnode4 cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
$ ssh hdnode5 cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys将新的authorized_keys文件复制到所有的节点:
$ scp ~/.ssh/authorized_keys hdnode2:/home/grid/.ssh/authorized_keys
$ scp ~/.ssh/authorized_keys hdnode3:/home/grid/.ssh/authorized_keys
$ scp ~/.ssh/authorized_keys hdnode4:/home/grid/.ssh/authorized_keys
$ scp ~/.ssh/authorized_keys hdnode5:/home/grid/.ssh/authorized_keys而后可以尝试在各尝试相互访问,看看是否需要输入密码。
本步操作中有不明白的可以参考“[三思笔记]hadoop安装手册”第1.3小节。
修改masters和slaves文件
Masters文件其实也可以不用修改,还记得masters的用途不?没错就是secondary namenode嘛,咱们这个测试环境中,就跟namenode放在一起也没关系的。 如果要修改的话,可以编译masters文件,新增一个节点保存secondary namenode:
修改所有节点的slaves文件,将新增的hdnode4和hdnode5加进去:
echo "hdnode4" >> /usr/local/hadoop-0.20.2/conf/slaves
echo "hdnode5" >> /usr/local/hadoop-0.20.2/conf/slaves修改后的slaves文件内容如下:
$ more /usr/local/hadoop-0.20.2/conf/slaves
hdnode2
hdnode3
hdnode4
hdnode5新节点中单独启动datanode和tasktracker
环境现在已经初始化好了,那么接下来就可以单独启动新节点中的datanode和tasktracker进程了。
分别在hdnode4和hdnode5节点执行:
$ hadoop-daemon.sh start datanode
$ hadoop-daemon.sh start tasktracker这样HDFS的扩容就完成了,可以通过hadoop dfsadmin命令查看统计信息:
[grid@hdnode4 ~]$ hadoop dfsadmin -report
Configured Capacity: 422752010240 (393.72 GB)
Present Capacity: 400489983786 (372.99 GB)
DFS Remaining: 400489492480 (372.98 GB)
DFS Used: 491306 (479.79 KB)
DFS Used%: 0%
Under replicated blocks: 0
Blocks with corrupt replicas: 0
Missing blocks: 0
-------------------------------------------------
Datanodes available: 4 (4 total, 0 dead)
……
……容量已经扩充到四百G了。
平衡存储负载
尽管容量扩展了,但数据目前仍然是保存在原有的两个节点上,接下来可以通过start-balancer.sh进行数据负载均衡:
$ start-balancer.sh
starting balancer, logging to /usr/local/hadoop-0.20.2/bin/../logs/hadoop-grid-balancer-hdnode4.out
Time Stamp Iteration# Bytes Already Moved Bytes Left To Move Bytes Being Moved
The cluster is balanced. Exiting...对于数据规模较大的HDFS来说,本操作可能需要花费较长时间,因为它需要将数据重新平衡到不同的节点上,因此正式环境操作的话需要慎重。
删除节点
这个就不演示了吧,直接关机,就当那台节点宕机了:)
然后呢,然后做什么?哥们,我们现在部署好了HDFS可以存储数据,Tasktracker和Jobtracker也已就绪,我们目前已经为分布式计算打好了基础,接下来,找个顺手的java开发工具吧。