本文详细介绍了基于centos7的Hadoop集群的搭建过程,给出了Hadoop的基础知识和项目搭建的流程,搭建了一个master结点和两个slave结点的Hadoop集群,在master和slave服务器上配置HDFS(hadoop分布式文件系统) ,HBase(集群数据库),zookeeper(集群维护服务),以及 kafka(消息队列),同时详细给出搭建过程和测试结果,并对搭建过程遇到的bug进行详细的记录
Hadoop是由java语言编写的,在分布式服务器集群上存储海量数据并运行分布式分析应用的开源框架,其核心部件是HDFS与MapReduce。
HDFS是一个分布式文件系统:引入存放文件元数据信息的服务器Namenode和实际存放数据的服务器Datanode,对数据进行分布式储存和读取。
MapReduce是一个分布式计算框架:MapReduce的核心思想是把计算任务分配给集群内的服务器里执行。通过对计算任务的拆分(Map计算/Reduce计算)再根据任务调度器(JobTracker)对任务进行分布式计算。
大数据存储:分布式存储
日志处理:擅长日志分析
ETL:数据抽取到oracle、mysql、DB2、mongdb及主流数据库
机器学习: 比如Apache Mahout项目
搜索引擎:Hadoop + lucene实现
数据挖掘:目前比较流行的广告推荐,个性化广告推荐
Hadoop是专为离线和大规模数据分析而设计的,并不适合那种对几个记录随机读写的在线事务处理模式。
Hadoop集群的搭建
无论是在windows上装几台虚拟机玩Hadoop,还是真实的服务器来玩,说简单点就是把Hadoop的安装包放在每一台服务器上,改改配置,启动就完成了Hadoop集群的搭建。
上传文件到Hadoop集群,实现文件存储
Hadoop集群搭建好以后,可以通过web页面查看集群的情况,还可以通过Hadoop命令来上传文件到hdfs集群,通过Hadoop命令在hdfs集群上建立目录,通过Hadoop命令删除集群上的文件等等。
编写map/reduce程序,完成计算任务
通过集成开发工具(例如eclipse)导入Hadoop相关的jar包,编写map/reduce程序,将程序打成jar包扔在集群上执行,运行后出计算结果。
由于 hadoop 框架的启动是依赖 java 环境,因此需要准备 jdk 环境,本例中使用的 jdk8 在/home/min/tar目录下进行演示,使用 jdk-8u202-linux-x64.tar.gz 解压jdk ,然后使用 mv jdk1.8.0_201 jdk8 将目录改名
export JAVA_HOME=/home/min/tar/jdk8
export CLASSPATH=.$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$JAVA_HOME/bin:$PATH
配置好以后使用 source /etc/profile 重新加载配置文件,使用 java -version 测试jdk 配置是否成功
本例中Linux操作系统为为 centos 7,使用自带的 hostnamectl 修改hostname
//192.168.19.200 上执行
hostnamectl set-hostname master
//192.168.19.201 上执行
hostnamectl set-hostname slave1
//192.168.19.202 上执行
hostnamectl set-hostname slave2
192.168.19.200 master
192.168.19.201 slave1
192.168.19.202 slave2
hadoop 集群是通过主节点的 rpc 调用来对整个集群进行统一的操作管理,如果不配置免密登录,在每次启动集群时需要输入每个从节点的机器密码,免密登录很好的解决此问题
ssh-keygen -t rsa
2. 将本机的公钥拷贝到其余两台机器和本机,以 master 机器为例
ssh-copy-id -i .ssh/id_rsa.pub slave1
ssh-copy-id -i .ssh/id_rsa.pub slave2
ssh-copy-id -i .ssh/id_rsa.pub master
将三台机器公钥都拷贝完成后,会在 ~/.ssh 文件下生成 authorized_keys,known_hosts 两个文件,存放的是一些免密登录的信息
关闭防火墙
关闭防火墙,并且设置开机不启动
systemctl stop firewalld.service
systemctl disable firewalld.service
使用命令 tar -zxvf hadoop-3.1.3.tar.gz 解压 hadoop 压缩包
在三台机器上都配置 HADOOP_HOME ,vi /etc/profile 添加图中内容,保存后,使用 source /etc/profile 使配置文件生效
export JAVA_HOME=/home/min/tar/jdk-11.0.4
export CLASSPATH=. J A V A H O M E / l i b / d t . j a r : JAVA_HOME/lib/dt.jar: JAVAHOME/lib/dt.jar:JAVA_HOME/lib/tools.jar
export HADOOP_HOME=/home/min/tar/hadoop-3.1.3
export PATH=JAVA_HOME/bin: P A T H : PATH: PATH:HADOOP_HOME/bin
修改Hadoop目录下的 etc/hadoop文件夹中的core-site.xml,hadoop-env.sh,hdfs-site.xml,mapred-site.xml,yarn-site.xml,workers。先修改 master 节点上的配置文件,然后通过远程复制到 slave1 与 slave2
将 hadoop 目录从 master 拷贝到 slave1 与 slave2,由于之前配置了免密登录,所以不需要输入密码即可完成拷贝
scp -qr /home/min/tar/hadoop-3.1.3 slave1:/home/min/tar
scp -qr /home/min/tar/hadoop-3.1.3 slave2:/home/min/tar
创建临时文件目录 (三台机器都需创建), 创建的目录对应于 第六步 hdfs-site.xml 中配置的目录
mkdir -p /data/hadoop/hdfs/data
mkdir -p /data/hadoop/hdfs/name
在master结点上的hadoop的安装目录下的 bin 目录下执行以下命令
./hdfs namenode -format
注意:
如果需要重新格式化NameNode,需要先将原来NameNode和DataNode下的文件全部删除,不然会报错,NameNode和DataNode所在目录是在core-site.xml中hadoop.tmp.dir、dfs.namenode.name.dir、dfs.datanode.data.dir属性配置的。
因为每次格式化,默认是创建一个集群ID,并写入NameNode和DataNode的VERSION文件中(VERSION文件所在目录为hdfs/name/current 和 hdfs/data/current),重新格式化时,默认会生成一个新的集群ID,如果不删除原来的目录,会导致namenode中的VERSION文件中是新的集群ID,而DataNode中是旧的集群ID,不一致时会报错。
主节点上在hadoop目录下执行:
./sbin/start-all.sh
以下几个web页面是否可以正常打开(注意关闭防火墙)
http://192.168.19.200:8088/cluster hadoop 集群信息
http://192.168.19.200:9870/dfshealth.html#tab-overview hdfs 地址
http://192.168.19.200:9864/datanode.html dataNode 地址
http://192.168.19.200:8042/node nodeManager 地址
http://192.168.19.200:9868/status.html secondaryNameNode
Good morning, everyone. Thank you for taking your time. It’s really my honor to have this opportunity to take part in this interview. Now, I would like to introduce myself briefly.
hadoop fs -put wordtest /wordtest
hadoop jar /home/min/hadoop-3.1.3/share/hadoop/mapreduce
/hadoop-mapreduce-examples-3.1.3.jar wordcount /wordtest /result
解压zookeeper安装包,并重命名为zookeeper,然后进行以下操作。
进入~/zookeeper/conf目录,拷贝zoo_sample.cfg文件为zoo.cfg
cp zoo_sample.cfg zoo.cfg
对zoo.cfg进行编辑,内容如下:
dataDir=/home/min/tar/zookeeper/data
server.1=192.168.19.200:2888:3888
server.2=192.168.19.201:2888:3888
server.3=192.168.19.202:2888:3888
在dataDir目录下新建myid文件,输入一个数字(master为1,slave1为2,slave2为3),比如master主机上的操作如下:
mkdir /home/min/tar/zookeeper/data
echo "1" > /home/min/tar/zookeeper/data/myid
同样,也可以使用scp命令进行远程复制,只不过要修改每个节点上myid文件中的数字
scp -qr /home/min/tar/zookeeper slave1:/home/min/tar
scp -qr /home/min/tar/zookeeper slave2:/home/min/tar
注意事项:
如果启动报类似异常:QuorumCnxManager@384] – Cannot open channel to 2 at election address slave-02/192.168.0.178:3888 是可以忽略的,因为该服务启动时会尝试连接所有节点,而其他节点尚未启动。通过后面部分可以看到,集群在选出一个Leader后,最后稳定 了。其他结点可能也出现类似问题,属于正常。
将hbase安装包进行解压,并重命名为hbase,然后进入habase的bin目录进行如下配置。
export JAVA_HOME=/home/min/tar/jdk-11.0.4
export HBASE_CLASSPATH=/home/min/tar/hadoop-3.1.3/etc/hadoop/
export HBASE_MANAGES_ZK=false
hbase.rootdir
hdfs://master:9000/hbase
hbase.master
master
hbase.cluster.distributed
true
hbase.zookeeper.property.clientPort
2181
hbase.zookeeper.quorum
master,slave1,slave2
zookeeper.session.timeout
60000000
dfs.support.append
true
master
slave1
slave2
将整个hbase安装目录都远程拷贝到所有slave服务器:
scp -qr /home/min/tar/hbase slave1:/home/min/tar
scp -qr /home/min/tar/hbase slave2:/home/min/tar
./hbase/bin/start-hbase.sh
将kafka安装包进行解压,并重命名为kafka,对config目录下的server.properties添加配置
broker.id=01
host.name=master
zookeeper.connect=master:2181,slave1:2181,slave2:2181
scp -qr /home/min/tar/kafka slave1:/home/min/tar
将broker id改为02和03
由于没有配置环境,需要再kafka目录下启动
./bin/kafka-server-start.sh -daemon config/server.properties
启动ZooKeeper
zookeeper/bin/zkServer.sh start
启动hadoop
./hadoop-3.1.3/sbin/start-all.sh
启动hbase
./hbase/bin/start-hbase.sh
启动kafka
./bin/kafka-server-start.sh -daemon config/server.properties
./bin/kafka-topics.sh --create --zookeeper master:2181,slave1:2181,slave2:2181 --replication-factor 3 --partitions 3 --topic test
Created topic "test".
./bin/kafka-topics.sh --list --zookeeper localhost:2181
./bin/kafka-console-producer.sh --broker-list master:9092,slave1:9092,slave2:9092 --topic test
./bin/kafka-console-consumer.sh --bootstrap-server master:9092,slave1:9092,slave2:9092 --from-beginning --topic test
这个测试是通过HBase Shell 命令来完成一个 HBase 表的创建、插入、查找、删除操作。
Starting datanodes
ERROR: Refusing to run as root: root account is not found. Aborting.
解决办法:
在hadoop/etc/hadoop/hadoop-env.sh中的配置文件中的root多打了个空格,更正即可
当我们多次格式化文件系统(hadoop namenode -format)时,会出现DataNode无法启动。
多次启动中发现有NameNode节点,并没有DataNode节点
如图所示:
经查看相关日志发现问题所在:
datanode的clusterID 和 namenode的clusterID 不匹配。
当我们执行文件系统格式化时,会在namenode数据文件夹(即配置文件中dfs.name.dir在本地系统的路径)中保存一个current/VERSION文件,记录namespaceID,标志了所有格式化的namenode版本。如果我们频繁的格式化namenode,那么datanode中保存(即dfs.data.dir在本地系统的路径)的current/VERSION文件只是你地第一次格式化时保存的namenode的ID,因此就会造成namenode和datanode之间的ID不一致。
解决办法:
删除DataNode的所有资料及将集群中每个datanode节点的/dfs/data/current中的VERSION删除,然后重新执行hadoop namenode -format进行格式化,重启集群,错误消失。
出现该问题的原因:
在第一次格式化dfs后,启动并使用了hadoop,后来又重新执行了格式化命令(hdfs namenode -format),这时namenode的clusterID会重新生成,而datanode的clusterID 保持不变。
./sbin/start-yarn.sh
jps上找不到 resourceManager 和 nodeManger的进程, 查询日志发现是jdk版本问题
解决办法: 从jdk9以后 java9默认禁用访问许多javax. * API。更换jdk8即可
如下图,提示"Failed to retrieve data from /webhdfs/v1/?op=LISTSTATUS:Server Error“,也无法透过Web界面上传文件
经过一番查找之后(可找Hadoop的Log日志)确认是Jdk的版本问题,更换jdk版本为 jdk8
这件事得到一个教训,软件并不是版本越高越好