Hadoop信息详解

第0章大数据概论

一、大数据概念

大数据:Big Data,指的是无法在一定时间范围内使用常规软进行捕捉,管理和处理的数据的集合。需要新的处理模式来进行决策力。洞察收取海量、高增长和多样化的信息进行管理。

二、大数据的特点

  1. 大量
  2. 高速
  3. 多样性
  4. 低密度值

三、大数据的应用场景

  1. 物流仓储
  2. 零售
  3. 旅游
  4. 商品广告推荐
  5. 保险
  6. 金融
  7. 人工智能

四、大数据的部门组织结构

平台组:

数据仓储组:

数据挖掘:

报表工程:

第一章Hadoop简介

一、什么是Hadoop

Hadoop是Apache基金会下开源的分布式的存储分布式计算基础系统架构。

官方网站:https://hadoop.apache.org/

四部分:

  1. Hadoop Common 基础模块
  2. Hadoop Distributed File System (HDFS™) :分布式存储
  3. Hadoop MapReduce :分布式计算
  4. Hadoop YARN :资源管理

二、Hadoop出现的背景

Doug Cutting :

GFS->HDFS

Map-Reduce -> MR(MapReduce)

BigTable -> HBase

三、Hadoop发展历程及国内外发展现状

四、Hadoop生态圈

五、Hadoop体系架构

5.1 核心项目:

HDFS: Hadoop的分布式文件系统

MapReduce : 分布式并行计算框架

YARN: 2.X 开始,资源管理

5.2 HDFS的架构介绍 (存储模型)

•主从结构

•主节点,只有一个: namenode(NN)

•从节点,有很多个: datanodes(DN)

•namenode负责:

•接收用户操作请求

•维护文件系统的目录结构

•管理文件与block之间关系,block与datanode之间关系

•datanode负责:

•存储文件

•文件被分成block存储在磁盘上

•为保证数据安全,文件会有多个副本

5.3 MapReduce架构介绍 (计算模型)

•主从结构

•主节点,只有一个: JobTracker(ResourceManager,RM)

•从节点,有很多个: TaskTrackers(NodeManager,NM)

•JobTracker负责:

•接收客户提交的计算任务

•把计算任务分给TaskTrackers执行

•监控TaskTracker的执行情况

•TaskTrackers负责:

•执行JobTracker分配的计算任务

第二章安装Hadoop

一、Hadoop安装方式

官网:https://hadoop.apache.org/docs/r2.7.3/hadoop-project-dist/hadoop-common/SingleCluster.html#Installing_Software

二、搭建Linux环境

2.1 克隆Linux

选中要克隆的虚拟机->右键拍快照->数据快照名称->点击拍快照

点击管理此虚拟机的快照->选中要克隆的快照->点击克隆->下一步->选中要克隆的快照->下一步(选中克隆方式)–>下一步

2.2 修改静态ip

[root@localhost ~]# vim /etc/sysconfig/network-scripts/ifcfg-ens33 
TYPE=Ethernet
BOOTPROTO=static ####
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33
UUID=435ff9da-284c-4323-ba20-7314ef4bdbe7
DEVICE=ens33
ONBOOT=yes
IPADDR=192.168.9.101    ###改自己的IP!!!!
NETMASK=255.255.255.0
GATEWAY=192.168.9.2
DNS1=114.114.114.114
DNS2=8.8.8.8

2.3 重启网络

[root@localhost ~]# systemctl  restart network.service   ###重启网络
[root@localhost ~]# ifconfig   ###查看网络配置
[root@localhost ~]# ip addr    ###查看网络配置

2.4 修改主机名

[root@localhost ~]# vim /etc/hostname 
[root@localhost ~]# hostname  ###查看 主机名

2.5 配置IP和hostname的映射关系

[root@localhost ~]# vim /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.9.101  hadoop101   ####映射关系

#192.168.9.101 和 IPADDR=192.168.9.101  一致
#hadoop101和  /etc/hostname 中设置的一致

2.6 设置window的host文件

修改C:\Windows\System32\drivers\etc文件夹下的host文件(必须以管理员的身份修改)

192.168.9.101 hadoop101

命令行输入C:\Users\qwy>ping hadoop101进行校验

三、关闭防火墙

[root@hadoop101 ~]# firewall-cmd --state  ##查看防火墙的状态
[root@hadoop101 ~]# systemctl stop firewalld.service  ###临时关闭防火墙
[root@hadoop101 ~]# systemctl disable firewalld.service  ### 开机不启动防火墙

四、实现SSH免密码登陆

1.生成秘钥

[root@hadoop101 ~]# ssh-keygen -t rsa  ##回车
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): ##回车
Enter passphrase (empty for no passphrase): ##回车
Enter same passphrase again: ##回车
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
6d:af:83:54:5f:7b:e2:56:73:17:a9:20:55:5e:60:cd root@hadoop101
The key's randomart image is:
+--[ RSA 2048]----+
|            .++. |
|           .o .E |
|          .  .  .|
|         o..  .o |
|        S.+......|
|        .. ...o.=|
|       . .  .. ++|
|        . ..  o  |
|          .. .   |
+-----------------+

2.将公钥发送给其他机器

[root@hadoop101 .ssh]# ssh-copy-id hadoop101 ####
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@hadoop101's password: ###输入密码
###3.验证
[root@hadoop101 .ssh]# ssh hadoop101  重新登录不要输入密码了

五、安装JDK

检查之前是否安装过

[root@hadoop101 module]# rpm -qa | grep java  ###检查之前是否安装过
java-1.8.0-openjdk-1.8.0.102-4.b14.el7.x86_64
java-1.8.0-openjdk-headless-1.8.0.102-4.b14.el7.x86_64
python-javapackages-3.4.1-11.el7.noarch
javapackages-tools-3.4.1-11.el7.noarch
tzdata-java-2016g-2.el7.noarch

###强制卸载之前安装的JDK 
[root@hadoop101 module]# rpm -e --nodeps java-1.8.0-openjdk-1.8.0.102-4.b14.el7.x86_64
[root@hadoop101 module]# rpm -e --nodeps java-1.8.0-openjdk-headless-1.8.0.102-4.b14.el7.x86_64
[root@hadoop101 module]# rpm -e --nodeps python-javapackages-3.4.1-11.el7.noarch
[root@hadoop101 module]# rpm -e --nodeps javapackages-tools-3.4.1-11.el7.noarch
[root@hadoop101 module]# rpm -e --nodeps tzdata-java-2016g-2.el7.noarch

上传

[root@hadoop101 opt]# mkdir software  ###创建文件夹
[root@hadoop101 opt]# mkdir module ###创建文件夹
[root@hadoop101 opt]# ll
total 0
drwxr-xr-x. 2 root root 6 Apr 11 14:04 module ###  安装程序
drwxr-xr-x. 2 root root 6 Mar 26  2015 rh
drwxr-xr-x. 2 root root 6 Apr 11 14:03 software ####存放上传文件的

解压

[root@hadoop101 software]# tar -xvzf jdk-8u144-linux-x64.tar.gz -C /opt/module/
##  tar  -zxvf  压缩包  -C   目录
###注意  C 是大写的

配置环境变量

[root@hadoop101 module]# vim /etc/profile ###配置环境变量
###在倒数第三行位置添加
export JAVA_HOME=/opt/module/jdk1.8.0_144
export PATH=$PATH:$JAVA_HOME/bin
##注意,变量之间使用英文的冒号分割,window上使用英文的分号

[root@hadoop101 module]# source /etc/profile  ###重新加载profile文件,使其生效
###校验是否安装成功
[root@hadoop101 module]# javac -version
javac 1.8.0_144
[root@hadoop101 module]# java -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)

六、Hadoop单机伪分布安装介绍

一、上传

二、解压

[root@hadoop101 software]# tar -zxvf  hadoop-2.7.7.tar.gz -C /opt/module/

三、目录说明

[root@hadoop101 module]# cd hadoop-2.7.7/
[root@hadoop101 hadoop-2.7.7]# ll
total 112
drwxr-xr-x. 2 qwy ftp   194 Jul 19  2018 bin   ##可执行命令
drwxr-xr-x. 3 qwy ftp    20 Jul 19  2018 etc   ##hadoop的配置文件
drwxr-xr-x. 2 qwy ftp   106 Jul 19  2018 include
drwxr-xr-x. 3 qwy ftp    20 Jul 19  2018 lib  ###运行时依赖的jar库
drwxr-xr-x. 2 qwy ftp   239 Jul 19  2018 libexec
-rw-r--r--. 1 qwy ftp 86424 Jul 19  2018 LICENSE.txt
-rw-r--r--. 1 qwy ftp 14978 Jul 19  2018 NOTICE.txt
-rw-r--r--. 1 qwy ftp  1366 Jul 19  2018 README.txt
drwxr-xr-x. 2 qwy ftp  4096 Jul 19  2018 sbin ### 可执行命令
drwxr-xr-x. 4 qwy ftp    31 Jul 19  2018 share  ### 文档,依赖的jar,官方实例等

四、配置环境变量

[root@hadoop101 hadoop-2.7.7]# vim /etc/profile
#JAVA_HOME
	export JAVA_HOME=/opt/module/jdk1.8.0_144
	export PATH=$PATH:$JAVA_HOME/bin
#HADOOP_HOME
	export HADOOP_HOME=/opt/module/hadoop-2.7.7
	export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
[root@hadoop101 hadoop-2.7.7]# . /etc/profile
### 英文的点(.) 是source的别名

五、验证

[root@hadoop101 hadoop-2.7.7]# hadoop  ###按Tab键
hadoop             hadoop.cmd         hadoop-daemon.sh   hadoop-daemons.sh  
[root@hadoop101 hadoop-2.7.7]# hdfs  ###按Tab键
hdfs             hdfs.cmd         hdfs-config.cmd  hdfs-config.sh   

六、配置hadoop的配置文件

这些文件在/opt/module/hadoop-2.7.7/etc/hadoop

6.1 hdfs-site.xml
<configuration>
		<!-- 指定HDFS副本的数量 -->
		<property>
			<name>dfs.replication</name>
			<value>1</value>
		</property>
</configuration>
6.2 mapper-site.xml

该文件默认不存在,需要拷贝一个

[root@hadoop101 hadoop]# cp mapred-site.xml.template mapred-site.xml  ###拷贝
[root@hadoop101 hadoop]# vim mapred-site.xml
<configuration>
	<!-- 指定MR运行在YARN上 -->
	<property>
		<name>mapreduce.framework.name</name>
		<value>yarn</value>
	</property>
</configuration>
6.3 yarn-site.xml
<configuration>
	<!-- Reducer获取数据的方式 -->
	<property>
		<name>yarn.nodemanager.aux-services</name>
		<value>mapreduce_shuffle</value>
	</property>

	<!-- 指定YARN的ResourceManager的地址 -->
	<property>
		<name>yarn.resourcemanager.hostname</name>
		<value>hadoop101</value>
	</property>
</configuration>
6.4 core-site.xml
<configuration>
	<!-- 指定HDFS中NameNode的地址 -->
	<property>
		<name>fs.defaultFS</name>
		<value>hdfs://hadoop101:9000</value>
	</property>

	<!-- 指定Hadoop运行时产生文件的存储目录 -->
	<property>
		<name>hadoop.tmp.dir</name>
		<value>/opt/module/hadoop-2.7.7/data/tmp</value>   ###data/tmp文件hdfs初始化自己创建,可修改
	</property>
</configuration>
6.5 hadoop-env.sh 、mapred-env.sh、yarn-env.sh

这几个文件都修改JAVA_HOME

JAVA_HOME=/opt/module/jdk-8u144_1.8.0
6.6 格式化hdfs
[root@hadoop101 hadoop]# hdfs namenode -format   ###一般情况下不要格式化两次

七、启动Hadoop

6.7.1 启动hdfs和yarn
[root@hadoop101 hadoop]# start-dfs.sh #  启动hdfs
[root@hadoop101 hadoop]# start-yarn.sh  ##启动yarn
6.7.2 查看进程
[root@hadoop101 hadoop]# jps
38848 DataNode
39011 SecondaryNameNode
39156 ResourceManager
38726 NameNode
39432 NodeManager
39549 Jps
6.7.3 web浏览器访问

http://192.168.80.100:50070/ 访问HDFS
http://192.168.80.100:8088/cluster 访问MR

6.7.4 关闭hdfs和yarn
[root@hadoop101 hadoop-2.7.7]# stop-dfs.sh   ###关闭hdfs
[root@hadoop101 hadoop-2.7.7]# stop-yarn.sh  ###关闭yarn

七、Hadoop完全分布式集群架构部署

7.1 集群规划

节点名称NNSNNDNRMNM
hadoop101(主节点)
hadoop102
hadoop103

7.2 修改文件数据

准备三台Linux并修改ip,hostname、网络映射

主机名iphostname
hadoop101192.168.9.101hadoop101
hadoop102192.168.9.102hadoop102
hadoop103192.168.9.103hadoop103
7.2.1 修改IP
[root@localhost ~]# vim /etc/sysconfig/network-scripts/ifcfg-ens33 
TYPE=Ethernet
BOOTPROTO=static  ####修改成静态ip
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33
UUID=435ff9da-284c-4323-ba20-7314ef4bdbe7
DEVICE=ens33
ONBOOT=yes

IPADDR=192.168.9.101   ####修改自己的ip
NETMASK=255.255.255.0   ####
GATEWAY=192.168.9.2   ####
DNS1=114.114.114.114   ####
DNS2=8.8.8.8  ####
[root@localhost ~]# systemctl restart network.service ###重启网络
[root@localhost ~]# ifconfig  ##检查是否成功
7.2.2 修改hostname
[root@localhost ~]# vim /etc/hostname 
hadoop101
7.2.3 配置ip和hostname的映射:
[root@localhost ~]# vi /etc/hosts
192.168.9.101  hadoop101
7.2.4 重启进行校验:!!!重启!!!
[root@localhost ~]# reboot
7.2.5 关掉防火墙:!!!!
[root@hadoop101 ~]# firewall-cmd --state  ###查看防火墙状态
running
[root@hadoop101 ~]# systemctl stop firewalld.service   ##关闭防火墙
[root@hadoop101 ~]# systemctl disable firewalld.service  ### 开机不启动防火墙
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
Removed symlink /etc/systemd/system/basic.target.wants/firewalld.service.
[root@hadoop101 ~]# firewall-cmd --state
not running

7.3 window上修改hosts文件

位置: C:\Windows\System32\drivers\etc

添加:192.168.9.101 hadoop101、192.168.9.102 hadoop102、192.168.9.103 hadoop103

7.4 创建用户并指定用户密码

添加hadoop用户

因为root用户权限太大了。

[root@hadoop101 ~]# adduser hadoop  ###添加用户
[root@hadoop101 ~]# passwd hadoop   ###给新用户指定密码
Changing password for user hadoop.
New password:  ###输入新用户密码
BAD PASSWORD: The password is shorter than 7 characters
Retype new password: ###输入确认新用户密码
passwd: all authentication tokens updated successfully.
7.4.1 在/opt下新建software和module文件夹
[root@hadoop101 ~]# mkdir /opt/software  ###  用来存储上传文件
[root@hadoop101 ~]# mkdir /opt/module ###  用来存储安装文件
root@hadoop101 opt]# ll
total 0
drwxr-xr-x. 2 root root 6 Apr 13 10:04 module
drwxr-xr-x. 2 root root 6 Mar 26  2015 rh
drwxr-xr-x. 2 root root 6 Apr 13 10:04 software
[root@hadoop101 opt]# chown  hadoop:hadoop /opt/module/  ###修改module文件夹拥有者为hadoop
[root@hadoop101 opt]# chown  hadoop:hadoop /opt/software/
[root@hadoop101 opt]# ll
total 0
drwxr-xr-x. 2 hadoop hadoop 6 Apr 13 10:04 module
drwxr-xr-x. 2 root   root   6 Mar 26  2015 rh
drwxr-xr-x. 2 hadoop hadoop 6 Apr 13 10:04 software
7.4.2 使hadoop用户拥有root的权限
[root@hadoop101 opt]# cd /etc/
[root@hadoop101 etc]# ls -al sudoers
-r--r-----. 1 root root 3907 Nov  5  2016 sudoers
[root@hadoop101 etc]# chmod u+w sudoers  ##添加修改的权限
[root@hadoop101 etc]# ls -al sudoers
-rw-r-----. 1 root root 3907 Nov  5  2016 sudoers
[root@hadoop101 etc]# vim /etc/sudoers
#Allow root to run any commands anywhere
root    ALL=(ALL)       ALL
hadoop  ALL=(ALL)       ALL   ###使hadoop可以执行root的命令
[root@hadoop101 etc]# chmod u-w sudoers ##去掉修改的权限

7.5 安装JDK(以后全部使用hadoop用户)

7.5.1 检查是否安装过JDK(使用root操作)
[root@hadoop101 module]# rpm -qa | grep java  ###检查之前是否安装过
java-1.8.0-openjdk-1.8.0.102-4.b14.el7.x86_64
java-1.8.0-openjdk-headless-1.8.0.102-4.b14.el7.x86_64
python-javapackages-3.4.1-11.el7.noarch
javapackages-tools-3.4.1-11.el7.noarch
tzdata-java-2016g-2.el7.noarch
###强制卸载之前安装的JDK 
[root@hadoop101 module]# rpm -e --nodeps java-1.8.0-openjdk-1.8.0.102-4.b14.el7.x86_64
[root@hadoop101 module]# rpm -e --nodeps java-1.8.0-openjdk-headless-1.8.0.102-4.b14.el7.x86_64
[root@hadoop101 module]# rpm -e --nodeps python-javapackages-3.4.1-11.el7.noarch
[root@hadoop101 module]# rpm -e --nodeps javapackages-tools-3.4.1-11.el7.noarch
[root@hadoop101 module]# rpm -e --nodeps tzdata-java-2016g-2.el7.noarch
7.5.2 上传解压
[hadoop@hadoop101 ~]$ tar -zxvf /opt/software/jdk-8u144-linux-x64.tar.gz -C /opt/module/
7.5.3 配置环境变量
[hadoop@hadoop101 module]$ sudo vi /etc/profile   ###注意使用sudo
##在倒数第三行位置添加如下操作
#JAVA_HOME
	export JAVA_HOME=/opt/module/jdk1.8.0_144
	export PATH=$PATH:$JAVA_HOME/bin
[hadoop@hadoop101 module]$ source /etc/profile  ###重新加载该文件
[hadoop@hadoop101 module]$ java -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
[hadoop@hadoop101 module]$ javac -version
javac 1.8.0_144

7.6 安装Hadoop

7.6.1 上传解压
[hadoop@hadoop101 module]$ tar -xvzf /opt/software/hadoop-2.7.7.tar.gz -C /opt/module/
7.6.2 配置JAVA_HOME
[hadoop@hadoop101 hadoop-2.7.7]$ sudo vim /etc/profile
#JAVA_HOME
   export JAVA_HOME=/opt/module/jdk1.8.0_144
#HADOOP_HOME
   export HADOOP_HOME=/opt/module/hadoop-2.7.7   ###
   export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/bin
[hadoop@hadoop101 hadoop-2.7.7]$ source /etc/profile  ###重新加载该文件

7.7 配置Hadoop的配置文件(6个)

注意:完全分布式只需要在伪分布式的基础上克隆并修改core-site.xml文件,

这些文件都在/opt/module/hadoop-2.7.7/etc/hadoop目录下

7.7.1 core-site.xml
[hadoop@hadoop101 hadoop]$ vim core-site.xml 
<configuration>
	<!-- 指定HDFS中NameNode的地址 -->
	<property>
		<name>fs.defaultFS</name>
		<value>hdfs://hadoop101:9000</value>    ###注意指定NameNode地址!!!
	</property>

	<!-- 指定Hadoop运行时产生文件的存储目录 -->
	<property>
		<name>hadoop.tmp.dir</name>
		<value>/opt/module/hadoop-2.7.7/data/tmp</value>
	</property>
</configuration>
7.7.2 hdfs-site.xml
[hadoop@hadoop101 hadoop]$ vim hdfs-site.xml 
<configuration>
		<!-- 指定HDFS副本的数量,默认值为3此处设置为2 -->
		<property>
			<name>dfs.replication</name>
			<value>2</value>
		</property>
	<!-- 指定Hadoop辅助名称节点主机配置 -->
	<property>
		  <name>dfs.namenode.secondary.http-address</name>
		  <value>hadoop102:50090</value>
	</property>
</configuration>
7.7.3 mapred-site.xml
[hadoop@hadoop101 hadoop]$ cp mapred-site.xml.template mapred-site.xml
[hadoop@hadoop101 hadoop]$ vim mapred-site.xml
<configuration>
		<!-- 指定MR运行在YARN上 -->
		<property>
				<name>mapreduce.framework.name</name>
				<value>yarn</value>
		</property>
</configuration>
7.7.4 yarn-site.xml
[hadoop@hadoop101 hadoop]$ vim yarn-site.xml
<configuration>
		<!-- Reducer获取数据的方式 -->
		<property>
				<name>yarn.nodemanager.aux-services</name>
				<value>mapreduce_shuffle</value>
		</property>

		<!-- 指定YARN的ResourceManager的地址 -->
		<property>
		<name>yarn.resourcemanager.hostname</name>
		<value>hadoop101</value>
		</property>
</configuration>
7.7.5 修改xxx-env.sh文件的JAVA_HOME
[hadoop@hadoop101 hadoop]$ vim hadoop-env.sh 
[hadoop@hadoop101 hadoop]$ vim yarn-env.sh 
[hadoop@hadoop101 hadoop]$ vim mapred-env.sh 
#JAVA_HOME
export JAVA_HOME=/opt/module/jdk1.8.0_144
7.7.6 slaves
[hadoop@hadoop101 hadoop]$ vim slaves 
hadoop102
hadoop103

**注意:**该文件修改时,不要出现空行,也不要出现多余的空格

7.8 克隆

7.8.1 在刚才配置好的机器上克隆出102,103虚拟机
7.8.2 分别修改102,103的ip,hostname以及映射
7.8.3 windows的hosts添加如下内容
192.168.9.101 hadoop101
192.168.9.102 hadoop102
192.168.9.103 hadoop103

7.8.4 配置三台机器的相互免秘钥登录
[hadoop@hadoop101 ~]$ ssh-keygen -t rsa   ###生成hadoop101的秘钥
Generating public/private rsa key pair.
Enter file in which to save the key (/home/hadoop/.ssh/id_rsa): 
Created directory '/home/hadoop/.ssh'.Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/hadoop/.ssh/id_rsa.
Your public key has been saved in /home/hadoop/.ssh/id_rsa.pub.
The key fingerprint is:
2f:23:f0:26:4f:4c:36:6e:d0:95:dc:3c:e8:ae:75:71 hadoop@hadoop101
The key's randomart image is:
+--[ RSA 2048]----+
|                 |
|       . =       |
|        = +      |
|     . o   .     |
|    o = S . E    |
|     O o . o     |
|    . O = o      |
|     * + +       |
|      o          |
+-----------------+
[hadoop@hadoop101 ~]$ ssh-copy-id hadoop101  ##将公钥拷给hadoop101
The authenticity of host 'hadoop101 (192.168.9.101)' can't be established.
ECDSA key fingerprint is 4f:3c:73:a6:0e:b9:81:20:e9:1f:16:b9:0e:b0:fe:e1.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the 
new keyshadoop@hadoop101's password:   ##输入hadoop101的密码
Number of key(s) added: 1
Now try logging into the machine, with:   "ssh 'hadoop101'"
and check to make sure that only the key(s) you wanted were added.

以上操作每台都执行一次

7.9 格式化操作(主节点)

7.9.1 在主节点上执行
[hadoop@hadoop101 ~]$ hdfs namenode -format
7.9.2 启动HDFS和YARN
[hadoop@hadoop101 ~]$ start-dfs.sh   ##启动HDFS
Starting namenodes on [hadoop101]
hadoop101: starting namenode, logging to /opt/module/hadoop-2.7.7/logs/hadoop-hadoop-namenode-hadoop101.out
hadoop103: starting datanode, logging to /opt/module/hadoop-2.7.7/logs/hadoop-hadoop-datanode-hadoop103.out
hadoop102: starting datanode, logging to /opt/module/hadoop-2.7.7/logs/hadoop-hadoop-datanode-hadoop102.out
Starting secondary namenodes [hadoop102]
hadoop102: starting secondarynamenode, logging to /opt/module/hadoop-2.7.7/logs/hadoop-hadoop-secondarynamenode-hadoop102.out
[hadoop@hadoop101 ~]$ start-yarn.sh  ###启动YARN
starting yarn daemons
starting resourcemanager, logging to /opt/module/hadoop-2.7.7/logs/yarn-hadoop-resourcemanager-hadoop101.out
hadoop103: starting nodemanager, logging to /opt/module/hadoop-2.7.7/logs/yarn-hadoop-nodemanager-hadoop103.out
hadoop102: starting nodemanager, logging to /opt/module/hadoop-2.7.7/logs/yarn-hadoop-nodemanager-hadoop102.out
7.9.3 校验

每台机器执行jps注意自己查看下角色。

[hadoop@hadoop101 ~]$ jps
4034 Jps
3460 NameNode
3768 ResourceManager

#################################
[hadoop@hadoop102 ~]$ jps
3617 NodeManager
3747 Jps
3397 DataNode
3502 SecondaryNameNode
##################################

[hadoop@hadoop103 ~]$ jps
3297 DataNode
3570 Jps
3438 NodeManager

浏览器访问测试:http://hadoop101:50070/ 、http://hadoop101:8088/cluster

7.9.4 配置时间同步

Hadoop完全分布式对时间的要求很高,主节点与各从节点的时间应该做到时间的同步,而配置时间同步服务也是为了解决集群各个节点之间的时间同步问题。

两种配置方式:

本地ntp服务器提供时间同步服务

外围的ntp服务器提供时间同步服务(常采用)

9.4.1 安装ntpdate(每台服务器在线安装)
[hadoop@hadoop101 ~]$ yum install ntpdate -y 
[hadoop@hadoop102 ~]$ yum install ntpdate -y 
[hadoop@hadoop103 ~]$ yum install ntpdate -y 
9.4.2 同步ntp服务器时间

命令格式:ntpdate -u ip(ntp服务器ip)

服务器IP命令
中国国家授时中心210.72.145.44ntpdate -u 210.72.145.44
NTP服务器(上海)ntp.api.bzntpdate -u ntp.api.bz
美国time.nist.govntpdate -u time.nist.gov
复旦ntp.fudan.edu.cnntpdate -u ntp.fudan.edu.cn
微软公司授时系统(美国)time.windows.comntpdate -u time.windows.com

7.10 集群节点的添加与删除

注意:新节点的配置要和集群中节点环境一致:

  • SSH免密登录
  • JDK
  • Hadoop配置文件
  • 时间同步
  • IP
  • HostName
  • 映射关系
7.10.1 添加新节点
  1. 克隆新的虚拟机
  2. 修改ip
  3. 修改hostname
  4. 修改映射(所有的机器都要配置)
  5. 关闭防火墙
  6. 配置hadoop101到hadoop104的免密登录

在主节点(.101)的hdfs-site.xml文件配置以下操作:

  1. hdfs-site.xml添加

    <property>
        <name>dfs.hosts</name>
        <value>/opt/module/hadoop-2.7.7/conf/datanode-allow.list</value>
        <description>允许加入集群的节点列表</description><!--此行为注释-->
    </property>
    <property>
        <name>dfs.hosts.exclude</name>
        <value>/opt/module/hadoop-2.7.7/conf/datanode-deny.list</value>
        <description>拒绝加入集群的节点列表</description><!--此行为注释-->
    </property>
    
  2. 新建conf文件夹和datanode-allow.list以及datanode-deny.list文件

    [hadoop@hadoop101 hadoop-2.7.7]$ mkdir conf
    [hadoop@hadoop101 hadoop-2.7.7]$ cd conf/
    [hadoop@hadoop101 conf]$ touch datanode-allow.list
    [hadoop@hadoop101 conf]$ touch datanode-deny.list
    [hadoop@hadoop101 conf]$ ll
    total 0
    -rw-rw-r--. 1 hadoop hadoop 0 Apr 14 10:30 datanode-allow.list
    -rw-rw-r--. 1 hadoop hadoop 0 Apr 14 10:30 datanode-deny.list
    
  3. 新节点单独驱动datanode进行

    [hadoop@hadoop104 hadoop-2.7.7]$ hadoop-daemon.sh start datanode
    starting datanode, logging to /opt/module/hadoop-2.7.7/logs/hadoop-hadoop-datanode-hadoop104.out
    [hadoop@hadoop104 hadoop-2.7.7]$ yarn-daemon.sh start nodemanager
    starting nodemanager, logging to /opt/module/hadoop-2.7.7/logs/yarn-hadoop-nodemanager-hadoop104.out
    
  4. 主节点(.101)执行如下操作*(也可以在浏览器中查看)*

    ###刷新节点
    [hadoop@hadoop101 conf]$ hdfs dfsadmin -refreshNodes
    Refresh nodes successful
    ###查看状态
    [hadoop@hadoop101 conf]$ hdfs dfsadmin -report
    Name: 192.168.9.104:50010 (hadoop104)
    Hostname: hadoop104
    Decommission Status : Normal
    Configured Capacity: 24470200320 (22.79 GB)
    DFS Used: 4096 (4 KB)
    Non DFS Used: 5396013056 (5.03 GB)
    DFS Remaining: 19074183168 (17.76 GB)
    DFS Used%: 0.00%
    DFS Remaining%: 77.95%
    Configured Cache Capacity: 0 (0 B)
    Cache Used: 0 (0 B)
    Cache Remaining: 0 (0 B)
    Cache Used%: 100.00%
    Cache Remaining%: 0.00%
    Xceivers: 1
    Last contact: Thu Apr 14 10:39:21 CST 2022
    
7.10.2 删除节点
  1. 在配置好的**/opt/module/hadoop-2.7.7/conf/datanode-deny.list**中配置

    hadoop104  ##将104排除在集群外
    
  2. 主节点执行如下命令

    [hadoop@hadoop101 conf]$ hdfs dfsadmin -refreshNodes   ##刷新节点
    

第三章 HDFS高可用搭建

高可用(HA):

​ 高可用,即High Availability,是指一个系统经过专门的设计,从而减少停工时间,而保持其服务的高度可用性。一般有两个或两个以上的节点,且分为活动节点及备用节点。通常把正在执行业务的称为活动节点,而备用节点是活动节点的一个备份节点。当活动节点出现问题,导致正在运行的业务(任务)不能正常运行时,备用节点会立即侦测到,并立即接续活动节点来执行业务,从而实现业务的不中断或短暂中断 。

3.1 安装zookeeper集群(在主节点上)

3.1.1 上传zookeeper、解压

[hadoop@hadoop101 software]$ tar -zxvf zookeeper-3.4.5.tar.gz -C /opt/module/

3.1.2 配置环境变量

[hadoop@hadoop101 software]$ sudo vim /etc/profile
#JAVA_HOME
export JAVA_HOME=/opt/module/jdk1.8.0_144
#HADOOP_HOME
export HADOOP_HOME=/opt/module/hadoop-2.7.7
#ZOOKEEPER_HOME
export ZOOKEEPER_HOME=/opt/module/zookeeper-3.4.5
export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$ZOOKEEPER_HOME/bin

3.1.3 配置zookeeper

找到安装目录的/opt/module/zookeeper-3.4.5/conf

[hadoop@hadoop101 conf]$ cp zoo_sample.cfg zoo.cfg   ##拷贝一个文件
[hadoop@hadoop101 conf]$ vim zoo.cfg
dataDir=/opt/module/zookeeper-3.4.5/tmp/zdata   ###编辑自己的目录

#在最后位置添加(写入myid的编号一定按server.x顺序)
server.1=hadoop101:2888:3888
server.2=hadoop102:2888:3888
server.3=hadoop103:2888:3888

[hadoop@hadoop101 conf]$ mkdir -p /opt/module/zookeeper-3.4.5/tmp/zdata  ###创建zoo.cfg文件中配置的路径
[hadoop@hadoop101 zdata]$ pwd
/opt/module/zookeeper-3.4.5/tmp/zdata
[hadoop@hadoop101 zdata]$ echo 1 > myid 
1、将配置好的zookeeper分发到其他的机器
[hadoop@hadoop101 zdata]$ scp -r /opt/module/zookeeper-3.4.5  hadoop@hadoop102:/opt/module/  
[hadoop@hadoop101 zdata]$ scp -r /opt/module/zookeeper-3.4.5  hadoop@hadoop103:/opt/module/
2、将hadoop102和hadoop103的myid修改为自己的编号
[hadoop@hadoop102 zdata]$ pwd
/opt/module/zookeeper-3.4.5/tmp/zdata
[hadoop@hadoop102 zdata]$ echo 2 > myid
[hadoop@hadoop103 zdata]$ pwd
/opt/module/zookeeper-3.4.5/tmp/zdata
[hadoop@hadoop103 zdata]$ echo 3 > myid
3、在hadoop102和hadoop103配置zookeeper的环境变量
[hadoop@hadoop101 ~]$ sudo scp /etc/profile hadoop102:/etc/
[hadoop@hadoop101 ~]$ sudo scp /etc/profile hadoop103:/etc/

###在hadoop102和hadoop103分别重新加载文件/profile 
[hadoop@hadoop102 zdata]$ source /etc/profile
[hadoop@hadoop103 zdata]$ source /etc/profile
4、校验是否成功
[hadoop@hadoop101 ~]$ zkServer.sh start
[hadoop@hadoop102 ~]$ zkServer.sh start
[hadoop@hadoop103 ~]$ zkServer.sh start
###每台机器都执行以下操作

[hadoop@hadoop101 ~]$ zkServer.sh status

Mode: follower   ##3随从
Mode: leader  ###领导者
Mode: follower ##随从

#表示成功了

3.1.4 配置hadoop

1、集群规划:
节点NameNodeDataNodeResourceManagerNodeManagerJournalNodeZKFCQuorumPeerMain
hadoop101
hadoop102
hadoop103
2、在主节点上修改
  1. hdfs-site.xml

    <configuration>
    	<!--完全分布式集群的名称-->
    	<property>
    		<name>dfs.nameservices</name>
    		<value>mycluster</value>
    	</property>
    	<!--service下NN节点-->
    	<property>
    		<name>dfs.ha.namenodes.mycluster</name>
    		<value>nn1,nn2</value>
    	</property>
    	<!--两个NN的通信地址-->
    	<property>
    		<name>dfs.namenode.rpc-address.mycluster.nn1</name>
    		<value>hadoop101:8020</value>
    	</property>
    	<property>
    		<name>dfs.namenode.rpc-address.mycluster.nn2</name>
    		<value>hadoop102:8020</value>
    	</property>
    	<!--网络访问地址-->
    	<property>
    		<name>dfs.namenode.http-address.mycluster.nn1</name>
    		<value>hadoop101:50070</value>
    	</property>
    	<property>
    		<name>dfs.namenode.http-address.mycluster.nn2</name>
    		<value>hadoop102:50070</value>
    	</property>
    	<!--JournalNodes配置(元数据)-->
    	<property>
    		<name>dfs.namenode.shared.edits.dir</name>
    		<value>qjournal://hadoop101:8485;hadoop102:8485;hadoop103:8485/mycluster</value>
    	</property>
    	<!-- 声明journalnode服务器存储目录-->
    	<property>
    		<name>dfs.journalnode.edits.dir</name>
    		<value>/opt/module/hadoop-2.7.7/data/journal</value>
    	</property>	
    	<!--故障转移代理-->
    	<property>
    		<name>dfs.client.failover.proxy.provider.mycluster</name>
    		<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
    	</property>
    	<!-- 配置隔离机制,即同一时刻只能有一台服务器对外响应 -->
    	<property>
    		<name>dfs.ha.fencing.methods</name>
    		<value>sshfence</value>
    	</property>
    	<!-- 使用隔离机制时需要ssh无秘钥登录-->
    	<property>
    		<name>dfs.ha.fencing.ssh.private-key-files</name>
    		<value>/home/hadoop/.ssh/id_rsa</value>
    	</property>
    	<!--开启故障自动转移-->
    	<property>
    		<name>dfs.ha.automatic-failover.enabled</name>
    		<value>true</value>
    	</property>
    	<!-- 关闭权限检查-->
    	<property>
    		<name>dfs.permissions.enable</name>
    		<value>false</value>
    	</property>
    </configuration>
    
  2. core.site.xml

    <configuration>	
    	<!--修改之前的:把两个NameNode的地址组装成一个集群mycluster-->
    	<property>
    		<name>fs.defaultFS</name>
    		<value>hdfs://mycluster</value>
    	</property>
    	<!--指定hadoop运行时产生文件的存储目录-->
    	<property>
    		<name>hadoop.tmp.dir</name>
    		<value>/opt/module/hadoop-2.7.7/data/tmp</value>
    	</property>
    	<!--配置ZK-->
    	<property>
    		<name>ha.zookeeper.quorum</name>
    		<value>hadoop101:2181,hadoop102:2181,hadoop103:2181</value>
    	</property>
    </configuration>
    
  3. mapred-site.xml

    <configuration>
    	<!-- 指定MR运行在Yarn上 -->
    	<property>
    		<name>mapreduce.framework.name</name>
    		<value>yarn</value>
    	</property>
    	<!-- 历史服务器端地址 -->
    	<property>
    		<name>mapreduce.jobhistory.address</name>
    		<value>hadoop101:10020</value>
    	</property>
    	<!-- 历史服务器web端地址 -->
    	<property>
    		<name>mapreduce.jobhistory.webapp.address</name>
    		<value>hadoop101:19888</value>
    	</property>
    </configuration>
    
  4. slaves

    hadoop101
    hadoop102
    hadoop103
    
3、所有节点删除之前的data和logs文件
[hadoop@hadoop101 hadoop-2.7.7]$ rm -rf  data/ logs/
[hadoop@hadoop102 hadoop-2.7.7]$ rm -rf  data/ logs/
[hadoop@hadoop103 hadoop-2.7.7]$ rm -rf  data/ logs/
4、配置文件分发到其他节点
[hadoop@hadoop101 etc]$ pwd
/opt/module/hadoop-2.7.7/etc

[hadoop@hadoop101 etc]$  scp -r hadoop/  hadoop@hadoop102:`pwd`  ###`pwd`打印当前目录
[hadoop@hadoop101 etc]$  scp -r hadoop/  hadoop@hadoop103:`pwd`
以下操作一定按照步骤来:
5、启动zookeeper集群
####启动
[hadoop@hadoop101 hadoop]$ zkServer.sh start
[hadoop@hadoop102 hadoop]$ zkServer.sh start
[hadoop@hadoop103 hadoop]$ zkServer.sh start
####检查
[hadoop@hadoop101 hadoop]$ zkServer.sh  status
[hadoop@hadoop102 hadoop]$ zkServer.sh  status
[hadoop@hadoop103 hadoop]$ zkServer.sh  status
6、启动 JournalNode
[hadoop@hadoop101 hadoop-2.7.7]$ hadoop-daemon.sh start journalnode
[hadoop@hadoop102 hadoop-2.7.7]$ hadoop-daemon.sh start journalnode
[hadoop@hadoop103 hadoop-2.7.7]$ hadoop-daemon.sh start journalnode
7、在hadoop101上进行格式化并单独启动该节点的namenode
[hadoop@hadoop101 hadoop-2.7.7]$ hdfs namenode -format 
[hadoop@hadoop101 hadoop-2.7.7]$ hadoop-daemon.sh start namenode
8、在hadoop102上,同步hadoop101的元数据信息
[hadoop@hadoop102 hadoop]$ hdfs namenode -bootstrapStandby
9、初始化HA在Zookeeper中状态

在hadoop101(主节点)上执行

[hadoop@hadoop101 hadoop-2.7.7]$ hdfs zkfc -formatZK
10、启动集群

最好在hadoop101

[hadoop@hadoop101 hadoop-2.7.7]$ start-dfs.sh 
[hadoop@hadoop101 hadoop-2.7.7]$ start-yarn.sh 
11、校验

使用jps命令查看

浏览器查看:

http://hadoop101:50070/dfshealth.html#tab-overview Overview ‘hadoop101:8020’ (active)

http://hadoop102:50070/dfshealth.html#tab-overview Overview ‘hadoop102:8020’ (standby)

kill掉hadoop101上的namenode;

[hadoop@hadoop101 hadoop-2.7.7]$ kill -9 6060     ###6060为namenode进程的PID

再次访问:

http://hadoop101:50070/dfshealth.html#tab-overview 打开失败

http://hadoop102:50070/dfshealth.html#tab-overview Overview ‘hadoop102:8020’ (active)

再次单独启动hadoop101上的namenode:

[hadoop@hadoop101 hadoop-2.7.7]$ hadoop-daemon.sh start namenode
12、下次如何启动
  1. 首先启动zookeeper(启动三个节点)
  2. 然后再启动hdfs和yarn

联邦:

Hadoop集群启动后,NameNode在内存中保存了文件和块的映射关系,这意味着对于一个拥有大量文件的超大集群来说,由于数据量太大,NameNode的内存中可能也无法放下这么多的对应关系,内存将成为限制系统横向扩展的瓶颈。在Hadoop2.x版本中引入了HDFS联邦机制来解决这个问题。在联邦的HDFS中可以设置多个NameNode,每个NameNode管理文件系统命名空间中的一部分,例如一个NameNode可能管理/user目录下的所有文件,而另一个NameNode可能管理/docs目录下的所有文件。

在联邦环境下,每个NameNode维护一套命名空间的元数据和一个Block Pool(块池),数据块池包含该命名空间下文件的所有数据块。联邦的优点有如下几点

  1. 命名空间可伸缩性 – 联邦添加命名空间水平扩展。通过允许将更多Namenode添加到群集中,对有大量小文件的集群非常有用。
  2. 性能 – 文件系统吞吐量不受单个Namenode的限制。向集群添加更多NameNode可扩展文件系统读/写吞吐量。
  3. 隔离 – 通过使用多个Namenode,可以将不同类别的应用程序和用户隔离到不同的名称空间,并且彼此之间互不影响,即使一个NameNode失效,也不会影响到其它NameNode维护的命名空间的可用性。

第四章 HDFS

1、介绍

HDFS(Hadoop Distributed File System)起先是作为Apache Nutch搜索引擎项目的基础架构而开发的。HDFS是Hadoop的最核心项目之一,它被设计成适合部署在通用硬件(commodity hardware)上的分布式文件系统。

2、HDFS采用主从结构

hadoop1.x:

  • 只有一个主节点(namenode,NN)
  • 有多个从节点 (datanode,DN)

hadoop2.x

  • 可以有两个主节点(namenode,NN)
  • 有多个从节点 (datanode,DN)

Block:

​ 默情况下: 线性切割,1.x(64M)2.x(128M)

​ 默认情况下: 副本数为3

2.1 主节点(NameNode)的作用:

1、存储元数据

  • 文件owership和permissions
  • 文件大小,时间
  • Block列表:Block偏移量,位置信息(持久化不存)
  • Block每个副本的位置(由DataNode上报)
  • 负责管理文件系统中的树状目录结构

2.2 从节点(DataNode)的作用:

  • 本地磁盘目录存储数据(Block),文件形式
  • 同时存储Block的元数据信息文件(MD5)
  • 启动DN时会向NN汇报Block信息
  • 通过向NN发送心跳保存与其联系(3秒一次),如果NN10分钟没有收到DN的心跳,则认为该DN已经lost,并copy该DN上的block到其他DN。

2.3 SecondaryNameNode(SNN) 主要作用:

  • 它不是NN的备份(但是可以作为备份),它的主要工作是帮助NN和并editslog,减少NN启动时间
  • SNN执行合并时机
  • 根据配置文件设置的时间间隔fs.checkpoint.period 默认3600秒
  • 根据配置文件设置edits log大小 fs.checkpoint.size 规定edits文件的最大值默认是64MB

3、HDFS的shell操作

相关操作在安装目录的bin和sbin目录下,如果配置了环境变量可以直接使用

[hadoop@hadoop101 ~]$ hdfs dfs
Usage: hadoop fs [generic options]
	[-appendToFile <localsrc> ... <dst>]
	[-cat [-ignoreCrc] <src> ...]    ###查看文件内容
	[-checksum <src> ...]  
	[-chgrp [-R] GROUP PATH...]   ###修改所在组
	[-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]  ###修改权限
	[-chown [-R] [OWNER][:[GROUP]] PATH...] ### 修改拥有者
	[-copyFromLocal [-f] [-p] [-l] <localsrc> ... <dst>]   ###上传
	[-copyToLocal [-p] [-ignoreCrc] [-crc] <src> ... <localdst>] ###下载
	[-count [-q] [-h] <path> ...]
	[-cp [-f] [-p | -p[topax]] <src> ... <dst>]  ###拷贝
	[-createSnapshot <snapshotDir> [<snapshotName>]]
	[-deleteSnapshot <snapshotDir> <snapshotName>]
	[-df [-h] [<path> ...]]
	[-du [-s] [-h] <path> ...]
	[-expunge]
	[-find <path> ... <expression> ...]
	[-get [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]  ###下载
	[-getfacl [-R] <path>]
	[-getfattr [-R] {-n name | -d} [-e en] <path>]
	[-getmerge [-nl] <src> <localdst>]
	[-help [cmd ...]]
	[-ls [-d] [-h] [-R] [<path> ...]] ###查看目录
	[-mkdir [-p] <path> ...]    ###创建目录,该目录为HDFS的目录
	[-moveFromLocal <localsrc> ... <dst>]  ###删除并删除本地文件
	[-moveToLocal <src> <localdst>]  ###下载
	[-mv <src> ... <dst>]  ##移动
	[-put [-f] [-p] [-l] <localsrc> ... <dst>]  ####上传文件
	[-renameSnapshot <snapshotDir> <oldName> <newName>]
	[-rm [-f] [-r|-R] [-skipTrash] <src> ...]  ####删除文件
	[-rmdir [--ignore-fail-on-non-empty] <dir> ...]  ###删除目录
	[-setfacl [-R] [{-b|-k} {-m|-x <acl_spec>} <path>]|[--set <acl_spec> <path>]]
	[-setfattr {-n name [-v value] | -x name} <path>]
	[-setrep [-R] [-w] <rep> <path> ...]
	[-stat [format] <path> ...]
	[-tail [-f] <file>]   ###查看文件内容
	[-test -[defsz] <path>]
	[-text [-ignoreCrc] <src> ...] ###查看文件内容
	[-touchz <path> ...]   ###创建空文件
	[-truncate [-w] <length> <path> ...]
	[-usage [cmd ...]]

Generic options supported are
-conf <configuration file>     specify an application configuration file
-D <property=value>            use value for given property
-fs <local|namenode:port>      specify a namenode
-jt <local|resourcemanager:port>    specify a ResourceManager
-files <comma separated list of files>    specify comma separated files to be copied to the map reduce cluster
-libjars <comma separated list of jars>    specify comma separated jar files to include in the classpath.
-archives <comma separated list of archives>    specify comma separated archives to be unarchived on the compute machines.

The general command line syntax is
bin/hadoop command [genericOptions] [commandOptions]

3.1 创建目录

[hadoop@hadoop101 ~]$ hdfs dfs  -mkdir -p  /a/b/c
###   -p  表示级联创建目录

3.2 删除目录

[-rm [-f] [-r|-R] [-skipTrash] <src> ...]  ####删除文件
[-rmdir [--ignore-fail-on-non-empty] <dir> ...]  ###删除目录,只能删除空目录

[hadoop@hadoop101 ~]$ hdfs dfs -rmdir /qwy   ###删除目录,只能删除空目录,多级目录可以使用 以下命令
[hadoop@hadoop101 ~]$ hdfs dfs -rm -R  /a     ###删除目录,可以删除多级目录

3.3 上传文件

###hdfs dfs -copyFromLocal   本地路径   hdfs上的路径
###hdfs dfs -put  本地路径  hdfs上的路径
[hadoop@hadoop101 software]$ hdfs dfs -copyFromLocal ./my.txt /mypath
[hadoop@hadoop101 software]$ hdfs dfs -put /opt/software/my2.txt /mypath
###以上操作等价

###会将本地文件删除
[hadoop@hadoop101 software]$ hdfs dfs -moveFromLocal ./my3.txt /mypath

3.4 下载文件

[hadoop@hadoop101 software]$ hdfs dfs -copyToLocal /mypath/my.txt
[hadoop@hadoop101 software]$ hdfs dfs -get /mypath/my2.txt 

3.5 用户、组、权限

[-chgrp [-R] GROUP PATH...]   ###修改所在组
[-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]  ###修改权限
[-chown [-R] [OWNER][:[GROUP]] PATH...] ### 修改拥有者

[hadoop@hadoop101 software]$ hdfs dfs -chown admin /mypath/my.txt
[hadoop@hadoop101 software]$ hdfs dfs -chmod 777 /mypath/my.txt
[hadoop@hadoop101 software]$ hdfs dfs -chgrp abc /mypath/my.txt

3.6 拷贝

[-cp [-f] [-p | -p[topax]] <src> ... <dst>]  ###拷贝

[hadoop@hadoop101 software]$ hdfs dfs -cp /mypath/my.txt /abc

3.7 移动文件

[hadoop@hadoop101 software]$ hdfs dfs -mv /mypath/my2.txt /abc

4、HDFS的写流程

在这里插入图片描述

  1. Client首先与NameNode建立连接,发起文件上传请求。
  2. NameNode检查上传路径是否存在,目标文件是否存在,权限是否允许。若无问题则修改命名空间,并反馈Client允许上传。
  3. Client收到允许上传反馈后再次请求第一个Block所在的节点名。
  4. NameNode根据机架感知原理选取三个节点(datanode1,datanode2,datanode3)并将其反馈给Client。
  5. Client从获取的三个节点中选取一个节点建立pipeline连接,请求上传数据。节点1收到请求后与节点2获取连接,节点2收到请求后与节点3获取连接。
  6. 连接全部建立成功后,Client开始向第一个节点传输第一个block。该Block数据以packet为单位进行传输。数据的校验则是以更小的chunk单位进行。数据在Client本地和DataNode端都有读取和写入的缓存队列。每一次packet在pipeline上的传输都需要反向应答。直到写完预定的block为止。同样的,节点1、节点2和节点3之间也会以同样的方式同步传输。
  7. 当第一个block传输完成后,Client再次发送请求到NameNode,将整个流程再次重复。

5、副本的存储策略(机架感知)

  1. 第一个副本在Client所在的节点上,如果客户端在集群外,随机选择一个节点
  2. 第二个副本和第一个副本位于相同的机架,节点随机。
  3. 第三个副本位于不同机架,随机选择节点。

6、HDFS的读流程

hdfs读流程

  1. 客户端通过Distributed Filesystem向Namenode请求下载文件,Namenode通过查询元数据,找到文件数据块所在的DataNode的地址。
  2. 客户端挑选一台Datanode(就近原则,然后随机),请求读取数据
  3. DataNode开始传输数据给客户端(以Packet作为单位)
  4. 客户端以Packet作为单位接收数据,先在本地缓存,然后写入本目标文件。

7、HDFS的元数据

  1. 文件目录结构信息,及其自身的属性信息。
  2. 文件存储信息,包括文件分块信息及block和节点对应信息
  3. Datanode信息
    注意: Block的地址信息不在NameNode的元数据中保存。地址信息由DataNode向NameNode汇报(通过心跳机制)

NameNode的元数据信息在哪里保存?

内存?磁盘?
如果过在磁盘中可以吗?不可以,访问效率低。因此元数据放在内存中比较好。

但是还有问题,一旦断电等其他的情况,元数据就会丢失,整个集群以后就无法正常工作了。最好在内存中有一份,然后再磁盘中进行备份FsImage。

在内存修改元数据或追加元数据时,引入Edits文件(只能做追加操作,效率很高)


NameNode和SecondaryNameNode 的关系:

NameNode是集群的主节点,SecondaryNameNode 主要用来合并NameNode中的元数据信息的。

SecondaryNameNode不能作为NameNode的备份。


CheckPoint触发阈值由两个参数决定 :

  1. dfs.namenode.checkpoint.period:设置两次相邻CheckPoint之间的时间间隔,默认是1小时;
  2. dfs.namenode.checkpoint.txns:设置的未经检查的事务的数量,默认为一百万次。

第五章 MapReduce

一、MapReduce概述

Mappeduce是一个分布式运算程序的编程框架,是用户开发“基于hadoop的数据分析应用”的核心框架 。

Mapreduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一个hadoop集群上 。

二、MapReduce优缺点

优点:

  1. MapReduce易于编程

    我们在编写的时候,只需要实现一些定义好的接口,加上自己的业务逻辑,就可以开发一个分布式应用程序。

  2. 良好的扩展性

    可以通过简单的增加机器来扩展他的计算能力。

  3. 高容错性

    如果计算过程中,其中的一台机器挂了,器群可以把这个机器上的计算任务转移到另外其他节点上运行,而且这个过程不需要人工参与,这样就不至于这个任务失败。

  4. 海量数据的处理

    因为是集群工作,并且是并发运行,所以适合处理海量的数据运算。

缺点:

  1. 不擅长实时计算

    无法像Mysql等关系型数据库,在秒级或毫秒内就返回结果。

  2. 不擅长流式计算

    流式计算就是输入的数据是动态的,但是MapReduce处理的数据是静态的。

  3. 不擅长有向图计算

三、官方wordcount实例

1、创建目录并上传一个文件到HDFS

[hadoop@hadoop101 software]$ hdfs dfs -mkdir /mypath
[hadoop@hadoop101 software]$ hdfs dfs -put ./word.txt  /mypath
[hadoop@hadoop101 software]$ hdfs dfs -cat /mypath/word.txt

2、官方实例位置

[hadoop@hadoop101 mapreduce]$ pwd
/opt/module/hadoop-2.7.7/share/hadoop/mapreduce   ###目录
[hadoop@hadoop101 mapreduce]$ ll
total 4984
-rw-r--r--. 1 hadoop hadoop  540117 Jul 19  2018 hadoop-mapreduce-client-app-2.7.7.jar
-rw-r--r--. 1 hadoop hadoop  773735 Jul 19  2018 hadoop-mapreduce-client-common-2.7.7.jar
-rw-r--r--. 1 hadoop hadoop 1556812 Jul 19  2018 hadoop-mapreduce-client-core-2.7.7.jar
-rw-r--r--. 1 hadoop hadoop  189951 Jul 19  2018 hadoop-mapreduce-client-hs-2.7.7.jar
-rw-r--r--. 1 hadoop hadoop   27831 Jul 19  2018 hadoop-mapreduce-client-hs-plugins-2.7.7.jar
-rw-r--r--. 1 hadoop hadoop   62388 Jul 19  2018 hadoop-mapreduce-client-jobclient-2.7.7.jar
-rw-r--r--. 1 hadoop hadoop 1556921 Jul 19  2018 hadoop-mapreduce-client-jobclient-2.7.7-tests.jar
-rw-r--r--. 1 hadoop hadoop   71617 Jul 19  2018 hadoop-mapreduce-client-shuffle-2.7.7.jar
-rw-r--r--. 1 hadoop hadoop  296044 Jul 19  2018 hadoop-mapreduce-examples-2.7.7.jar  ###官方实例
drwxr-xr-x. 2 hadoop hadoop    4096 Jul 19  2018 lib
drwxr-xr-x. 2 hadoop hadoop      30 Jul 19  2018 lib-examples
drwxr-xr-x. 2 hadoop hadoop    4096 Jul 19  2018 sources

3、统计word.txt文件中每个单词出现的次数

[hadoop@hadoop101 mapreduce]$ hadoop jar hadoop-mapreduce-examples-2.7.7.jar wordcount /mypath/word.txt /rs

4、查看结果

[hadoop@hadoop101 mapreduce]$ hdfs dfs -cat /rs/part-r-00000

5、源码分析

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.hadoop.examples;

import java.io.IOException;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;

public class WordCount {

  public static class TokenizerMapper 
       extends Mapper<Object, Text, Text, IntWritable>{
    
    private final static IntWritable one = new IntWritable(1);
    private Text word = new Text();
      
    public void map(Object key, Text value, Context context
                    ) throws IOException, InterruptedException {
        //每一行按照 空格切分
      StringTokenizer itr = new StringTokenizer(value.toString());
      while (itr.hasMoreTokens()) {
        word.set(itr.nextToken());//每一个单词
        context.write(word, one);//输出key-value  key: 单词  value  数字1
      }
    }
  }
  
  public static class IntSumReducer 
       extends Reducer<Text,IntWritable,Text,IntWritable> {
    private IntWritable result = new IntWritable();

    public void reduce(Text key, Iterable<IntWritable> values, 
                       Context context
                       ) throws IOException, InterruptedException {
      int sum = 0;
      for (IntWritable val : values) {
        sum += val.get();//对每一个单词进行求和统计
      }
      result.set(sum);
      context.write(key, result);//输出key,value  key :单词,value:这个单词出现的次数
    }
  }

  public static void main(String[] args) throws Exception {
    Configuration conf = new Configuration();
    String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
    if (otherArgs.length < 2) {
      System.err.println("Usage: wordcount <in> [<in>...] <out>");
      System.exit(2);
    }
    Job job = Job.getInstance(conf, "word count");
    job.setJarByClass(WordCount.class);
    job.setMapperClass(TokenizerMapper.class);
    job.setCombinerClass(IntSumReducer.class);
    job.setReducerClass(IntSumReducer.class);
    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(IntWritable.class);
    for (int i = 0; i < otherArgs.length - 1; ++i) {
      FileInputFormat.addInputPath(job, new Path(otherArgs[i]));
    }
    FileOutputFormat.setOutputPath(job,
      new Path(otherArgs[otherArgs.length - 1]));
    System.exit(job.waitForCompletion(true) ? 0 : 1);
  }
}

6、开发wordcount程序

MapReduce程序编写规范:分成三部分 Mapper,Reducer,Dirver

6.1 Mapper阶段
  1. 自定义Mapper类要继承的父类
  2. Mapper的输入数据以KV对的形式(k1,v1)
  3. 在map方法中编写自己的业务逻辑
  4. 输出KV对象(k2,v2)
package com.inspur.mr;

import java.io.IOException;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
/**
 * Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT>
 * map的输入是以KV对的形式输入的(K1,V2)
 * K1:行的偏移量偏移量
 * V2:一行数据
 * map的输出是以KV对的形式输出的(K2,V2)
 * K2: 每一个单词
 * V2 :每一个单词记做 1 
 * @author qwy
 *
 */
public class WCMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
	Text k2= new Text();
	IntWritable v2=new IntWritable(1);
	//重写map方法
	@Override
	protected void map(LongWritable key, Text value, Context context)
			throws IOException, InterruptedException {
		//获取一行数据
		String line = value.toString();
		//按照制表符进行切割
		String[] words = line.split("\t");
		//输出
		for(String word:words){
			//这有有个问题?
			//context.write(new Text(word), new IntWritable(1));
			k2.set(word);
			context.write(k2, v2);
		}
	}
}
6.2 Reduce阶段
  1. 自定义Reducer实现父类
  2. Reducer的输入类型数据KV对的形式(K2,V2s)
  3. 在reduce方法中编写自己的业务逻辑
  4. 输出KV对对象(K3,V3)
package com.inspur.mr;
   
import java.io.IOException;
   
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
/**
* Reducer<KEYIN, VALUEIN, KEYOUT, VALUEOUT>
* reducer的输入k2,V2s(map阶段的输出类型)
* k2 就是要统计的每个单词()
* v2s:  map输出v2的一个迭代器
* 输出k3,V3
* k3: 单词
* v3:这个单词出现的次数
* @author qwy
*
*/
public class WCReducer extends Reducer<Text, IntWritable, Text, IntWritable>{
	Text k3=new Text();
   	IntWritable v3=new IntWritable();
   	//重写reduce方法
   	@Override
   	protected void reduce(Text k2, Iterable<IntWritable> v2s,
   			Context context) throws IOException, InterruptedException {
   		//定义一个变量,用来存储每个单词的累加和
   		int sum =0;
   		for(IntWritable count:v2s){
   			sum += count.get();
   		}
   		k3=k2;
   		v3.set(sum);
   		//输出
   		context.write(k3, v3);
	}
}
6.3 driver驱动类:
package com.inspur.mr;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
   
public class WCJob {
	public static void main(String[] args) throws Exception {
   		//1.获取配置信息,创建Job任务
   		Configuration configuration= new Configuration();
   		Job job = Job.getInstance(configuration);
   		//2.设置jar的加载路径
   		job.setJarByClass(WCJob.class);
   		//3.设置map和reduce的类型
   		job.setMapperClass(WCMapper.class);
   		job.setReducerClass(WCReducer.class);
   		//4.设置map的输出类型
   		job.setMapOutputKeyClass(Text.class);
   		job.setMapOutputValueClass(IntWritable.class);
   		//5.设置最终输出的类型(K3,V3)
   		job.setOutputKeyClass(Text.class);
   		job.setOutputValueClass(IntWritable.class);
   		//6.设置输入路径和输出路径
   		FileInputFormat.setInputPaths(job, new Path(args[0]));
   		FileOutputFormat.setOutputPath(job, new Path(args[1]));
   		//7.提交任务
   		boolean rs = job.waitForCompletion(true);
   		System.exit(rs ? 0 : 1 );//此步可以不用写
   	}
}
6.4 打jar包并上传到Linux

右键工程-export-java-jar-next-选择导出的路径,上传要统计的数据到hdfs上。

[hadoop@hadoop101 software]$ hadoop jar wc.jar com.inspur.mr.WCJob  /mypath/wc.txt  /wcrs

7、Hadoop的序列化

7.1 什么是序列化:

**序列化:**就是把内存中的对象,转换成字节码序列,以便于在磁盘存储或在网络间进行传输。

**反序列化:**就是将字节码序列重新转换成内存中的对象。

java中本身就提供了序列化机制,但是会附带很多额外的信息。不便于在网络间进行高效的传输,所以hadoop开发了自己的序列化。

7.2 序列化格式特点 :
  • 紧凑:高效使用存储空间。
  • 快速:读写数据的额外开销小
  • 可扩展:可透明地读取老格式的数据
  • 互操作:支持多语言的交互
7.3 Hadoop提供的默认的序列化的类型:
Java类型Hadoop Writable类型
byteByteWritable
shortShortWritable
intIntWritable
longLongWritable
floatFloatWritable
doubleDoubleWritable
StringText
mapMapWritable
arrayArrayWritale

自定义bean的序列化:

  1. 必须实现Writable接口
  2. 重写序列化的方法
  3. 重写反序列化的方法
  4. 重写toString方法
案例
1、数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vI6eRbNc-1655566332056)(/手机上网日志日志格式.jpg)]

1363157985066 	13726230503	00-FD-07-A4-72-B8:CMCC	120.196.100.82	i02.c.aliimg.com		24	27	2481	24681	200
1363157995052 	13826544101	5C-0E-8B-C7-F1-E0:CMCC	120.197.40.4			4	0	264	0	200
1363157991076 	13926435656	20-10-7A-28-CC-0A:CMCC	120.196.100.99			2	4	132	1512	200
1363154400022 	13926251106	5C-0E-8B-8B-B1-50:CMCC	120.197.40.4			4	0	240	0	200
1363157993044 	18211575961	94-71-AC-CD-E6-18:CMCC-EASY	120.196.100.99	iface.qiyi.com	视频网站	15	12	1527	2106	200
1363157995074 	84138413	5C-0E-8B-8C-E8-20:7DaysInn	120.197.40.4	122.72.52.12		20	16	4116	1432	200
1363157993055 	13560439658	C4-17-FE-BA-DE-D9:CMCC	120.196.100.99			18	15	1116	954	200
1363157995033 	15920133257	5C-0E-8B-C7-BA-20:CMCC	120.197.40.4	sug.so.360.cn	信息安全	20	20	3156	2936	200
1363157983019	13719199419	68-A1-B7-03-07-B1:CMCC-EASY	120.196.100.82			4	0	240	0	200
1363157984041 	13660577991	5C-0E-8B-92-5C-20:CMCC-EASY	120.197.40.4	s19.cnzz.com	站点统计	24	9	6960	690	200
1363157973098 	15013685858	5C-0E-8B-C7-F7-90:CMCC	120.197.40.4	rank.ie.sogou.com	搜索引擎	28	27	3659	3538	200
1363157986029 	15989002119	E8-99-C4-4E-93-E0:CMCC-EASY	120.196.100.99	www.umeng.com	站点统计	3	3	1938	180	200
1363157992093 	13560439658	C4-17-FE-BA-DE-D9:CMCC	120.196.100.99			15	9	918	4938	200
1363157986041 	13480253104	5C-0E-8B-C7-FC-80:CMCC-EASY	120.197.40.4			3	3	180	180	200
1363157984040 	13602846565	5C-0E-8B-8B-B6-00:CMCC	120.197.40.4	2052.flash2-http.qq.com	综合门户	15	12	1938	2910	200
1363157995093 	13922314466	00-FD-07-A2-EC-BA:CMCC	120.196.100.82	img.qfc.cn		12	12	3008	3720	200
1363157982040 	13502468823	5C-0A-5B-6A-0B-D4:CMCC-EASY	120.196.100.99	y0.ifengimg.com	综合门户	57	102	7335	110349	200
1363157986072 	18320173382	84-25-DB-4F-10-1A:CMCC-EASY	120.196.100.99	input.shouji.sogou.com	搜索引擎	21	18	9531	2412	200
1363157990043 	13925057413	00-1F-64-E1-E6-9A:CMCC	120.196.100.55	t3.baidu.com	搜索引擎	69	63	11058	48243	200
1363157988072 	13760778710	00-FD-07-A4-7B-08:CMCC	120.196.100.82			2	2	120	120	200
1363157985066 	13726238888	00-FD-07-A4-72-B8:CMCC	120.196.100.82	i02.c.aliimg.com		24	27	2481	24681	200
1363157993055 	13560436666	C4-17-FE-BA-DE-D9:CMCC	120.196.100.99			18	15	1116	954	200
2、需求

统计每一个手机号耗费的总上行流量、下行流量、总流量

3、需求分析

a:统计每一个手机号耗费的总上行流量、下行流量、总流量

b:输入数据格式

记录报告时间戳 手机号 APmac ACmac 访问的网址 网络种类 上行包 下行包 上行流量 下行流量 HTTP状态
1363157985066 13726230503 00-FD-07-A4-72-B8:CMCC 120.196.100.82 i02.c.aliimg.com 24 27 2481

​ 24681 200

c:期望输出格式

​ 手机号 上行流量 下行流量 总流量
13726230503 2481 24681 27162

d:Map阶段

d1:读取一行数据

1363157985066 	13726230503	00-FD-07-A4-72-B8:CMCC	120.196.100.82	i02.c.aliimg.com		    24	 	27		2481		24681		200

d2:抽取手机号、上行流量、下行流量
13726230503 2481 24681

d3:以手机号为key,bean对象为value输出,即context.write(手机号,bean)

d4:bean对象要想能够传输,则必须实现序列化接口。

e:Reduce阶段

累加上行流量和下行流量到总流量

  手机号		上行流量	+	下行流量	=	总流量
13726230503		2481		   24681		 27162
4、开发步骤
4.1 编写bean类
package com.inspur.tel;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

import org.apache.hadoop.io.Writable;
/**
 * 1.实现org.apache.hadoop.io.Writable接口
 * 2.重写序列化和反序列化的方法
 * 3. 提供必要的无参构造
 * 4. 重写toString
 * @author qwy
 *
 */
public class FlowBean implements Writable{
	private long upFlow;//上行流量
	private long downFlow;//下行流量
	private long sumFlow;//总流量
	//提供必要无参构造
	public FlowBean() {
	}
	//提供全参构造
	public FlowBean(long upFlow, long downFlow, long sumFlow) {
		super();
		this.upFlow = upFlow;
		this.downFlow = downFlow;
		this.sumFlow = upFlow + downFlow;//计算总流量
	}

	/**
	 * 序列化的方法
	 * 注意:序列化和反序列化的字段顺序要一致
	 */
	@Override
	public void write(DataOutput out) throws IOException {
		out.writeLong(upFlow);
		out.writeLong(downFlow);
		out.writeLong(sumFlow);
	}
	/**
	 * 反序列化的方法
	 */
	@Override
	public void readFields(DataInput in) throws IOException {
		this.upFlow = in.readLong();
		this.downFlow=in.readLong();
		this.sumFlow=in.readLong();
	}
	//重写toString方法
	@Override
	public String toString() {
		return upFlow + "\t" + downFlow + "\t" + sumFlow ;
	}
	/**
	 * @return
	 */
	public long getUpFlow() {
		return upFlow;
	}
	public void setUpFlow(long upFlow) {
		this.upFlow = upFlow;
	}
	public long getDownFlow() {
		return downFlow;
	}
	public void setDownFlow(long downFlow) {
		this.downFlow = downFlow;
	}
	public long getSumFlow() {
		return sumFlow;
	}
	public void setSumFlow(long sumFlow) {
		this.sumFlow = sumFlow;
	}
}
4.2 编写mapper
package com.inspur.tel;

import java.io.IOException;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

/**
 * 1.继承mapper类
 * 2.重写map方法
 * Mapper<偏移量, 一行文本, 手机号, 自定义的bean>
 */

public class TelDataMapper extends Mapper<LongWritable, Text, Text, FlowBean>{
	Text k2=new Text();
	FlowBean v2=new FlowBean();
	@Override
	protected void map(LongWritable key, Text value, Context context)
		throws IOException, InterruptedException {
		//1.获取一行数据
		String line = value.toString();
		//2.切割一行数据使用制表符(\t)
		String[] fields = line.split("\t");
		//3.获取要统计的字段
		//获取手机号
		String telNo=fields[1];
		//获取上行流量和下行流量
		long upFlow=Long.parseLong(fields[8]);
		long downFlow=Long.parseLong(fields[9]);
		k2.set(telNo);
		//??可不可以简化
		v2.setDownFlow(downFlow);
		v2.setUpFlow(upFlow);
		//map输出
		context.write(k2, v2);
	}
}
4.3 编写reduce
package com.inspur.tel;

import java.io.IOException;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

/**
 * 1. 继承Reduce类
 * 2. 重写Reduce方法
 * Reducer<手机号, 自定义FlowBean, 手机号, 自定义FlowBean>
 * @author qwy
 *
 */
public class TelDataReduce extends Reducer<Text, FlowBean, Text, FlowBean>{
	Text k3= new Text();
	FlowBean v3=new FlowBean();
	@Override
	protected void reduce(Text k2, Iterable<FlowBean> v2s, Context context)
			throws IOException, InterruptedException {
		//定义计数器
		long sum_upFlow=0;//上行总流量
		long sum_downFlow=0;//下行总流量
		long sum_total=0;
		//遍历所有的bean,统计上行总流量、下行总流量
		for(FlowBean bean: v2s){
			sum_upFlow += bean.getUpFlow();
			sum_downFlow +=bean.getDownFlow();
		}
		//就算这个手机上网的总流量
		sum_total = sum_upFlow +sum_downFlow;
		
		k3=k2;
		//???
		v3.setUpFlow(sum_upFlow);
		v3.setDownFlow(sum_downFlow);
		v3.setSumFlow(sum_total);
		//输出
		context.write(k3, v3);
	}
}
4.4 编写driver
package com.inspur.tel;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

/**
 * Driver驱动
 * @author qwy
 *
 */
public class TelDataJob {
	public static void main(String[] args) throws Exception  {
		//1.获取配置信息,并创建job对象
		Configuration configuration= new Configuration();
		Job job = Job.getInstance(configuration);
		//2.指定jar的路径
		job.setJarByClass(TelDataJob.class);
		//3.指定mapper和reduce类
		job.setMapperClass(TelDataMapper.class);
		job.setReducerClass(TelDataReduce.class);
		//4.指定mapper的输入的key(k2)和value(v2)的数据类型
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(FlowBean.class);
		//5.指定最终输入的key(k3)和value(v3)的类型
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(FlowBean.class);
		//6.指定输入(要统计的原始文件)和输出的路径(结果的存放位置)
		FileInputFormat.setInputPaths(job, new Path(args[0]));
		FileOutputFormat.setOutputPath(job, new Path(args[1]));
		//7.提交任务
		job.waitForCompletion(true);
	}
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值