项目说明
首先需要说明的是hadoop集群的情况。一共有5台服务器,其中一台作为namenode,另四台是datenode节点。项目具体什么内容不便透露,但是用hadoop集群跑了12个小时,跑完的结果文件有280G,共几亿条数据,也算和大数据沾点边吧。写这篇博客的目的也是为了记录下期间遇到的问题及解决办法,不至于以后再用的时候仍是一片茫然。
hadoop
hadoop的基本概念这里不做介绍。首先说明的是在hadoop安装过程中,需要修改的配置文件。首先第一步要做的是自然是使集群内的节点能够互联。其次,要修改的配置文件有master, slaves, hadoop-env.sh, yarn-env.sh, core-site.xml, hdfs-site.xml, mapred-site.xml.template, yarn-site.xml
。配置好这些文件,一些简单的hadoop程序如wordcount就能顺利跑起来。
在这里遇到的问题是,一旦数据量变大,hadoop程序的yarn就会经常挂掉然后重启,接着就会报错,内容是Application attempt xxx doesn’t exit in ApplicationMasterService cache,然后job的状态就会变成accepted。造成这个问题的原因主要是给每个任务分配的内存不够大。解决这个问题的办法也很简单,就是将配置文件中与内存分配有关的参数调整一下,如yarn-site.xml文件,配置如下
//nodemanager所在的单节点内存最大值
<property>
<description>Amount of physical memory, in MB, that can be allocated
for containers.</description>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>50480</value>
</property>
//给每一个container设置的最小内存
<property>
<description>The minimum allocation for every container request at the RM,in MBs. Memory requests lower than this won't take effect,and the specified value will get allocated at minimum.</description>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>1500</value>
</property>
//给每一个container设置的最大内存
<property>
<description>The maximum allocation for every container request at the RM,
in MBs. Memory requests higher than this won't take effect,
and will get capped to this value.</description>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>8192</value>
</property>
以及mapred-site.xml文件的配置
//mapreduce任务调度框架设置为yarn
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
//map memory
<property>
<name>mapreduce.map.memory.mb</name>
<value>1500</value>
</property>
在修改了这些配置文件后,hadoop程序就能成功地结束了。
zookeeper
zookeeper的配置比较简单,只有一个zoo.cfg一个配置文件,需要修改的参数如下
# The number of milliseconds of each tick
tickTime=2000
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/home/hadoop/zookeeperData
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
这里需要说明的是,hbase的运行必须依赖于zookeeper,虽然hbase有其内置的zookeeper,但是建议独立部署一个zookeeper。每个节点都应该部署zookeeper,且在启动hbase之前,应该首先启动每个节点上的zookeeper。
hbase
hbase是在hdfs文件系统之上的一个面向列的数据库系统。其配置也比较简单,首先是hbase-env.sh,需要给出java路径以及设置是否让hbase管理内置的zookeeper,这里设置为false,使用外部的zookeeper,配置文件如下:
# The java implementation to use. Java 1.7+ required.
export JAVA_HOME=/home/hadoop/jdk/
# Tell HBase whether it should manage it's own instance of Zookeeper or not.
export HBASE_MANAGES_ZK=false
其次就要配置regionservers文件,告诉hbase哪些是数据节点,文件如下
hadoop1
hadoop2
hadoop3
hadoop4
最关键的一个配置文件是hbase-site.xml,其中参数如下
-->
<configuration>
<property>
<name>hbase.rootdir</name>
<value>hdfs://hadoop5:9000/hbase</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<property>
<name>hbase.zookeeper.quorum</name>
<value>hadoop5</value>
</property>
<property>
<name>hbase.zookeeper.property.clientPort</name>
<value>2181</value>
</property>
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/home/hadoop/zookeeperData</value>
</property>
</configuration>
但是这样子配置好之后,小规模的数据可以跑起来,但是跑大规模的数据,会出现timedout after 600 secs,以及exited with code 143等错误。具体解决办法仍在摸索。
其他
另一个很关键的操作是将hadoop及hbase需要的各种jar包加入到classpath中,这也是为了使用的方便。导入hadoop jar包实在yarn-site.xml文件里,属性如下
<property>
<name>yarn.application.classpath</name>
<value>
/home/hadoop/hadoop/etc/*,
/home/hadoop/hadoop/etc/hadoop/*,
/home/hadoop/hadoop/lib/*,
/home/hadoop/hadoop/share/hadoop/common/*,
/home/hadoop/hadoop/share/hadoop/common/lib/*,
/home/hadoop/hadoop/share/hadoop/mapreduce/*,
/home/hadoop/hadoop/share/hadoop/mapreduce/lib/*,
/home/hadoop/hadoop/share/hadoop/hdfs/*,
/home/hadoop/hadoop/share/hadoop/hdfs/lib/*,
/home/hadoop/hadoop/share/hadoop/yarn/*,
/home/hadoop/hadoop/share/hadoop/yarn/lib/*,
/home/hadoop/hbase/lib/*
</value>
</property>
导入hbase jar包是在hadoop-env.sh配置文件里,代码如下:
export HBASE_HOME=/home/hadoop/hbase/
for f in $HBASE_HOME/lib/*.jar; do
if [ "$HADOOP_CLASSPATH" ]; then
export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:$f
else
export HADOOP_CLASSPATH=$f
fi
done