Hadoop使用学习笔记
1.Hadoop安装与基本概念
Hadoop发行版本地址
1.1环境配置需求
本文是用的Hadoop版本是最新的2.7.2发行版。 本文分两个机器环境,分别是研发环境和测试环境:
环境配置: 操作系统: LSB Version: :base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-noarch Distributor ID: RedHatEnterpriseServer Description: Red Hat Enterprise Linux Server release 6.6 (Santiago) Release: 6.6 Codename: Santiago 硬件配置: 内存 16384MB 虚拟处理器(VCPU) 8 硬盘 40GB
首先检查环境配置, 1.Java需求,目前Java版本支持度测试,Hadoop2.7需要Java1.7以上的版本,Hadoop2.6以及之前的需要Java1.6版本以上。 2.Hadoop利用ssh远程操控集群,所以需要ssh(输入sshd命令看是否可以找到这个命令) 3.rsync命令是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件。rsync使用所谓的rsync算法来使本地和远程两个主机之间的文件达到同步,这个算法只传送两个文件的不同部分,而不是每次都整份传送,因此速度相当快。(同理,请输入rsync 命令检查是否存在) 之后开始安装,下载好Hadoop,解压:
代码语言:javascript复制>tar zxvf hadoop-2.7.2.tar.gz
>cd hadoop-2.7.2
>ll
total 52
drwxr-xr-x 2 sfdba usr01 4096 Jan 26 08:20 bin
drwxr-xr-x 3 sfdba usr01 4096 Jan 26 08:20 etc
drwxr-xr-x 2 sfdba usr01 4096 Jan 26 08:20 include
drwxr-xr-x 3 sfdba usr01 4096 Jan 26 08:20 lib
drwxr-xr-x 2 sfdba usr01 4096 Jan 26 08:20 libexec
-rw-r--r-- 1 sfdba usr01 15429 Jan 26 08:20 LICENSE.txt
-rw-r--r-- 1 sfdba usr01 101 Jan 26 08:20 NOTICE.txt
-rw-r--r-- 1 sfdba usr01 1366 Jan 26 08:20 README.txt
drwxr-xr-x 2 sfdba usr01 4096 Jan 26 08:20 sbin
drwxr-xr-x 4 sfdba usr01 4096 Jan 26 08:20 share
解压完毕后,需要修改一个脚本。修改etc/hadoop/hadoop-env.sh
代码语言:javascript复制>vim etc/hadoop/hadoop-env.sh
修改其中的JAVA_HOME为java安装路径,hadoop运行时会在后面加上/bin/java来启用java
代码语言:javascript复制# The java implementation to use.
export JAVA_HOME=/usr/lib/jvm/jre-1.7.0-openjdk.x86_64/
之后保存,运行一个简单的hadoop命令,看到如下输出,则成功:
代码语言:javascript复制>bin/hadoop version
Hadoop 2.7.2
Subversion https://git-wip-us.apache.org/repos/asf/hadoop.git -r b165c4fe8a74265c792ce23f546c64604acf0e41
Compiled by jenkins on 2016-01-26T00:08Z
Compiled with protoc 2.5.0
From source with checksum d0fda26633fa762bff87ec759ebe689c
This command was run using /home/sfdba/hadoop-2.7.2/share/hadoop/common/hadoop-common-2.7.2.jar
下面测试官网给的独立运行测试:
代码语言:javascript复制mkdir input
cp etc/hadoop/*.xml input
bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.2.jar grep input output 'dfs[a-z.] '
cat output/*
这是一段将所有配置文件作为输入,检查其中匹配’dfs[a-z.] ’这个正则表达式(开头是dfs末尾为多个字母的词语)的词语的个数
1.2 伪集群安装
Hadoop可以单机伪集群模式运行。 首先我们先来明确几个概念: Hadoop主要由两部分构成,分别是Mapreduce计算部分,还有底层存储HDFS。 系统架构(manager-worker架构):
其中Namenode就是整个集群中的Manager,保存着文件系统的命名空间,以及维护整个文件系统。这些信息保存在两个文件中形式中:命名空间镜像文件还有编辑日志文件。也记录着每个文件的块(有的地方叫block也有叫chunk,都可以,磁盘块大概512字节,Hadoop中目前默认为128MB,原理:块设置的足够大,那么块寻址时间将远小于磁盘传输时间,减少寻址占比。假设寻址时间为10ms,传输速度为100MB/s,那么块设置为100MB,将使寻址时间占比约为1%)所载在的据节点信息,但是不是持久化的,这些信息会在系统启动时,由数据节点重建 Datanode就是文件系统中的工作节点,根据需要存储并检索数据库块,并且定时向Namenode发送所存储块的列表。 Namenode不能损坏,否则数据无法从data中拼接出来
伪集群安装,就是在单机部署多个Hadoop实例(多个JVM运行)。这里,我们部署一个namenode和一个datanode的单机伪集群。 首先,我们需要修改etc/hadoop/core-site.xml,添加如下所示:
代码语言:javascript复制<configuration>
<property>
<!-指定HDFS服务端口-->
<name>fs.defaultFSname>
<value>hdfs://localhost:9000value>
property>
configuration>
之后修改HDFS配置文件:
代码语言:javascript复制<configuration>
<property>
<!-指定HDFS数据复制份数-->
<name>dfs.replicationname>
<value>1value>
property>
configuration>
之后,检查是否可以无参正常ssh连接localhost
代码语言:javascript复制>ssh localhost
如果不行,则执行如下命令生成SSH秘钥:
代码语言:javascript复制>ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
>cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
>chmod 0600 ~/.ssh/authorized_keys
之后启动HDFS,分为如下几步: 1.格式化文件系统,执行下面命令,初始化Hadoop文件系统HDFS(其实就是初始化保存目录以及namenode中要保存的metadata)如果,,日志中没报错并且看到INFO util.ExitUtil: Exiting with status 0的话则成功初始化
代码语言:javascript复制>bin/hdfs namenode -format
2.启动Datanode还有Namenode。运行下面命令:
代码语言:javascript复制>sbin/start-dfs.sh
打开浏览器,访问http://你的机器ip:50070,如果出现如下类似界面,则成功
3.下一步我们为当前用户创建必要的目录
代码语言:javascript复制>bin/hdfs dfs -mkdir /user
#这里替换成你当前系统用的用户名
>bin/hdfs dfs -mkdir /user/
查看刚才网页中的Utilities->Browse the file system,可以看到我们之前创建的文件夹:
4.接下来接着使用刚才的例子测试,首先将etc/hadoop 目录下的文件传入HDFS中的input文件夹(就是放在/usr//input中)
代码语言:javascript复制>bin/hdfs dfs -put etc/hadoop input
之后执行刚才的例子:
代码语言:javascript复制>bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.2.jar grep input output 'dfs[a-z.] '
命令中指定结果放在HDFS的/usr//output
文件夹中,查看结果,结果如下所示:
>bin/hdfs dfs -cat output/*
6 dfs.audit.logger
4 dfs.class
3 dfs.server.namenode.
2 dfs.period
2 dfs.audit.log.maxfilesize
2 dfs.audit.log.maxbackupindex
1 dfsmetrics.log
1 dfsadmin
1 dfs.servers
1 dfs.replication
1 dfs.file
可以看出,HDFS其实和linux的基本文件系统在使用命令上大同小异
5.停止集群:
代码语言:javascript复制>sbin/stop-dfs.sh
1.3 利用YARN提交任务
确认上面1.2节的前三步已经执行后,我们可以通过YARN(Yet Another Resource Negotiator)来提交MapReduce任务。 为了能够对集群中的资源进行统一管理和调度,Hadoop 2.0引入了数据操作系统YARN。YARN的引入,大大提高了集群的资源利用率,并降低了集群管理成本。首先,YARN允许多个应用程序运行在一个集群中,并将资源按需分配给它们,这大大提高了资源利用率,其次,YARN允许各类短作业和长服务混合部署在一个集群中,并提供了容错、资源隔离及负载均衡等方面的支持,这大大简化了作业和服务的部署和管理成本。 之后我们会详细介绍YARN。 首先,如果要里用YARN提交任务,我们需要先启动YARN。修改etc/hadoop/mapred-site.xml:
代码语言:javascript复制<configuration>
<property>
<name>mapreduce.framework.namename>
<value>yarnvalue>
property>
configuration>
之后修改YARN配置etc/hadoop/yarn-site.xml:
代码语言:javascript复制<configuration>
<property>
<name>yarn.nodemanager.aux-servicesname>
<value>mapreduce_shufflevalue>
property>
configuration>
启动YARN:
代码语言:javascript复制>sbin/start-yarn.sh
访问http://你的机器ip:8808,可以看到YARN控制台 就可以以YARN的方式提交MapReduce任务。 关闭YARN:
代码语言:javascript复制>sbin/stop-yarn.sh
1.4 Hadoop集群安装
在Hadoop集群中,一般包括如下七个元素: HDFS: NameNode, SecondaryNameNode, 还有DataNode YARN:ResourceManager, NodeManager, 还有WebAppProxy 如果需要用到MapReduce,则MapReduce历史服务器也需要用到。 我们通过修改etc/hadoop/hadoop-env.sh, etc/hadoop/mapred-env.sh and etc/hadoop/yarn-env.sh这三个脚本来修改一些关于JVM的配置。 这里我们对于云环境,稍微修改限制下JVM heap size,防止内存溢出。
第一步,首先配置每台机器的host文件。对于每台机器,执行 vim /etc/hosts 添加:
代码语言:javascript复制#三台机器/etc/hosts文件配置,nosql1作为主,nosql2作为从
10.202.7.184 nosql1
10.202.7.185 nosql2
10.202.7.186 nosql3
之后,在每台机器上分别执行:
代码语言:javascript复制ping nosql1
ping nosql2
ping nosql3
看网络是否通畅。
第二步,添加hadoop用户,配置两台机器ssh无密登陆。 几台机器中的hadoop用户以及hadoop存放路径需要相同,否则hadoop HDFS会找不到节点。 SSH无密码原理:Master作为客户端,要实现无密码公钥认证,连接到服务器Salve上时,需要在Master上生成一个密钥对,包括一个公钥和一个私钥,而后将公钥复制到所有的Slave上。当Master通过SSH连接Salve时,Salve就会生成一个随机数并用Master的公钥对随机数进行加密,并发送给Master。Master收到加密数之后再用私钥解密,并将解密数回传给Slave,Slave确认解密数无误之后就允许Master进行连接了。这就是一个公钥认证过程,其间不需要用户手工输入密码。 以nosql1举例,首先在master上创建hadoop用户,属于hadoop组:
代码语言:javascript复制#创建hadoop组
groupadd hadoop
#创建具有管理员权限的用户hadoop,属于hadoop组,同时自动创建用户home目录
useradd -g hadoop -r -m hadoop
#修改hadoop密码
passwd hadoop
#切换到hadoop用户
su - hadoop
之后,我们需要生成SSH秘钥:
代码语言:javascript复制#生成公钥私钥至~/.ssh/id_dsa
ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
#添加到授权秘钥
cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
#更改权限为仅限当前用户读写
chmod 0600 ~/.ssh/authorized_keys
验证是否可以无密登陆本机:
代码语言:javascript复制ssh localhost
在slave上添加同样的用户后,从master将公钥拷贝过去:
代码语言:javascript复制ssh-copy-id hadoop@nosql2
ssh-copy-id hadoop@nosql3
验证成功后,即可无密登陆nosql2和nosql3
代码语言:javascript复制ssh nosql2
ssh nosql3
之后以相同的方式配置slave无密登陆master即可 注意:每次修改host中的相关DNS信息后,需要清除掉之前的SSH公钥秘钥,重新生成
第三步,配置Hadoop。 如下配置: etc/hadoop/core-site.xml:
代码语言:javascript复制<configuration>
<property>
<name>fs.defaultFSname>
<value>hdfs://nosql1:9000value>
property>
<property>
<name>io.file.buffer.sizename>
<value>131072value>
property>
configuration>
etc/hadoop/hdfs-site.xml:
代码语言:javascript复制<configuration>
<property>
<name>dfs.replicationname>
<value>1value>
property>
<property>
<name>dfs.namenode.name.dirname>
<value>/home/hadoop/nnData1,/home/hadoop/nnData2value>
property>
<property>
<name>dfs.blocksizename>
<value>268435456value>
property>
<property>
<name>dfs.namenode.handler.countname>
<value>5value>
property>
<property>
<name>dfs.datanode.data.dirname>
<value>/home/hadoop/dnData1,/home/hadoop/dnData2,/home/hadoop/dnData3value>
property>
<property>
<name>dfs.namenode.secondary.http-addressname>
<value>nosql2:9001value>
property>
configuration>
etc/hadoop/mapred-site.xml:
代码语言:javascript复制<configuration>
<property>
<name>mapreduce.framework.namename>
<value>yarnvalue>
property>
<property>
<name>mapreduce.jobhistory.addressname>
<value>nosql1:10020value>
property>
<property>
<name>mapreduce.jobhistory.webapp.addressname>
<value>nosql1:19888value>
property>
configuration>
etc/hadoop/yarn-site.xml:
代码语言:javascript复制<configuration>
<property>
<name>yarn.nodemanager.aux-servicesname>
<value>mapreduce_shufflevalue>
property>
<property>
<name>yarn.nodemanager.aux-services.mapreduce.shuffle.classname>
<value>org.apache.hadoop.mapred.ShuffleHandlervalue>
property>
<property>
<name>yarn.resourcemanager.addressname>
<value>nosql1:8032value>
property>
<property>
<name>yarn.resourcemanager.scheduler.addressname>
<value>nosql1:8030value>
property>
<property>
<name>yarn.resourcemanager.resource-tracker.addressname>
<value>nosql1:8031value>
property>
<property>
<name>yarn.resourcemanager.admin.addressname>
<value>nosql1:8033value>
property>
<property>
<name>yarn.resourcemanager.webapp.addressname>
<value>nosql1:8088value>
property>
configuration>
etc/hadoop/slaves:
代码语言:javascript复制nosql2
nosql3
第四步,修改脚本 至少要修改JAVA_HOME为你的JAVA安装地址 在hadoop-env.sh,mapred-env.sh,yarn-env.sh添加或修改:
代码语言:javascript复制export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.101-2.6.6.1.el7_2.x86_64/jre
第五步,格式化,启动集群 首先将master上配置好的hadoop拷贝传输到slave上,注意master和slave上的hadoop路径一定要一致:
代码语言:javascript复制scp –r hadoop-2.7.2 hadoop@nosql2:/home/hadoop/
scp –r hadoop-2.7.2 hadoop@nosql3:/home/hadoop/
传输完成,在master上执行:
代码语言:javascript复制>bin/hdfs namenode -format
代码语言:javascript复制sbin/start-all.sh
启动完成后,在主机执行jps,可以看到:
代码语言:javascript复制7826 NameNode
8662 Jps
8092 ResourceManager
在从机上执行,可以看到:
代码语言:javascript复制30742 Jps
29552 SecondaryNameNode
29638 NodeManager
29425 DataNode
访问:http://nosql1:50070/查看HDFS集群状况 访问:http://nosql1:8088/cluster查看任务状况 接着测试之前的MapReduce任务:
代码语言:javascript复制bin/hdfs dfs -mkdir -p /test/input
bin/hdfs dfs -put ./etc/hadoop/hdfs-site.xml /test/input
bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.2.jar grep /test/input /test/output 'dfs[a-z.] '
观察结果即可:
问题整理:
1、Map-Reduce成功,结果失败:Job history中:
代码语言:javascript复制2014-06-04 13:17:20,060 ERROR [Thread-62] org.apache.hadoop.mapreduce.v2.app.rm.RMContainerAllocator: Exception while unregistering
java.lang.NullPointerException
at org.apache.hadoop.mapreduce.v2.util.MRWebAppUtil.getApplicationWebURLOnJHSWithoutScheme(MRWebAppUtil.java:133)
at org.apache.hadoop.mapreduce.v2.util.MRWebAppUtil.getApplicationWebURLOnJHSWithScheme(MRWebAppUtil.java:148)
at org.apache.hadoop.mapreduce.v2.app.rm.RMCommunicator.doUnregistration(RMCommunicator.java:207)
at org.apache.hadoop.mapreduce.v2.app.rm.RMCommunicator.unregister(RMCommunicator.java:177)
at org.apache.hadoop.mapreduce.v2.app.rm.RMCommunicator.serviceStop(RMCommunicator.java:250)
at org.apache.hadoop.mapreduce.v2.app.rm.RMContainerAllocator.serviceStop(RMContainerAllocator.java:255)
at org.apache.hadoop.service.AbstractService.stop(AbstractService.java:221)
at org.apache.hadoop.service.ServiceOperations.stop(ServiceOperations.java:52)
at org.apache.hadoop.mapreduce.v2.app.MRAppMaster$ContainerAllocatorRouter.serviceStop(MRAppMaster.java:817)
at org.apache.hadoop.service.AbstractService.stop(AbstractService.java:221)
at org.apache.hadoop.service.ServiceOperations.stop(ServiceOperations.java:52)
at org.apache.hadoop.service.ServiceOperations.stopQuietly(ServiceOperations.java:80)
at org.apache.hadoop.service.CompositeService.stop(CompositeService.java:159)
at org.apache.hadoop.service.CompositeService.serviceStop(CompositeService.java:132)
at org.apache.hadoop.service.AbstractService.stop(AbstractService.java:221)
at org.apache.hadoop.mapreduce.v2.app.MRAppMaster.shutDownJob(MRAppMaster.java:548)
at org.apache.hadoop.mapreduce.v2.app.MRAppMaster$JobFinishEventHandler$1.run(MRAppMaster.java:599)
表明:某个host配置有问题,检查*-site.xml中所有的域名是否正确
2、都提示成功,但是找不到datanode,但是jps中有datanode,datanode日志报错:
代码语言:javascript复制2016-07-19 16:38:13,817 INFO org.apache.hadoop.hdfs.server.datanode.DataNode: Block pool BP-896553954-10.202.44.205-1468914346523 (Datanode Uuid null) service to /10.202.44.205:9000 beginning handshake with NN
2016-07-19 16:38:13,820 ERROR org.apache.hadoop.hdfs.server.datanode.DataNode: Initialization failed for Block pool BP-896553954-10.202.44.205-1468914346523 (Datanode Uuid null) service to /10.202.44.205:9000 Datanode denied communication with namenode because hostname cannot be resolved (ip=10.202.44.206, hostname=10.202.44.206): DatanodeRegistration(0.0.0.0:50010, datanodeUuid=9ef57feb-d3a5-47c4-9ed2-db386e4969a8, infoPort=50075, infoSecurePort=0, ipcPort=50020, storageInfo=lv=-56;cid=CID-d5340873-3047-4a6a-89db-8aba9ee5846b;nsid=463107860;c=0)
at org.apache.hadoop.hdfs.server.blockmanagement.DatanodeManager.registerDatanode(DatanodeManager.java:863)
at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.registerDatanode(FSNamesystem.java:4528)
at org.apache.hadoop.hdfs.server.namenode.NameNodeRpcServer.registerDatanode(NameNodeRpcServer.java:1285)
at org.apache.hadoop.hdfs.protocolPB.DatanodeProtocolServerSideTranslatorPB.registerDatanode(DatanodeProtocolServerSideTranslatorPB.java:96)
at org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos$DatanodeProtocolService$2.callBlockingMethod(DatanodeProtocolProtos.java:28752)
at org.apache.hadoop.ipc.ProtobufRpcEngine$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine.java:616)
at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:969)
at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2049)
at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2045)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:415)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1657)
at org.apache.hadoop.ipc.Server$Handler.run(Server.java:2043)
表明:域名填写的是IP,改成域名。
3、执行ssh-copy-id hadoop@nosql2 提示:/usr/bin/ssh-copy-id: ERROR: No identities found 改成指定公钥文件的命令: ssh-copy-id -i ~/.ssh/id_dsa.pub nosql2
4、远程登录被拒绝: 设置允许远程登录,linux一般都通过ssh远程连接,修改/etc/ssh/sshd_config文件 在结尾处添加 AllowUsers 用户名,如 AllowUsers zhangsan 保存,退出 重启ssh服务,service sshd restart