hadoop 分布式搭建

环境

虚拟机: VMware Workstation Pro 14
系统 : CentOS-7-x86_64-Minimal-1708.iso
Hadoop: Hadoop 2.8.1
使用三个节点作为集群环境:

  1. Master: 192.168.23.131
  2. Slave1: 192.168.23.129
  3. Slave2: 192.168.23.130

局域网ip为: 192.168.23.1 使用NAT连接方式
7.jpg

搭建过程

  1. CentOS master节点安装
  2. 由于是CentOS minimal版本 需要自行进行网络配置 有些工具没有 需自行安装
    网络配置: Vnet8 3.png4.png5.png

[hadoop@Master ~]
$ vim /etc/sysconfig/network-scripts/ifcfg-ens33
6.png

TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
IPADDR=192.168.23.131
NETMASK=255.255.255.0
GATEWAY=192.168.23.2
DNS1=8.8.8.8
DNS2=114.114.114

DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33
UUID=f1c3639c-ae61-4635-a223-5fb7b66eb9e5
DEVICE=ens33
ONBOOT=yes

7.jpg

http://blog.csdn.net/u013066244/article/details/61655788

>`sudo yum install net-tools`  
>`sudo yum install vim`  
>`sudo yum install wget`
  
  1. 创建用户

su # 上述提到的以 root 用户登录
useradd -m hadoop -s /bin/bash # 创建新用户hadoop
visudo
8.png

  1. ssh 使ssh master 成功
  2. 安装JAVA环境

sudo yum install java-1.7.0-openjdk java-1.7.0-openjdk-devel
配置PATH变量 JAVA_HOME

  1. 安装 Hadoop 2

centos minimal 不是桌面版 故命令行下载 wget https://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/common/hadoop-2.8.1/hadoop-2.8.1.tar.gz
择将 Hadoop 安装至 /usr/local/ 中:

sudo tar -zxf ~/hadoop-2.6.0.tar.gz -C /usr/local # 解压到/usr/local中
cd /usr/local/
sudo mv ./hadoop-2.6.0/ ./hadoop # 将文件夹名改为hadoop
sudo chown -R hadoop:hadoop ./hadoop # 修改文件权限

vim ~/.bashrc

export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.151-2.6.11.1.el7_4.x86_64
export HADOOP_HOME=/usr/local/hadoop
export HADOOP_INSTALL=$HADOOP_HOME
export HADOOP_MAPRED_HOME=$HADOOP_HOME
export HADOOP_COMMON_HOME=$HADOOP_HOME
export HADOOP_HDFS_HOME=$HADOOP_HOME
export YARN_HOME=$HADOOP_HOME
export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native
export PATH=$PATH:$HADOOP_HOME/sbin:$HADOOP_HOME/bin
export STREAM=$HADOOP_HOME/share/hadoop/tools/lib/hadoop-streaming-*.jar

9.png

source ~/.bashrc

  1. 开始集群配置
    将master机克隆出两个slave 分别为slave1和slave2
    在其他 Slave 安装 SSH server 改ip 修改hostname sudo vim /etc/hostname
  2. 在 Master 节点上开启 Hadoop
  3. 网络配置

sudo vim /etc/hostname
修改自己所用节点的IP映射
sudo vim /etc/hosts
10.png

需要在所有节点上完成网络配置

  1. SSH无密码登陆节点 是三台虚拟经济两两之间可无密码ssh连接
    11.png
    12.png
    13.png
  2. 配置集群/分布式环境
  1. 文件 slaves,将作为 DataNode 的主机名写入该文件,每行一个,默认为 localhost,所以在伪分布式配置时,节点即作为 NameNode 也作为 DataNode。分布式配置可以保留 localhost,也可以删掉,让 Master 节点仅作为 NameNode 使用
    14.png
  2. 文件 core-site.xml 改为下面的配置:
<configuration>
        <property>
                <name>fs.defaultFS</name>
                <value>hdfs://Master:9000</value>
        </property>
        <property>
                <name>hadoop.tmp.dir</name>
                <value>file:/usr/local/hadoop/tmp</value>
                <description>Abase for other temporary directories.</description>
        </property>
</configuration>
  1. 文件 hdfs-site.xml,dfs.replication 一般设为 3,但我们只有一个 Slave 节点,所以 dfs.replication 的值还是设为 1:
<configuration>
        <property>
                <name>dfs.namenode.secondary.http-address</name>
                <value>Master:50090</value>
        </property>
        <property>
                <name>dfs.replication</name>
                <value>1</value>
        </property>
        <property>
                <name>dfs.namenode.name.dir</name>
                <value>file:/usr/local/hadoop/tmp/dfs/name</value>
        </property>
        <property>
                <name>dfs.datanode.data.dir</name>
                <value>file:/usr/local/hadoop/tmp/dfs/data</value>
        </property>
</configuration>
  1. 文件 mapred-site.xml (可能需要先重命名,默认文件名为 mapred-site.xml.template),然后配置修改如下:
<configuration>
        <property>
                <name>mapreduce.framework.name</name>
                <value>yarn</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>
  1. 文件 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>
</configuration>
  1. 配置好后,将 Master 上的 /usr/local/Hadoop 文件夹复制到各个节点上。因为之前有跑过伪分布式模式,建议在切换到集群模式前先删除之前的临时文件。在 Master 节点上执行:

cd /usr/local
sudo rm -r ./hadoop/tmp # 删除 Hadoop 临时文件
sudo rm -r ./hadoop/logs/* # 删除日志文件
tar -zcf ~/hadoop.master.tar.gz ./hadoop # 先压缩再复制
cd ~
scp ./hadoop.master.tar.gz Slave1:/home/hadoop

Shell 命令
在 Slave1 节点上执行:

sudo rm -r /usr/local/hadoop # 删掉旧的(如果存在)
sudo tar -zxf ~/hadoop.master.tar.gz -C /usr/local
sudo chown -R hadoop /usr/local/hadoop

Shell 命令
同样,如果有其他 Slave 节点,也要执行将 hadoop.master.tar.gz 传输到 Slave 节点、在 Slave 节点解压文件的操作。

首次启动需要先在 Master 节点执行 NameNode 的格式化:
hdfs namenode -format # 首次运行需要执行初始化,之后不需要
在 Master 节点上启动:
start-dfs.sh
start-yarn.sh
mr-jobhistory-daemon.sh start historyserver
启动之后 master 节点 jps
15.jpg
slave1
16.png
slave2
17.png
Slave1 节点 jps

测试运行

1.执行分布式实例
先在本地创建一个word.txt文件
在hdfs上新建一个文件夹hdfs dfs -mkdir /user
hdfs dfs -mkdir /user/hadoop
将文件copy到hdfs上
hdfs dfs -copyFromLocal ~/word.txt /user/hadoop/input.txt

hadoop jar /usr/local/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar wordcount /user/hadoop output
18.jpg
19.jpg

  1. 查看文件
    hdfs dfs -cat output/*
    20.jpg
  2. 打开网页 centos minimal 不是桌面版 所以开一个端口转发
    21.png
    22.png
    23.jpg
    24.jpg

代码

mapper.py
reducer.py
mastrixA.txt
mastrixB.txt

vim matrixA.txt

A#2,2,6
A#3,5,3
A#5,1,2

vim matrixB.txt

B#2,3,1
B#3,1,2
B#2,1,2

注 就是 在windows下txt文件要加最后一行就是回车
linux要把最后一行回车删去 不然会提示 文件都不完 陷入死循环

vim mapper.py

#!/usr/bin/python
# -*-coding:utf-8 -*-

import sys

rowNum = 3
colNum = 3
rowIndexA = 1
rowIndexB = 1

def read_inputdata(splitstr):
    for line in sys.stdin:
        yield line.split(splitstr)

if __name__ == '__main__':
    for matrix, matrixline in read_inputdata('#'):
        if matrix == 'A':
            for i in range(rowNum):
                key = str(rowIndexA) + ',' + str(i+1)
                value = matrix + ':'
                j = 1
                for element in matrixline.split(','):
                    print '%s\t%s%s,%s' %  (key, value, j, element)
                    j += 1
            rowIndexA += 1
        elif matrix == 'B':
            for i in range(colNum):
                value = matrix + ':'
                j = 1
                for element in matrixline.split(','):
                    print '%s,%s\t%s%s,%s' % (i+1, j, value, rowIndexB, element)
                    j = j+1
            rowIndexB += 1
        else: continue


vim reducer.py

#!/usr/bin/python
# -*- coding:utf-8 -*-

import sys
from itertools import groupby
from operator import itemgetter

def read_input(splitstr):
    for line in sys.stdin:
        line = line.strip()
        if len(line) == 0: continue
        yield line.split(splitstr, 1)


def run():
    data = read_input('\t')
    i=1
    a = ''
    for current_element, group in groupby(data, itemgetter(0)):
        try:
            matrixA = {}
            matrixB = {}
            result = 0
            for current_element, elements in group:
                matrix, index_value = elements.split(':')
                index, value = index_value.split(',')
                if matrix == 'A':
                    matrixA[index] = int(value)+1
                else:
                    matrixB[index] = int(value)+1

            # print matrixA
            # print matrixB
            for key in matrixA:
                result += matrixA[key]*matrixB[key]
            # if i%3==0:
            #     print '\n'
            #     print '%s' % a
            #     a = ''
            # else :
            #     a = a + result
            
            # print '%s\t%s %s' % (current_element, result,i)
            if i==1:
                a = '%s ' % (result)
            if i%3 == 0:
                # a = a +  '%s ' % (result)
                print '%s' % (a)
                a = '%s ' % (result)
                i = i + 1
            else :
                a = a +  '%s ' % (result)
                i = i + 1
                # print '%s %s' % (a,i)
            
        except Exception:
            pass

if __name__ == '__main__':
    run()

25.jpg

运行结果

先将matrixA.txt matrix.txt 传至hdfs
hdfs dfs -mkdir mat
hdfs dfs -put mat/* mat
hdfs dfs -ls mat
28.jpg

$STREAM 为环境变量 需在 ~/.bashrc 加
export STREAM=$HADOOP_HOME/share/hadoop/tools/lib/hadoop-streaming-*.jar

给py文件足够的权限
chmod a+x mapper.py
chmod a+x reducer.py
执行程序:
hadoop jar $STREAM -file ~/mapper.py -mapper ~/mapper.py -file ~/reducer.py -reducer ~/reducer.py -input /input -output /ooook
36.png
32.png
hdfs dfs -cat /ooook/*
37.png

使用教程

Hadoop安装教程_单机/伪分布式配置_CentOS6.4/Hadoop2.6.0
Hadoop集群安装配置教程_Hadoop2.6.0_Ubuntu/CentOS
用python写MapReduce函数——以WordCount为例

踩过的坑

  1. python hadoop stream 流 no such file
    解决方法:http://www.guanggua.com/question/4339788-hadoop-streaming-unable-to-find-file-error.html

powered by Erestu

甲鱼的博客