文章目录
0.前置条件
在/etc/hosts里面配置节点和别名(master,node1.node2)
三个节点配置免密登陆的ssh
1. 安装JDK
JDK就是java和java的开发环境的合称
官网:
https://www.java.com/zh-CN/download/help/index_installing.html
wget https://download.java.net/openjdk/jdk8u41/ri/openjdk-8u41-b04-linux-x64-14_jan_2020.tar.gz
mkdir /usr/java
tar zxvf openjdk-8u41-b04-linux-x64-14_jan_2020.tar.gz -C /usr/java
sudo vim /etc/profile
export JAVA_HOME=/usr/java/java-se-8u41-ri
export JRE_HOME=$JAVA_HOME/jre
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
source /etc/profile
java -version
jps
安装好java后,在/etc/profile或者 ~/.bashrc下添加环境变量,后source /etc/profile 或者 source ~/.bashrc 即可
/etc/profile和~/.bashrc的区别是 /etc/profile 是全局的,也就是你在任何一个用户下执行都可以, ~/.bashrc 这个是某个用户所单独拥有的,像java这样的每个用户都需要的 写在 /etc/profile下即可
jre是运行环境,只是运行java的,不包含工具包
开发包是jdk,包含工具包和运行环境
安装完成之后,按照同样的方式在node节点上都安装上jdk
2. 安装hadoop
2.1 安装
https://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/common/
wget https://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/common/hadoop-3.3.0/hadoop-3.3.0.tar.gz
tar zxvf hadoop-3.3.0.tar.gz -C /usr/local/
cd /usr/local/
mv hadoop-3.3.0 hadoop
vim ~/.bashrc
export HADOOP_HOME=/usr/local/hadoop
export CLASSPATH=$($HADOOP_HOME/bin/hadoop classpath):$CLASSPATH
export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
export JAVA_LIBRARY_PATH=$HADOOP_HOME/lib/native
source ~/.bashrc
hadoop version
Hadoop 可以在单节点上以伪分布式的方式运行,Hadoop 进程以分离的 Java 进程来运行,节点既作为 NameNode 也作为 DataNode,同时,读取的是 HDFS 中的文件。Hadoop 的配置文件位于 /usr/local/hadoop/etc/hadoop/ 中,伪分布式需要修改2个配置文件 core-site.xml 和 hdfs-site.xml 。Hadoop的配置文件是 xml 格式,每个配置以声明 property 的 name 和 value 的方式来实现。首先将jdk1.7的路径添(export JAVA_HOME=/usr/lib/jvm/java )加到hadoop-env.sh文件
2.2 hadoop修改配置文件
添加环境变量
vim /usr/local/hadoop/etc/hadoop/hadoop-env.sh
export JAVA_HOME=/usr/java/java-se-8u41-ri
source ~/.bashrc
修改core-site.xml文件:
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://master:8020</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/usr/local/hadoop/hadoopDatas/tempDatas</value>
</property>
<!-- 缓冲区大小,实际工作中根据服务器性能动态调整 -->
<property>
<name>io.file.buffer.size</name>
<value>1024</value>
</property>
<property>
<name>fs.trash.interval</name>
<value>10080</value>
<description>检查点被删除后的分钟数。 如果为零,垃圾桶功能将被禁用。
该选项可以在服务器和客户端上配置。 如果垃圾箱被禁用服务器端,则检查客户端配置。
如果在服务器端启用垃圾箱,则会使用服务器上配置的值,并忽略客户端配置值。</description>
</property>
<property>
<name>fs.trash.checkpoint.interval</name>
<value>0</value>
<description>垃圾检查点之间的分钟数。 应该小于或等于fs.trash.interval。
如果为零,则将该值设置为fs.trash.interval的值。 每次检查指针运行时,
它都会从当前创建一个新的检查点,并删除比fs.trash.interval更早创建的检查点。</description>
</property>
</configuration>
接下来修改配置文件 hdfs-site.xml
<configuration>
<property>
<name>dfs.hosts</name>
<value>/usr/local/hadoop/etc/hadoop/accept_host</value>
</property>
<property>
<name>dfs.hosts.exclude</name>
<value>/usr/local/hadoop/etc/hadoop/deny_host</value>
</property>
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>master:50090</value>
</property>
<property>
<name>dfs.namenode.http-address</name>
<value>master:50070</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:///usr/local/hadoop/hadoopDatas/namenodeDatas</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///usr/local/hadoop/hadoopDatas/datanodeDatas</value>
</property>
<property>
<name>dfs.namenode.edits.dir</name>
<value>file:///usr/local/hadoop/hadoopDatas/dfs/nn/edits</value>
</property>
<property>
<name>dfs.namenode.checkpoint.dir</name>
<value>file:///usr/local/hadoop/hadoopDatas/dfs/snn/name</value>
</property>
<property>
<name>dfs.namenode.checkpoint.edits.dir</name>
<value>file:///usr/local/hadoop/hadoopDatas/dfs/nn/snn/edits</value>
</property>
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
<property>
<name>dfs.blocksize</name>
<value>134217728</value>
</property>
</configuration>
接下来修改配置文件 yarn-site.xml
<configuration>
<property>
<name>yarn.resourcemanager.hostname</name>
<value>master</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<property>
<name>yarn.log.server.url</name>
<value>http://master:19888/jobhistory/logs</value>
</property>
<!--多长时间聚合删除一次日志 此处-->
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>2592000</value><!--30 day-->
</property>
<!--时间在几秒钟内保留用户日志。只适用于如果日志聚合是禁用的-->
<property>
<name>yarn.nodemanager.log.retain-seconds</name>
<value>604800</value><!--7 day-->
</property>
<!--指定文件压缩类型用于压缩汇总日志-->
<property>
<name>yarn.nodemanager.log-aggregation.compression-type</name>
<value>gz</value>
</property>
<!-- nodemanager本地文件存储目录-->
<property>
<name>yarn.nodemanager.local-dirs</name>
<value>/usr/local/hadoop/hadoopDatas/yarn/local</value>
</property>
<!-- resourceManager 保存最大的任务完成个数 -->
<property>
<name>yarn.resourcemanager.max-completed-applications</name>
<value>1000</value>
</property>
</configuration>
接下来修改配置文件 mapred-site.xml
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>mapreduce.job.ubertask.enable</name>
<value>true</value>
</property>
<property>
<name>mapreduce.jobhistory.address</name>
<value>master:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>master:19888</value>
</property>
</configuration>
创建上面配置文件中声明的data路径
cd /usr/local/hadoop
mkdir -p hadoopDatas/{tempDatas,namenodeDatas,datanodeDatas,dfs/nn/edits,dfs/snn/name,dfs/nn/snn/edits}
声明node节点
hadoop3.0 slaves改为works
vim /usr/local/hadoop/etc/hadoop/workers
master
node1
复制hadoop目录到node节点服务器(slaves服务器)
这里注意,需要添加java的环境和hadoop的路径到node节点的/etc/profile文件中,并通过source生效,相当于全拷贝一份到节点服务器
scp -r /usr/local/hadoop node2:/usr/local/
如果你是root用户配置和运行的hadoop,则需要配置下面的文件
在/hadoop/sbin路径下:
将start-dfs.sh,stop-dfs.sh两个文件顶部添加以下参数
#!/usr/bin/env bash
HDFS_DATANODE_USER=root
HADOOP_SECURE_DN_USER=hdfs
HDFS_NAMENODE_USER=root
HDFS_SECONDARYNAMENODE_USER=root
还有,start-yarn.sh,stop-yarn.sh顶部也需添加以下:
#!/usr/bin/env bash
YARN_RESOURCEMANAGER_USER=root
HADOOP_SECURE_DN_USER=yarn
YARN_NODEMANAGER_USER=root
Hadoop 的运行方式是由配置文件决定的(运行 Hadoop 时会读取配置文件),因此如果需要从伪分布式模式切换回非分布式模式,需要删除 core-site.xml 中的配置项。此外,伪分布式虽然只需要配置 fs.defaultFS 和 dfs.replication 就可以运行(可参考官方教程),不过若没有配置 hadoop.tmp.dir 参数,则默认使用的临时目录为 /tmp/hadoo-hadoop,而这个目录在重启时有可能被系统清理掉,导致必须重新执行 format 才行。所以我们进行了设置,同时也指定 dfs.namenode.name.dir 和 dfs.datanode.data.dir,否则在接下来的步骤中可能会出错。
2.3启动hadoop服务
配置完成后,执行 NameNode 的格式化
./bin/hdfs namenode -format
启动namenode和datanode进程,并查看启动结果
./sbin/start-dfs.sh
jps
启动完成后,可以通过命令 jps 来判断是否成功启动,若成功启动则会列出如下进程: “NameNode”、”DataNode” 和 “SecondaryNameNode”
2.4 可能报错
WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform
解决思路:https://blog.csdn.net/qq_41541801/article/details/82413776
hadoop ERROR: Attempting to operate on hdfs namenode as root ERROR: but there is no HDFS_NAMENODE_US
解决思路:https://blog.csdn.net/lglglgl/article/details/80553828
Permission denied
解决思路:
cd ~/.ssh
mkdir backup && mv id_rsa* backup
ssh-keygen -t rsa
#注意不要输入密码,即免密登陆
cat id_rsa.pub >> authorized_keys
登陆被管理的服务器,进入需要远程登陆的用户目录,把公钥放到用户目录的 .ssh 这个目录下(如果目录不存在,需要创建~/.ssh目录,并把目录权限设置为700),把公钥改名为authorized_keys,并且把它的用户权限设成600
put: File /home/wget-log._COPYING_ could only be written to 0 of the 1 minReplication nodes. There are 0 datanode(s) running and 0 node(s) are excluded in this operation.
解决思路
解决办法是:找到hadoop安装目录下 hadoop-2.4.1/data/dfs/data里面的current文件夹删除,然后从新执行一下 hadoop namenode -format,再使用start-dfs.sh和start-yarn.sh 重启一下hadoop
用jps命令看一下就可以看见datanode已经启动了
3. hadoop集群的增删改查
3.1 增加节点
比如增加节点node2,前置的条件都是一样的:
1.配置JDK和hadoop,并且加到环境中
2.所有节点设置/etc/hosts,并且设置成ssh免密登陆
3.在master主机添加新节点到workers文件中
上面的前置条件完成后,开始执行下面的步骤
hadoop系统正处于运行之中,要将新添加的节点动态加入到系统中,只需要在此节点上启动datanode和nodemanager
cd /usr/local/hadoop
sbin/hadoop-daemon.sh start datanode
重启所有的节点
hdfs --daemon stop datanode
hdfs --daemon start datanode
jps
查看节点有没有加进来
hdfs dfsadmin -report
因为HDFS里面都是有数据的,增加节点会导致数据分布不均衡,所有需要进行自动均衡操作。默认的数据传输带宽比较低,可以设置为64M,目录如下:
hdfs dfsadmin -setBalancerBandwidth 67108864
默认balancer的threshold为10%,即各个节点与集群总的存储使用率相差不超过10%,我们在均衡时可以指定该值为5%:
start-balancer.sh -threshold 5
在新增的节点启动nodemanager进程
Hadoop 从2.X引入了YARN框架,所以对于每个计算节点都可以通过NodeManager进行管理,同理启动NodeManager进程后,即可将其加入集群。
yarn-daemon.sh start nodemanager
yarn --daemon stop nodemanager
yarn --daemon start nodemanager
jps
yarn node -list
新增的节点 slaves 启动了 DataNode 和 NodeManager,实现了动态向集群添加了节点,至此Hadoop 动态添加节点操作完成。
3.2 删除节点
在删除的节点上关闭进程
yarn-daemon.sh stop nodemanager
hadoop-daemon.sh stop datanode
在主节点刷新
hdfs dfsadmin -refreshNodes
查看节点状态(可以看到节点的状态变成了Decommissioned,过一段时间后变成Died)
hdfs dfsadmin -report
4. 来个baseline
cat 1.txt
i like you very much i i i like
cat mapper.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
for line in sys.stdin:
line = line.strip()
words = line.split()
for word in words:
print("%s\t%s"%(word,1))
cat reducer.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from operator import itemgetter
import sys
current_word = None
current_count = 0
word = None
for line in sys.stdin:
words = line.strip()
word,count = words.split('\t')
try:
count = int(count)
except ValueError:
continue
if current_word == word:
current_count += 1
else:
if current_word:
print("%s\t%s"%(current_word,current_count))
current_count = count
current_word = word
if current_word == word:
print("%s\t%s"%(current_word,count))
cat run.sh
#!/bin/sh
QUEUENAME=`awk 'BEGIN{srand();if(rand() > 0.5){print "batch"}else{print "nlp"}}'`
CUR_DIR="$(pwd)"
HADOOP_JAR_FILE="/usr/hadoop/streaming/hadoop-streaming-2.6.0-mr1-cdh5.11.0.jar"
HADOOP_INPUT_DIR="/data/temp/daicong_test"
HADOOP_OUTPUT_DIR="/data/temp/daicong_test/output"
OUTPUT_FILE=out_put_file
function Process() {
if hadoop fs -test -e "$HADOOP_OUTPUT_DIR"; then
hadoop fs -rm -r "$HADOOP_OUTPUT_DIR"
fi
hadoop jar /usr/hadoop/hadoop-streaming-3.6.0-mr1-cdh5.11.0.jar \
-D mapreduce.job.queuename=${QUEUENAME} \
-D mapreduce.job.queue.priority=HIGH \
-D mapreduce.job.name="daicong_test" \
-D mapreduce.map.memory.mb=16384 \
-D mapred.map.tasks=300 \
-D mapreduce.reduce.tasks=2 \
-file ${CUR_DIR}/mapper.py \
-mapper ${CUR_DIR}/mapper.py \
-file ${CUR_DIR}/reducer.py \
-reducer ${CUR_DIR}/reducer.py \
-input ${HADOOP_INPUT_DIR}/*.txt \
-output ${HADOOP_OUTPUT_DIR}
if [ $? -ne 0 ]; then
echo 'Failed to run mapreduce'
exit 1
fi
hadoop fs -text "$HADOOP_OUTPUT_DIR/*" > $CUR_DIR/result
}
Process $@
-file就是告诉说要把这些文件上传到集群中,然后再制定map和reduce的脚本即可
先测试
cat 1.txt|python mapper.py |sort|python reducer.py
i 4
like 2
much 1
very 1
you 1
上面的输出没问题,下面执行./run.sh使用hadoop进行脚本的执行,注意的是-input /data/temp/daicong_test/*.txt \
这里应该把1.txt文件上传上去,再执行脚本即可
hadoop fs -put 1.txt /data/temp/daicong_test/
./run.sh