Hadoop

Hadoop

Day01

学习方法:

做笔记

MarkDown

有道云笔记

写博客 csdn

官网(Hadoop Hive...Spark,Flinkxxx.apache.org

背单词

大数据相关的博客和论坛

CSDN

about

36大数据

http://www.36dsj.com/

 

一、大数据:

1.大数据起源于社交网络

QQ 博客 微信

发展于电商平台

淘宝,京东,一号店

 

交通大数据

金融行业 银行 保险公司

 

携程 途牛旅游网站

在线教育网站

游戏网站

 

DBA

 

2.***大数据的4V特征

Volume   数据量大 TB PB

         1PB(Petabyte 拍字节) = 2^10 TB = 1024 TB

   1EB(Exabyte 艾字节) = 2^10 PB = 1024 PB

  1ZB(Zettabyte 泽字节) = 2^10 EB = 1024 EB

  1YB(YottaByte 尧字节) = 2^10 ZB = 1024 ZB

 

  1BB(Brontobyte ) = 2^10 YB = 1024 YB

   1NB(NonaByte ) = 2^10 BB = 1024 BB

   1DB(DoggaByte) = 2^10 NB = 1024 NB

Varity   的数据多种多样文本(.log .txt .sql .xml

Veracity 价值密度低 商业价值高

Velocity  速度快

 

Hadoop ->  传统的数据统计分析  Mysql

Spark  ->   Hadoop   在内存快100倍 在磁盘快10

 

3.企业大数据分析的数据来源

(理解) 企业内部

:日志记录(应用服务器 Nginx

:关系型数据库

 

外部渠道

 :爬虫(Python

 API(网站埋点技术 jsSDK JavaSDK

 

4.大数据应用发展前景

拉勾网  智联招聘

**大数据应用分析

1)统计 -》  数据仓库

2)个性化推荐(预测)

3)机器学习  图形计算

4)人工智能

 

二、Hadoop 的概念

1.Hadoop的起源及发展史

大数据 Hdoop

Doug Coutting  Hadoop之父

 

2.*** Goolge 三大论文 大数据的三驾马车

Goolge Hadoop

文件系统     GFS        ->   HDFS

计算MapReduce  ->   Mapreduce

大表格BigTable     ->   HBase

 

http://hadoop.apache.org/

 

The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models. It is designed to scale up from single servers to thousands of machines, each offering local computation and storage. Rather than rely on hardware to deliver high-availability, the library itself is designed to detect and handle failures at the application layer, so delivering a highly-available service on top of a cluster of computers, each of which may be prone to failures.

 

3.Apache Hadoop是一个应用java语言实现的软件框架,由大量的廉价的计算机组成的集群中运行海量数据的可靠的,可扩展的分布式并行计算框架,它可以让应用程序支持上千个节点和PB级别的数据。Hadoop是项目的总称,主要是由分布式存储(HDFS)、和分布式并行计算(MapReduce)等组成。

  Hadoop Common: The common utilities that support the other Hadoop modules.

    Hadoop Distributed File System (HDFS™): A distributed file system that provides high-throughput access to application data.

    Hadoop YARN: A framework for job scheduling and cluster resource management.

    Hadoop MapReduce: A YARN-based system for parallel processing of large data sets.

4.*** Hadoop的四个模块,也叫四大组件

 

Hadoop Common  公共模块(支其他Hadoop模块的公用工具,包括FileSystem(面向通用文件系统的抽象类)、远程过程调用(RPC)和序列化库)

Hadoop HDFS   存储数据:一个为访问应用数据提供高吞吐量的分布式文件系统。

Hadoop YARN    管理资源(Hadoop2.x)  一个全局的任务调度与资源管理的框架--YARNmareduce的云操作系统

Hadoop MapReduce  并行计算框架:一个基于Yarn的大数据分布式并行计算框架

5.Hadoop的发行版本:

Apache

Cloudera    商业发行版(卖服务)cdh

7.Hadoop的体系架构

HDFS

NameNode(一个集群只有一个):用于保存元数据信息(Namenode将元数据保存在内存中),同时会在硬盘上保留一份。元数据(Filename、副本数,各个副本所在的节点的位置)

学生信息管理系统

书的目录

DataNode:用于具体保存数据的

HDFS上保存的数据副本数,默认是3个,副本数可以设置

每个班级的学生(本人)

每个章节的具体的内容

 

SecondaryNameNode: 用于同步元数据信息

 

YARN

ResourceManager:负责全局的资源管理Container:硬件资源(CPU,内存,硬盘))

教务处主任(教学资源:教室:实验室 阶梯教室 体育馆)

Nodemanager:负责所在节点上的资源

班主任 机房管理员

Mapreduce

分两个阶段:MapReduce  计算框架,编程模型 “分而治之”的思想

100副扑克,少了一张,那么可以找50个人。每个人分2副本扑克

分布式并行计算

 

三、Hadoop的安装运行模式:

单机模式:

1.单机(本地)运行模式

无需运行任何守护进程,所有程序都在单个JVM上执行,测试用

 

分布式:

2.伪分布式

将所有的守护进程运行在一个节点

 

3.集群模式

1)完全分布式

不同的守护进程运行在不同的节点

2)HA

Namenode HA

3)联盟

Hadoop2.x环境搭建

一、系统环境准备工作:

1、把网卡IP设置成静态(NAT模式)

** 首先查看网卡IP

$ ip a $ ifconfig (network interfaces configuring)网络接口配置

** 然后配置VPNVirtual Private Network 虚拟专用网络)

a. 右下角选择"配置VPN"

b. 选择eth0,点击编辑

c. IPv4页面设置

   方法:手动  

   添加:地址192.168.122.128 掩码255.255.255.0 网关192.168.122.2

   DNS服务器:192.168.122.2, 202.96.209.5

   勾选需要IPv4

#202.96.209.5(或133)是上海电信DNS服务器(baidu),8.8.8.8Google服务器

***配置NotepadNppFTP来修改文件,协议必需要选择SFTP***

** 插件--NppFTP--勾选"show NppFTP window"

** 注意:文件必需在Linux里建,可以在Windows里改

编辑文件(root

# vi /etc/sysconfig/network-scripts/ifcfg-eth0

#注意:VPN修改后,文件名会变化,如:ifcfg-Auto_eth0

ONBOOT=yes   # 把网卡设置成开机启动

BOOTPROTO=static   # DHCP改为staticLinux严格区分大小写,一定要注意

IPADDR=192.168.122.128

NETMASK=255.255.255.0

GATEWAY=192.168.122.2   #前三位相同,末位设置为2,NAT模式特有的做法

 

设置好后,重启网卡:

# ifup eth0 (若是有问题,将文件中以IPV6开头的行删除)

#Linuxeth0eth1eth2分别表示网卡一,网卡二,网卡三 ……

#/etc/sysconfig/network-scripts/ifcfg-eth0文件内容参照如下:

#若是有问题就将IPV6开头的删除

DEVICE="eth0"

BOOTPROTO=static

IPV6INIT="yes"

NM_CONTROLLED="yes"

ONBOOT="yes"

TYPE="Ethernet"

UUID="0faffc60-5eda-421f-9cb9-c90cea321005"

HWADDR=00:0C:29:3D:37:60

IPADDR=192.168.122.128

NETMASK=255.255.255.0

PREFIX=24

GATEWAY=192.168.122.2

DNS1=192.168.122.2

DNS2=202.96.209.5

DEFROUTE=yes

IPV4_FAILURE_FATAL=yes

IPV6_AUTOCONF=yes

IPV6_DEFROUTE=yes

IPV6_PEERDNS=yes

IPV6_PEERROUTES=yes

IPV6_FAILURE_FATAL=no

NAME="System eth0"

LAST_CONNECT=1477989881

2、设置DNS

# vi /etc/sysconfig/network-scripts/ifcfg-eth0 (同一个文件)

DNS1=192.168.200.2#第一个DNS设置成跟网关地址一样,NAT模式比较特殊

DNS2=202.96.209.5    上海的DNS

# service network restart  #重启network服务,即网络服务

3、修改主机名

** 集群内部的主机名通常都会使用统一的命名格式

** 注意:hadoop里主机名不能使用下划线

gu.com

chao.com

feng.com

 

# vi /etc/sysconfig/network

HOSTNAME=gu.com

查看主机名:

# hostname

 

4、关闭Linux防火墙和selinux

** 默认情况下,防火墙只开启了22号端口,会影响集群通讯

# service iptables status

# service iptables stop   # 关闭防火墙服务

# chkconfig iptables off  # 设置为开机不启动

# chkconfig --list        # 列出所有的系统服务

# chkconfig --list | grep iptables

PS

等级代号指定该系统服务要在哪一个执行等级中开启或关闭。

等级0表示:表示关机,系统默认运行级别不能设置为0,否则不能正常启动、关闭。

等级1表示:单用户模式

等级2表示:无网络连接的多用户命令行模式

等级3表示:有网络连接的多用户命令行模式

等级4表示:等级4保留,一般不用,可以处理一些特殊情况。如笔记本电池用尽时,可以切换到这个模式来做一些设置。

等级5表示:带图形界面的多用户模式

等级6表示:重新启动

# 关闭selinux,是一个安全子系统,它能控制程序只能访问特定文件

# vi /etc/sysconfig/selinux(注意:此文件在notepad中不可见)

SELINUX=disabled   # enforcing改成disabled

5、添加主机名映射

** 后面需要多次使用主机名

# vi /etc/hosts

在最后一行添加:192.168.122.128gu.com

6、创建普通用户

** 后期所有操作都尽量使用普通用户来进行

# useradd tom #创建用户tom

# passwd tom  #设置密码

# echo blue | passwd --stdin tom  #--stdin接收系统输入数据

PS:

** 安装rz

# yum install lrzsz -y

Xshell工具--选项--键盘和鼠标

右键粘贴功能: 修改“右键按钮”为:paste the clipboard contents

选中复制功能:勾选“将选中的内容自动复制到剪贴板”

 

=============================安装jdk======================================

 普通$ tar -zxf jdk-7u67-linux-x64.tar.gz  -C ../modules/

配置环境变量

  root# vim /etc/profile

#JAVA_HOME

export JAVA_HOME=/opt/modules/jdk1.7.0_67

 

export PATH=$PATH:$JAVA_HOME/bin

使配置生效

 # source /etc/profile

卸载openJDK

  # rpm -qa | grep jdk

  # rpm -e  --nodeps   XXX.rpm   //不验证依赖进行卸载

1.种:三、配置Hadoop  ${HADOOP_HOME}---hadoop的安装目录

解压安装hadoop【注意上传和解压过程中的用户权限问题】

$ tar -zxf hadoop-2.5.0.tar.gz -C  /opt/modules/

2.配置hadoopjava环境支持, ${HADOOP_HOME}/etc/hadoop目录下

hadoop-env.sh

mapred-env.sh

yarn-env.sh

在这3个文件中都配置

export JAVA_HOME=/home/gu/ruan/jdk

3.hdfs相关的配置   ${HADOOP_HOME}/etc/hadoop

1core-site.xml

========================core-site.xml==========================

<!--NameNode地址,8020是指定进程8020,访问入口 -->    

<property>

        <name>fs.defaultFS</name>

        <value>hdfs://gu.com:8020</value>

    </property>

 

<!--hadoop在运行时产生的文件,元数据在本地的存放目录 -->

<property>

<name>hadoop.tmp.dir</name>

<value>/opt/modules/hadoop-2.5.0/data</value>

</property>

============================================================

2)hdfs-site.xml

=======================hdfs-site.xml==========================

<!--存放到hdfs上的文件的副本数,伪分布式配置为1 -->

<property>

        <name>dfs.replication</name>

        <value>1</value>

    </property>

===========================================================

    3)格式化namenode  只格式化一遍,不要重复格式化

    ${HADOOP_HOME}目录下:

$ bin/hdfs namenode -format       

 

    17/03/21 00:34:52 INFO common.Storage: Storage directory /opt/modules/hadoop-2.5.0/data/dfs/name has been successfully formatted.

    4)启动hdfs守护进程

    $ sbin/hadoop-daemon.sh start namenode  //启动namenode进程

$ sbin/hadoop-daemon.sh start datanode    //启动datanode

 

$  jps

3097 Jps

2931 NameNode

3023 DataNode

 

 

web访问界面

http://gu.com:50070/

5)HDFS文件系统常用命令

$ bin/hdfs dfs   //可以查看所有的dfs相关的操作指令

$ bin/hdfs dfs -ls /  

$ bin/hdfs dfs -mkdir -p /input/test

$ bin/hdfs dfs  -rmdir /input/test

$ bin/hdfs dfs  -put /opt/software/jdk-7u67-linux-x64.tar.gz /input/test

 

3.配置YARN  任务调度 (Mapreduce) 资源管理(resourcemanager nodemanager

${HADOOP_HOME}/etc/hadoop目录下配置yarn-site.xml

 

=======yarn-site.xml =====

<!-- 指定ResorceManager所在服务器的主机名-->

<property>

<name>yarn.resourcemanager.hostname</name>

<value>[hostname]</value>

</property>

<!-- 指明在执行MapReduce的时候使用shuffle-->

<property>

<name>yarn.nodemanager.aux-services</name>

<value>mapreduce_shuffle</value>

</property>

====================================

复制并重名模板文件

$ cp etc/hadoop/mapred-site.xml.template etc/hadoop/mapred-site.xml

 Cp home/gu/ruan/hadoop-2.5.0/etc/hadoop/mapred-site.xml.template home/gu/ruan/hadoop-2.5.0/etc/hadoop/mapred-site.xml

=======mapred-site.xml=====

${HADOOP_HOME}/etc/hadoop目录下配置mapred-site.xml

<!-- 指定MapReduce基于Yarn来运行-->

<property>

<name>mapreduce.framework.name</name>

<value>yarn</value>

</property>

=====================================

4.启动hdfs yarn进程

$ sbin/hadoop-daemon.sh start namenode

$ sbin/hadoop-daemon.sh start datanode

$ sbin/yarn-daemon.sh start resourcemanager

$ sbin/yarn-daemon.sh start nodemanager

5.检查hdfs yarn启动状态,即查看守护进程 jps

6.yarn提交mapreducer任务

1)计算圆周率

$ bin/yarn jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.5.0.jar  pi 5 3

2wordcount词频统计

a.在用户主目录创建一个wordcount.txt

$ vi /home/user01/wordcount.txt

hadoop java

html java

linux hadoop

yarn hadoop

b.上传到hdfsinput目录下

$ bin/hdfs dfs -put ~/wordcoun.txt /input/

c.提交wordcount任务

执行方式

bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.5.0.jar  wordcount  /input /output

 

 

【报错】:再次执行wordcount会提示输出目录已存在

org.apache.hadoop.mapred.FileAlreadyExistsException: Output directory hdfs://gu.com:8020/output already exists

【报错】:unknowHostException  

检查主机映射

【解决办法】

删除hdfs上的输出目录或者重新指定输出目录

【常见错误】:

1:主机名配置错误或者未配置主机名;

2:配置的参数【<name>标签对】错误,<value>标签对参数有空格

3xml的注释格式错误,标签对未对齐

4namenode重复格式化

5:修改配置参数未保存,进程未重启

PS

编译Hadoop(选做,在Windows平台安装hadoop时,或者添加Hadoop一些额外功能时,才需要编译)

**  hadoop-2.5.0.tar.gz  编译过后的包

**  hadoop-2.5.0-src.tar.gz  没有经过编译的

** 系统必须联网(mvn仓库)

hadoop-2.5.0-src.tar.gz --> hadoop-2.5.0.tar.gz

** 时间比较长,而且对网络条件要求高,只要有一个包maven下载漏掉,就要重新编译,很麻烦(参考编译操作文档)

PS

一、MapRMapR Technologies, Inc的一个产品,号称下一代Hadoop,使Hadoop变为一个速度更快、可靠性更高、更易于管理、使用更加方便的分布式计算服务和存储平台,同时性能也不断提高。它将极大的扩大了Hadoop的使用范围和方式。它包含了开源社区的许多流行的工具和功能,例如HbaseHive。它还100%Apache HadoopAPI兼容。它能够为客户节约一半的硬件资源消耗,使更多的组织能够利用海量数据分析的力量提高竞争优势。目前有两个版本,M3M5,其中M3是免费版,

M5为收费版。

二、NAT(Network Address Translation)网络地址转换,它是一个IETF标准,允许一个整体以一个公用IP地址出现在Internet上。

顾名思义,它是一种把内部私有网络地址翻译成合法网络IP地址的技术。简单的说,NAT就是在局域网内部网络中使用内部地址,

而当内部节点要与外部网络进行通讯时,就在网关处,将内部地址替换成公用地址,从而在外部公网(internet)上正常使用,

这一功能很好地解决了公共IP地址紧缺的问题。通过这种方法,只申请一个合法IP地址,就把整个局域网中的计算机接入Internet

内部网计算机用户通常不会意识到NAT的存在。NAT功能通常被集成到路由器、防火墙、ISDN路由器或者单独的NAT设备中。

NAT有三种类型:静态NAT(Static NAT)、动态地址NAT(Pooled NAT)、网络地址端口转换NAPTPortLevel NAT)。其中,

静态NAT设置起来最为简单和最容易实现的一种,内部网络中的每个主机都被永久映射成外部网络中的某个合法的地址。

在使用的之前 可以将  rm -rf /tmp/*.pid  这样可以避免namenodedatanode的一些异常错误。

8020是为web50070)界面提供数据流的端口

Hadoop分布环境搭建的步骤:

   1.环境准备

      静态Ip地址的配置(包括DNS

      主机名称的更改

      配置所需的映射

      防火墙的关闭

   2.JDK的安装

       环境的配置

        # vi /etc/profile(root用户)

   3.hadoop的安装(实际上就是在对应的目录下解压)

       环境的配置

       hadoop-env.sh  mapred-env.sh  yarn-env.sh

   文件的配置

     hdfs-site.xml  core-site.xml  mapred-site.xml  yarn-site.xml

格式化(在没有报错的时候)

$ bin/hdfs namenode -format  

   在命令行开启相对应的进程

   Jps检查是否开启

       测试环境是否存在问题

         Web

       http://gu.com:50070/

           http://gu.com:8088/

 

2种:

在使用本地模式MapReduce程序运行在本地,启动JVM

$ bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.5.0.jar grep  input output 'dfs[a-z.]+'

统计

[hadoop-2.5.0]$ mkdir wcinput

[hadoop-2.5.0]$ cd wcinput

[wcinput]$ touch wc.input

[wcinput]$ vi wc.input

$bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.5.0.jar wordcount (统计)wcinput(所需要统计的文件目录) wcoutput(自己命名的在查询时用的到)

[hadoop-2.5.0]$ cat wcoutput/part-r-00000(查看统计结果)

akjfdskhfdsj    1

asdasfd 1

asdfasdfasdkhaudsfsdfajsdvjk    1

asdflahfdsiuhasdkuf     1

asdfnaksdfalkvljkvas    1

fsdfasdfasd     1

hadoop  1

sadfkashdkjfafdskj      1

yarn    1

 

伪分布式:

配置core-site.xml(配置文件系统hdfs)

<configuration>

    <property>

<name>fs.defaultFS</name>

<value>hdfs://gu.com:8020</value>

    </property>

 

<property>

<name>hadoop.tmp.dir</name>

<value>/home/gu/linux/hadoop-2.5.0/date/tmp(自己新建的一个临时文件)</value>

    </property>

</configuration>

hdfs-site.xml  伪分布式配置为1,其他的时候则不需要

<configuration>

   <property>

     <name>dfs.replication</name>

 <value>1</value>

   </property>

</configuration>

对他进行格式化:

bin/hdfs namenode –format

启动namenode(主节点)

sbin/hadoop-daemon.sh start namenode

启动datanode(从节点)

sbin/hadoop-daemon.sh start datanode

 

hdfs的监控界面可以通过50070来查看文件信息

http://gu.com(映射名):50070/dfshealth.html#tab-overview

通过dfs来对hdfs文件系统进行操作

bin/hdfs dfs -mkdir -p /user/gu/

循环查看hdfd 文件目录bin/ hdfs dfs –ls –R  /

 

因为跑的是mapreduce所以再建立一个便于管理

bin/hdfs dfs -mkdir -p /user/ gu/mapreduce/wordcount/input

上传到文件

   bin/hdfs dfs -put wcinput/wc.input /user/gu/mapreduce/wordcount/input/

 

跑一下

 bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.5.0.jar wordcount /user/gu/mapreduce/wordcount/input/ /user/gu/mapreduce/wordcount/output 

 

配置yarn

  1. 配置yarn-site.xml

<property>

   <name>yarn.nodemanager.aux-services</name>

   <value>mapreduce_shuffle</value>

 </property>

 

 <!--bendi-->

  <property>

   <name>yarn.resourcemanager.hostname</name>

   <value>gu.com</value>

 </property>

配置环境文件yarn-env.sh 

Jdk环境的位置  export JAVA_HOME=/home/gu/linux/jdk1.7.0_67

  1. slaves文件决定了node的主节点从节点的分布

gu.com

  1. 启动yarn的主节点sbin/yarn-daemon.sh start resourcemanager  

从节点sbin/yarn-daemon.sh start nodemanager

 

 

Yarn的监控界面

http://gu.com:8088/cluster

mapreduceyarn上运行

  1. 配置mapred-env.sh

export JAVA_HOME=/home/gu/linux/jdk1.7.0_67

  1. 配置mapred-site.xml.template重命名为mapred-site.xml

<configuration>

<property>

  <name>mapreduce.framework.name</name>

  <value>yarn</value>

</property>

</configuration>

3.  输出目录不能存在不然会报错所以要删除它

bin/hdfs dfs -rm -R /user/gu/mapreduce/wordcount/output/

然后跑一下

bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.5.0.jar wordcount /user/gu/mapreduce/wordcount/input/ /user/gu/mapreduce/wordcount/output

 

Jps 查看开启的程序(线程)

======================================================================================

Hadoop 2.x

  Common

Hdfs

   存储数据

   NameNode

      存储文件系统的元数据,命名空间namespace

   DataNode

      存储数据(每一台机器上面)

   SecondaryNameNode

      辅助NameNode工作,合并两个文件(定时周期性)

客户端先于NameNode进行交互,获取需要读取的文件所在位置。然后再到具体的DataNode去读文件数据 数据流不经过NameNode

YARN

  Hadoop操作系统

  Data 操作系统

  Container(容器)对资源的隔离

  ResouceManager 对整个集群的管理和调度

  NodeManager 对每个节点管理的资源与调度

MapReduce

  分而治之的思想

map

 “分”,大的分成小的,每一份都进行单独的处理

   Reduce

     “合并”

Input  -> map  shuffle(排序) ->reduce  ->output

分布式并行的计算框架

运行模式:

  本地模式上(小数据上)

  Yarn模式上

bin/hdfs(脚本) dfs(运行文件系统的命令)

查看自带的一些案例

bin/yarn jar share/hadoo[p/mapreduce/hadoop-mapreduce-examples-2.5.0.jar

mapreduce默认功能排序升序

测试程序:

 HadoopMapReduce提供的三个程序ckiruo程序

teragen :生成数据

terasort:对数据进行排序

teravalidate:验证排序的结果

 

==================================问题====================================================

在格式化时出错:$ bin/hdfs namenode –format

  1. 配置文件错误(在文件格式化时会先读取core-site.xml配置文件)
  2. 主机名与IP地址的映射问题
  3. NameNode启动出错

  需要查看日志信息[hadoop]$ll /logs

More 翻页查看 以log结尾的文件

Tail:文件的末尾

 

 

Yarn的历史服务器

需要启动一下

$ sbin/mr-jobhistory-daemon.sh start historyserver

Log Aggregation

   日志聚集

应用运行完成以后,将日志信息上传到HDFS系统上,

需要配置yarn-site.xml文件

<!--aggregation log-->

  <property>

   <name>yarn.log-aggregation-enable</name>

   <value>true</value>

 </property>

 <!--log save time-->

 <property>

   <name>yarn.log-aggregation.retain-seconds</name>

   <value>640200(秒默认-1永久保存)</value>

 </property>

配置完成后需要重启一下

关闭

sbin/yarn-daemon.sh stop resourcemanager

sbin/yarn-daemon.sh stop nodemanager

sbin/mr-jobhistory-daemon.sh stop historyserver

开启

sbin/yarn-daemon.sh start resourcemanager

sbin/yarn-daemon.sh start nodemanager

sbin/mr-jobhistory-daemon.sh start historyserver

 

============================启动方式================================

各个服务组件逐一启动

hdfs

   hadoop-daemon.sh start|stop namenode|datanode|secondarynamenode

yaen

   yarn-daemon.sh staret|stop resourcemanager|nodemanager

mapreduce

   mr-historyserver-deamon.sh start|stop historyserver

脚本

各个模块分开启动所以要配置ssh(通过ssh来实现)

(sbin/start.sh)

Hdfs

start-dfs.sh

stop-dfs.sh

yarn

start-yarn.sh

stop-yarn.sh

需要配置一下

  脚本是在主节点上运行的

配置SSH无秘钥登录

  

 

 

 

在根目录下的.shh目录中

   生成公钥 ssh-keygen –t rea

指定用户使用公钥

ssh-copy-id (hostname)

全部启动或停止(不推荐)

 Start-all.sh

 Stop-all.sh

==============================总结============================================

守护进程

HDFS

NameNode

core-site.xml

  <property>

     <name>fs.defaultFS</name>

     <value>hdfs://guyu.com:8020</value>

</property>

 

DataNode

  slaves

     guyu.com

hdfs-site.xml

   <property>

     <name>dfs.namenode.secondary.http-address </name>

     <value>hdfs://guyu.com:50090</value>

</property>

 

 

7.配置日志聚合

=======mapred-site.xml=========

**追加到原来配置和后面

<property>

<name>mapreduce.jobhistory.address</name>

<!--配置实际的主机名和端口-->

<value>[hostname]:10020</value>

</property>

<property>

<name>mapreduce.jobhistory.webapp.address</name>

<value>[hostname]:19888</value>

</property>

==============yarn-site.xml=======

<!--启用日志聚合功能-->

<property>

<name>yarn.log-aggregation-enable</name>

<value>true</value>

</property>

<!--日志保存时间-->

<property>

<name>yarn.log-aggregation.retain-seconds</name>

<value>86400</value>

</property>

8.停止所有进程重新启动,以便配置文件生效

1)停止进程

$ sbin/hadoop-daemon.sh stop namenode

$ sbin/hadoop-daemon.sh stop datanode

$ sbin/yarn-daemon.sh stop resourcemanager

$ sbin/yarn-daemon.sh stop nodemanager

2)启动进程

$ sbin/hadoop-daemon.sh start namenode

$ sbin/hadoop-daemon.sh start datanode

$ sbin/yarn-daemon.sh start resourcemanager

$ sbin/yarn-daemon.sh start nodemanager

3)启动历史

启动历史服务

sbin/mr-jobhistory-daemon.sh start historyserver

4)查看守护进程

28904 ResourceManager

28724 NameNode

28808 DataNode

29152 NodeManager

29304 JobHistoryServer

30561 Jps

查看hdfsweb界面

http://gu.com:50070

28724 NameNode

28808 DataNode

查看yarnweb访问界面

http://gu.com:8088

28904 ResourceManager

28724 NameNode

28808 DataNode

29152 NodeManager

查看历史日志的web访问界面

http://gu.com:19888

28904 ResourceManager

28724 NameNode

28808 DataNode

29152 NodeManager

29304 JobHistoryServer

                                                                        Day02

===========================HDFS================================================

HDFS(Hadoop Distributed File System)

** block:(见图)

** HDFS把文件划分成block存储在不同节点上

--默认128M(以前是64M,今后可能会变为256M

--dfs.blocksize属性(hdfs-site.xml)

--该属性应该由文件大小的数值分布来决定,比如80%的文件大小为200M左右,那么该值设定为256M或者128就比较合适

  另如,大都是G级单位大小的文件,该值就应该尽量设置的大些

** 如果一个文件大小只有1M,它实际占用的空间也是1M,并非128M,并不会浪费空间

client(1M) --> namenode(128M逻辑空间) --> datanode(1M实际占用空间)

** 遵循:一次写入多次读取

** namenode(一台)

--存储和管理整个文件系统的元数据,目录和文件的元数据会被持久化保存

--管理文件块和datanode节点的对应关系,该数据保存在内存中,

记录一个block的信息大约需要0.15K,因此内存的大小,会限制能够存储的文件的总数

--整个文件系统集群的访问入口,无论读写数据,都要首先访问namenode

  namenode上找到了对应的datanode,数据读写就不再需要经过namenode

--监听datanode节点的存活状态

** datanode(多台)

--以块(block)的形式存储数据

--默认每个块有三个副本(包括自身),都是存储在不同的节点

-- namenode发送心跳信息(默认3s),超时则认为该节点不可用(默认超过10m

 一旦发生,namenode会复制该节点上的所有block到其他节点

--namenode发送存储的所有块的信息

--真正响应客户端数据读写请求

Hadoop默认block副本存放策略(分布式系统默认为3,伪分布式只能是1

官方说法:

** 第一个副本放在本机架某一个datanode节点

** 第二个副本放在同一机架另外一个datanode节点

** 第三个副本放在另外一个机架的节点(离架)

参见:http://hadoop.apache.org/docs/r2.5.2/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html

(For the common case, when the replication factor is three, HDFSs placement policy is to put

one replica on one node in the local rack/机架, another on a different node in the local rack, and the last on a different node in a different rack. )

另外一种说法(Hadoop权威指南)

** 第一个副本放在运行客户端程序的节点,如果该节点位于集群外,就随机选择一个节点

** 第二个副本放在和第一个副本不同机架的随机节点(离架)

** 第三个副本放在与第二副本同一机架的随机节点

** 如果需要存放其他副本,则在集群中随机选择其他节点,系统会尽量避免过多副本集中在同一个机架的现象

-- 其实这两种说法类似,都是一个机架放一个,另外一个机架放两个,其他随机存放

-- 客户端读取副本: 就近原则

----------------------------------------

 

NameNode元数据(见图)

** fsimage文件系统镜像

** edits 编辑日志

client操作行为: putrm...  ==>  记录到edits文件(变化的元数据)

-- 存放位置由dfs.namenode.name.dir属性(hdfs-site.xml)决定,

   默认为/opt/modules/hadoop-2.5.0/data(${hadoop.tmp.dir})/dfs/name,可以查看

-- 类似的,数据存放位置由dfs.datanode.data.dir属性决定,默认为file://${hadoop.tmp.dir}/dfs/data

 

-- 回顾:hadoop.tmp.dircore-site.xml(见上一章)

 

NameNode启动过程

** 加载fsimage,并重新执行edits文件,然后加载到内存

** 如果edits文件比较大,合并会非常消耗时间

** 解决方法:通过Secondarynamenode合并

** 等待dataNode发送block report(块报告)namenode

** 等待过程中,整个HDFS进入安全模式(safemode)

 

SecondaryNamenode

** 辅助Namenode,进行fsiamgeedits文件合并

** 避免Namenode下一次重启fsiamgeedits合并时间过长问题

** SecondaryNamenode不是namnode的热备

 

安全模式safemode

** 整个文件系统只能读,不能写

** 为什么要设计一个安全模式?  保证数据的完整和安全性

** 什么条件下我们会进入安全模式

** namenode启动过程中

** 使用命令手动进入(如:维护阶段)

** NameNode重启时,进入安全模式,DataNode需要向NameNode发送块的信息,NameNode只有当整个文件系统中99.9%

  (可以通过dfs.namenode.safemode.threshold-pct属性配置)的块满足最小副本要求,才会自动退出安全模式。

** 假设我们设置的副本数(dfs.replication属性)5,那么在dataNode上,每个块就应该有5个副本存在,假设现在

  只存在3个副本,那么比率就是3/5=0.6,明显小于0.999,因此系统会自动的复制副本到其他dataNode,直到至少

  99.9%的块都有5个副本,才会自动退出安全模式。

** 同样,如果系统中有8个副本,超过我们设定的5个副本,那么系统也会删除多余的3个副本。

 

查看安全模式

$ bin/hdfs dfsadmin -safemode get

进入安全模式

$ bin/hdfs dfsadmin -safemode enter

离开安全模式

$ bin/hdfs dfsadmin -safemode leave

 

-----------------------------------

 

HDFS里面常见的SHELL操作命令

 

$ bin/hdfs dfs

Usage: hadoop fs [generic options]

[-cat [-ignoreCrc] <src> ...]

[-chgrp [-R] GROUP PATH...]

[-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]

[-chown [-R] [OWNER][:[GROUP]] PATH...]

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

[-du [-s] [-h] <path> ...]

[-get [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]

[-ls [-d] [-h] [-R] [<path> ...]]

[-mkdir [-p] <path> ...]

[-mv <src> ... <dst>]

[-put [-f] [-p] <localsrc> ... <dst>]

[-rm [-f] [-r|-R] [-skipTrash] <src> ...]

[-text [-ignoreCrc] <src> ...]

 

例子:

上传文件:(测试HDFS)

#随便创建一个文件a.txt,测试用

$ vi a.txt

# 打开网页,Utilities--Browse file system

$ hdfs dfs -mkdir /input2      #HDFS上创建文件夹,没有类似-cd进入目录的参数

$ hdfs dfs -mkdir -p /aaa/bbb/ccc #级联创建目录

$ hdfs dfs -ls /                  #查看

$ hdfs dfs -put a.txt /input      #把本地文件拷到HDFS

$ hdfs dfs -cat /input2/a.txt     #查看文件

$ hdfs dfs -text /input2/a*      #同上,查看文件内容(可以查看非纯文本格式文件)

$ hdfs dfs -rm /input2/a.txt      #删除文件

$ hdfs dfs -rmr /input?           #递归删除文件夹和里面的文件,推荐使用'-rm -r'格式;单字符通配符'?'

$ hdfs dfs -help

PS:

# hadoop fs  :可以跨文件系统操作,到了2.x版本,分成hdfsyarn两个命令

# hadoop dfs :功能有限,不赞成使用(Deprecated

$ hadoop fs -mkdir /input2      #用法和'hdfs dfs'类似

$ hadoop fs -ls /               

$ hadoop fs -put b.txt /input2

$ hadoop fs -cat /input2/b.txt

$ hadoop fs -rm /input2/b.txt

$ hadoop fs -rmr /input2

$ hadoop fs -help

 

----日志-------------------------------------

1.HDFS深入学习

2.Namenode的启动流程和元数据的合并

3.HDFS的读写流程和存储机制(重点)

4.HDFSJava API

一、HDFS深入

1namenode datanode功能

namenode

接收用户操作请求 维护文件系统的目录结构 管理文件与block之间关系,blockdatanode之间关系 namenode管理:namenode支持对HDFS中的目录、文件和块做类似文件系统的创建、修改、删除、列表文件和目录等基本操作。 块存储管理 在整个HDFS集群中有且只有唯一一个处于active状态namenode节点,该节点负责对这个命名空间(HDFS)进行管理

datanode

存储文件 文件被分成block存储在磁盘上 为保证数据安全,文件会有多个副本 namenodeclient的指令进行存储或者检索block,并且周期性的向namenode节点报告它存了哪些文件的block

2.NameNode的启动流程和元数据合并流程

NameNode的元数据信息先往edits文件中写,当edits文件达到一定的阈值(3600秒或大小到64M)的时候,会开启合并的流程。

合并流程:

1.当开始合并的时候,SecondaryNameNode会把editsfsimage拷贝到自己服务器所在内存中,开始合并,合并生成一个名为fsimage.ckpt的文件。

2.fsimage.ckpt文件拷贝到NameNode上,成功后,再删除原有的fsimage,并将fsimage.ckpt文件重命名为fsimage

3.SecondaryNameNodeeditsfsimage拷贝走之后,NameNode会立刻生成一个edits.new文件,用于记录新来的元数据,当合并完成之后,原有的edits文件才会被删除,并将edits.new文件重命名为edits文件,开启下一轮流程。

====core-site.xml=====

<property>

<name>fs.checkpoint.period</name>

<value>3600</value>

<description>The number of seconds between two periodic checkpoints.</description>

</property>

 

<property>

<name>fs.checkpoint.size</name>

<value>67108864</value>

<description>The size of the current edit log (in bytes) that triggers

a periodic checkpoint even if the fs.checkpoint.period hasn’t expired.</description>

</property>

 

【安全模式 safemode

Namenode的一种状态,启动时会自动进入安全模式,在安全模式,文件系统不允许有任何修改,“只读不写”。目的,是在系统启动时检查各个DataNode上数据的有效性。

//手动进入安全模式

bin/hdfs dfsadmin -safemode enter

 

//手动离开安全模式

$ bin/hdfs  dfsadmin -safemode leave

 

3HDFS的特点

优点:

1)处理超大文件

  这里的超大文件通常是指百MB、数百TB大小的文件。目前在实际应用中,HDFS已经能用来存储管理PB级的数据了。

2)流式的访问数据

***  HDFS的设计建立在更多地响应"一次写入、多次读取"任务的基础上。这意味着一个数据集一旦由数据源生成,就会被复制分发到不同的存储节点中,然后响应各种各样的数据分析任务请求。在多数情况下,分析任务都会涉及数据集中的大部分数据,也就是说,对HDFS来说,请求读取整个数据集要比读取一条记录更加高效。

3)运行于廉价的商用机器集群上

  Hadoop设计对硬件需求比较低,只须运行在低廉的商用硬件集群上,而无需昂贵的高可用性机器上。廉价的商用机也就意味着大型集群中出现节点故障情况的概率非常高。这就要求设计HDFS时要充分考虑数据的可靠性,安全性及高可用性。

缺点:

1)不适合低延迟数据访问

如果要处理一些用户要求时间比较短的低延迟应用请求,则HDFS不适合。HDFS是为了处理大型数据集分析任务的,主要是为达到高的数据吞吐量而设计的,这就可能要求以高延迟作为代价。

2)无法高效存储大量小文件

  因为Namenode把文件系统的元数据放置在内存中,所以文件系统所能容纳的文件数目是由Namenode的内存大小来决定。一般来说,每一个文件、文件夹和Block需要占据150字节左右的空间,所以,如果你有100万个文件,每一个占据一个Block,你就至少需要300MB内存。当前来说,数百万的文件还是可行的,当扩展到数十亿时,对于当前的硬件水平来说就没法实现了。还有一个问题就是,因为Map task的数量是由splits来决定的,所以用MR处理大量的小文件时,就会产生过多的Maptask,线程管理开销将会增加作业时间。举个例子,处理10000M的文件,若每个split1M,那就会有10000Maptasks,会有很大的线程开销;若每个split100M,则只有100Maptasks,每个Maptask将会有更多的事情做,而线程的管理开销也将减小很多。

3)不支持多用户写入及任意修改文件

  在HDFS的一个文件中只有一个写入者,而且写操作只能在文件末尾完成,即只能执行追加操作。目前HDFS还不支持多个用户对同一文件的写操作,以及在文件任意位置进行修改。

二、HDFS的读写流程

hdfs中,将数据存入hdfs的时候,会把数据分成一个一个的block,在hadoop2.x中,一个block默认是128M

rack1rack2rack3

NNDN3DN6

DN1DN4DN7

DN2DN5DN8

 

 File:200M

2block

block1:128M

block2:72M

 

 

 

 

 

 

 

 

流式写入:

1.block1分成一个一个的package,package1发送给DN1

2.DN1接受完package1,自己存一份,再将package1发送给DN2

同时,接收client发送来的package2

3.DN2接收完package1,自己存一份,再将package1发送给DN4

...

 

4.block1接收完毕,DN1DN2DN4NN汇报消息(接收完毕),DN1再向client汇报block1接收完毕,于是,client开始发送block2.

5....

hdfs读取

1.client会想NameNode发送读取请求,NameNode会将元数据查出来,每一个数据存在的位置发给client

2.client会优先从本地去读取数据,如果本地不存在数据,会

从元数据记录的第一个存储位置开始读取

三、搭建Linux环境的Java开发(Eclipse + maven

1.Java 安装  配置环境变量

2.Maven 管理工程,管理依赖包(jar包)

1)上传并解压apache-maven安装包

$ tar -zxf apache-maven-3.0.5-bin.tar.gz -C ../modules/

2)配置环境变量

vi /etc/profile

# MAVEN_HOME

export MAVEN_HOME=/opt/modules/apache-maven-3.0.5

export PATH=$PATH:$MAVEN_HOME/bin

3)使配置文件生效

$ source /etc/profile

4)检查配置是否正确

$ mvn --v

Apache Maven 3.0.5 (r01de14724cdef164cd33c7c8c2fe155faf9602da; 2013-02-19 21:51:28+0800)

3.安装Eclipse

1)上传并解压Eclipse安装包

2)启动Eclipse

//进入eclipse安装目录

$ cd /opt/software/eclipse

//启动

./eclipse

3)

4)进入maven安装目录

cd /opt/modules/apache-maven-3.0.5/conf

vi settings.xml

  <localRepository>/home/user01/.m2/repository</localRepository>

 

 

5)拷贝settings.xml/home/user01/.m2

cp /opt/modules/apache-maven-3.0.5/conf/settings.xml ~/.m2

 

  6)上传repository.tar.gz~/.m2

  tar -zxf repository.tar.gz -C ./

 

***顺序: 一定要先替换repository中的jar文件,然后创建maven工程,接下来修改porm.xml增加<dependency>依赖信息

 

四、WindowsEclispe远程开发Mapreduce程序

1.安装插件

1).hadoop-eclipse-plugin-2.6.0.jar 拷贝到${MyEclispe_HOME} /plugins

2).打开MyEclispe,菜单栏->windows->Preferneces->Hadoop MapReduce

2.Windows安装hadoop

1)解压hadoop-2.5.0.tar.gzD:/根目录

右键WinRar--》属性--》兼容性-》勾选 以管理员运行此程序

打开==》浏览到到hadoop-2.5.0.tar.gz ==>解压到 D:/根目录

2)配置hadoop的环境变量

HADOOP_HOME=hadoop的解压目录】    //新建项

Path=%HADOOP_HOME%\bin//在原有配置的最前面

;%HADOOP_HOME%\bin //在原有配置的最后面

;%HADOOP_HOME%\bin;   //在原有位置的中间插入

 

cmd命令提示符

hadoop -h

 

Error: JAVA_HOME is incorrectly set.

       Please update D:\green\hadoop-2.5.0\conf\hadoop-env.cmd

 

Definde Hadoop  Location

 

3.配置插件参数

MavreduceV2

host:[hostname]

port8032            //resourcemanager 的默认端口号

DFS Master

host:[hostname]

port8020

4.拷贝winutils.exe hadoop.dll${hadoop_HOME}/bin

5.单独拷贝hadoop.dllC:\Windows\System32

6.创建工程的两种方式

1)使用插件,自动导入jar包,使用模板创建mapper reducer

driver

2)创建maven工程

 2-1)解压apache-maven-3.0.5.tar.gz

 2-2) 配置maven环境变量

MAVEN_HOME=[maven的解压目录]

path=%MAVEN_HOME%/bin

 2-3)命令提示符  mvn --v

Apache Maven 3.0.5 (r01de14724cdef164cd33c7c8c2fe155faf9602da; 2013-02-19 21:51:28+0800)

3)修改apache-maven-3.0.5\conf\settings.xml

 <localRepository>C:\Users\Administrator\.m2\repository</localRepository>

 4)解压repository.tar.gzsettings.xml配置文件中指定的repository

 5)配置使用自己解压的maven

 6)将${hadoop_Home}/ect/hadoop/log4j.properties拷贝到项目的src目录

linux中的hadoop安装目录下的etc/hadoop/hdfs-site.xml添加如下配置

,重启HDFS的进程

<property>

<name>dfs.permissions</name>

        <value>false</value>

</property>

五、WindowsEclispe远程开发Mapreduce程序

1.安装插件

1).hadoop-eclipse-plugin-2.6.0.jar 拷贝到${MyEclispe_HOME} /plugins

2).打开MyEclispe,菜单栏->windows->Preferneces->Hadoop MapReduce

2.Windows安装hadoop

1)解压hadoop-2.5.0.tar.gzD:/根目录

右键WinRar--》属性--》兼容性-》勾选 以管理员运行此程序

打开==》浏览到到hadoop-2.5.0.tar.gz ==>解压到 D:/根目录

2)配置hadoop的环境变量

HADOOP_HOME=hadoop的解压目录】    //新建项

Path=%HADOOP_HOME%\bin//在原有配置的最前面

;%HADOOP_HOME%\bin //在原有配置的最后面

;%HADOOP_HOME%\bin;   //在原有位置的中间插入

 

cmd命令提示符

hadoop -h

 

Error: JAVA_HOME is incorrectly set.

       Please update D:\green\hadoop-2.5.0\conf\hadoop-env.cmd

 

Definde Hadoop  Location

 

 

3.配置插件参数

MavreduceV2

host:[hostname]

port8032            //resourcemanager 的默认端口号

 

DFS Master

host:[hostname]

port8020

 

4.拷贝winutils.exe hadoop.dll${hadoop_HOME}/bin

5.单独拷贝hadoop.dllC:\Windows\System32

 

6.创建工程的两种方式

1)使用插件,自动导入jar包,使用模板创建mapper reducer

driver

2)创建maven工程

2-1)解压apache-maven-3.0.5.tar.gz

2-2) 配置maven环境变量

MAVEN_HOME=[maven的解压目录]

path=%MAVEN_HOME%/bin

2-3)命令提示符  mvn --v

Apache Maven 3.0.5 (r01de14724cdef164cd33c7c8c2fe155faf9602da; 2013-02-19 21:51:28+0800)

3)修改apache-maven-3.0.5\conf\settings.xml

 <localRepository>C:\Users\Administrator\.m2\repository</localRepository>

 4)解压repository.tar.gzsettings.xml配置文件中指定的repository

 5)配置使用自己解压的maven

 6)将${hadoop_Home}/ect/hadoop/log4j.properties拷贝到项目的src目录

 

linux中的hadoop安装目录下的etc/hadoop/hdfs-site.xml添加如下配置

,重启HDFS的进程

<property>

<name>dfs.permissions</name>

        <value>false</value>

</property>

 Day03

 

MapReduce(重点)

 

一、Yarn的基本流程(执行流程)

 

 

 

 

1.clientyarn提交job,首先找ResourceManager分配资源(CPU 内存)

2.ResourceManager开启一个Container,Container中运行一个Application manager

3.Application manager找一台nodemanager启动Application master,计算任务所需的计算

4.Application masterApplication managerYarn)申请运行任务所需的资源

5.Resource scheduler将资源封装发给Application master

6.Application master将获取到的资源分配给各个nodemanager

7.各个nodemanager得到任务和资源开始执行map task

8.map task执行结束后,开始执行reduce task

9.map taskreduce task将执行结果反馈给Application master

10.Application master将任务执行的结果反馈Application manager

 

mapreduce

** 分布式离线计算模型

** 周期性(每天、每周、每月)分析历史数据

** Mapreduce分为两个阶段

** map阶段:  找出关键数据,会产生多个mapper

   默认情况,一个split对应一个mapper,一个block对应一个mapper

** reduce阶段 map阶段运行的结果进行合并

 

例如:一个100G文件:

    被分隔成多个block,分散存放在不同的datanode(通常一个节点即是datanode又是nodemanager)

这些nodemanager会为每个split启动一个mapper

 

** Input --> map --> reduce --> output

** 整个过程数据流都是键值对

 

====wordcount=========================================================

 

以此例分析Mapreduce:

 

需求:单词统计,分隔符是\t

hadoopmapreduce

sparkstorm

maphadoopmapreduce

reducestormhadoop

hbasemapstorm

 

 

** map 输入

** 按行读取数据,然后转换成key-value

<0,hadoopmapreduce>

<15,sparkstorm>

<26,maphadoopmapreduce>

<40,reducestormhadoop>

<50,hbasemapstorm>

** map 输出

<hadoop,1> <mapreduce,1> <spark,1> <storm,1> <map,1> <hadoop,1>  ...

** 中间结果临时存储在本地目录,而非HDFS

 

** reduce

** 从相关nodemanager拉取map输出的结果

** 运行reduce函数

** 输入

<hadoop,(1,1,1)> <storm,(1,1,1)> <hbase,1> ...

** 输出

hadoop3

storm3

hbase1  ...

 

** 结果写入HDFS

hadoop3

storm3

hbase1  ...

 

二、MapRedcue

分布式并行计算框架    分而治之的思想

编程模型

 

bin/hadoop  jar  *****.jar  /input/wc.txt   /out/

 

1.一个简单的MapRedcue包含两个过程,一个Map阶段(map 映射),一个Reduce(化简)阶段

2.第一个阶段Map Task,并发的各司其职的读取,完全并行

3.第二个阶段Redcue Task,处理的数据要依赖于map阶段  reduce个数少于map个数

4.整个过程是以key value形式进行数据传递

input/input/wc.txt)   -》  Map Task -Reduce task -out(/out)

 

=====input=======================

输入源文件/input/wc.txt

hadoop java

namenode java

 xml html

 spark

 

=====map Task(一行一行的读取)

hadoop java     ->   <0,  hadoop java>

namenode java    ->  <10, namenode java>

 

用户逻辑

str[]=line.split(" ")

<str[0],1> -> <hadoop,1>

<str[1],1> -> <java,1 >

......

 

Context 上下文

 

=====shuffle(洗牌)==========================

分区:决定map阶段的<key value>交给哪个reduce处理

分组: <key,list[1,1,1,1...]>

 

=======Redcue Task =====================

<hadoop,n>

 

Context 上下文

=====out(/out)

hadoop 1

java 2

....

 

package mapReduce;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.conf.Configured;

import org.apache.hadoop.fs.FileSystem;

import org.apache.hadoop.fs.Path;

import org.apache.hadoop.io.IntWritable;

import org.apache.hadoop.io.LongWritable;

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.Tool;

import org.apache.hadoop.util.ToolRunner;

 

/**

 * hadoop专门封装的数据类型,是HDFS的序列化接口 long -> LongWritable String -> Text

 *

 * @author Administrator

 *

 */

public class WordCountMR extends Configured implements Tool {

/**

 * LongWritable,Text -> 文件每一行内容偏移量 每一行的内容

 * Text,IntWritable -> 每一行每个单词 1

 * @author Administrator

 */

public static class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable>{

/**

 * Context 上下文  将map输出的key value 发给reduce的输入

 *   /input/wordcount.txt

 *   一行一行读进来 Mapper按一行一行的处理

 *   key  LongWritable的每一行的偏移量

 *   vaue Text类型每一行的内容   hadoop  java

 */

private  Text mapOuoputKey = new Text();

private  IntWritable mapOutputValue = new IntWritable(1);

 @Override

protected void map(LongWritable key, Text value,Context context)

throws IOException, InterruptedException {

//Text类型的内容转化成String类型

String line = value.toString();

//String类型的每一行内容按照空格切分为String

String[] strs = line.split(",");

/**

 * 遍历数组将每个Text类型的元素作为map输出的key

 * IntWritable类型的1作为map输出的value

 */

for(String str : strs){

mapOuoputKey.set(str);

context.write(mapOuoputKey, mapOutputValue);  

}

}

}

public static class wordCountReducer extends

Reducer<Text,IntWritable, Text, IntWritable> {

@Override

protected void reduce(Text key, Iterable<IntWritable> values,Context context)

throws IOException, InterruptedException {

//定义临时变量 用来接收相同单词出现个数的总和

int sum = 0;

for(IntWritable value : values){

System.out.print(value.toString()+"\t");

sum += value.get();

}

/**

 * context 将统计结果输出到结果文件中

 */

context.write(key, new IntWritable(sum));

}

}

public int run(String[] args) throws Exception {

//1.获取hadoop配置信息

Configuration conf = new Configuration();

 

//2.生成job

Job job = Job.getInstance(

conf,

this.getClass().getName()

);

//打成jar包并指定jar包所在路径

job.setJarByClass(getClass());

//3.设置job的内容

// inputDir  ->  map  -> reduce -> outPutdir

//3.1 指定输入路径

Path  inPath = new Path(args[0]);

FileInputFormat.setInputPaths(job, inPath);

 

//3.2 map阶段

job.setMapperClass(WordCountMapper.class);

job.setMapOutputKeyClass(Text.class);

job.setMapOutputValueClass(IntWritable.class);

 

//3.3 reduce阶段

job.setReducerClass(wordCountReducer.class);

job.setOutputKeyClass(Text.class);

job.setOutputValueClass(IntWritable.class);

 

//3.4 指定输出路径

Path outPath = new Path(args[1]);

FileSystem fs = outPath.getFileSystem(conf);

if(fs.exists(outPath)){

fs.delete(outPath, true);

}

FileOutputFormat.setOutputPath(job, outPath);

 

//4.提交job运行并得到结果

 

boolean isSuccess =  job.waitForCompletion(true);

return isSuccess ? 0 : 1;

}

public static void main(String[] args) throws Exception {

Configuration conf = new Configuration();

args = new String[]{

"hdfs://apache.bigdata.com:8020/input/wc.txt",

"hdfs://apache.bigdata.com:8020/output"

};

int status = ToolRunner.run(conf  , new  WordCountMR() , args);

System.exit(status);

 

}

}

 

 

1(可选)

创建"Source Folder"src/main/resources目录,用来存放core-site.xml

拷贝log4j.properties

$ cp /opt/modules/hadoop-2.5.0/etc/hadoop/log4j.properties /home/tom/workspace/myhdfs/src/main/resources

 

2、编写代码

Hadoop常用类型:

IntWritableLongWritable  Text  NullWritable

 

package com.myblue.myhdfs;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.fs.FileSystem;

import org.apache.hadoop.fs.Path;

import org.apache.hadoop.io.LongWritable;

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;

 

public class WordCountMapReduce{

//mapper

public static class WordCountMapper extends

Mapper<LongWritable, Text, Text, LongWritable> {

protected void map(LongWritable key, Text value, Context context)

throws IOException, InterruptedException {

//输入行

System.out.println(key.get());

String lineValue = value.toString();

String[] splits = lineValue.split("\t");

 

Text mapOutputKey = new Text(); //输出键

LongWritable mapOutputValue = new LongWritable(1); //输出值,本例恒为1

 

for (String s : splits) {

mapOutputKey.set(s);

context.write(mapOutputKey, mapOutputValue);

}

}

}

 

//reducer

public static class WordCountReducer extends

Reducer<Text, LongWritable, Text, LongWritable> {

 

protected void reduce(Text key, Iterable<LongWritable> values,

Context context) throws IOException, InterruptedException {

 

long sum = 0;

for (LongWritable value : values) {

sum += value.get();

}

 

LongWritable outputValue = new LongWritable();

outputValue.set(sum);

context.write(key, outputValue);

}

}

 

public static void main(String[] args) throws Exception {

 

 args = new String[]{"hdfs://chao.com:8020/input/wc.txt",

"hdfs://chao.com:8020/output"

};

Configuration conf = new Configuration();

 

//创建作业

Job job = Job.getInstance(conf);

job.setJarByClass(WordCountMapReduce.class);

 

//输入路径

FileInputFormat.addInputPath(job, new Path(args[0]));

//输出路径

Path outPath = new Path(args[1]);

FileSystem dfs = FileSystem.get(conf);

if (dfs.exists(outPath)) {

dfs.delete(outPath, true);

}

FileOutputFormat.setOutputPath(job, outPath);

 

//mapper

job.setMapperClass(WordCountMapper.class);

job.setMapOutputKeyClass(Text.class);

job.setMapOutputValueClass(LongWritable.class);

 

//reducer

job.setReducerClass(WordCountReducer.class);

job.setOutputKeyClass(Text.class);

job.setOutputValueClass(LongWritable.class);

 

//提交作业

System.exit(job.waitForCompletion(true) ? 0 : 1);

}

}

 

3、运行

eclipse里直接运行(需要core-site.xml

 

PS:打包运行

a) 启动Hadoop (若是报进程已启动的错误,可以到tmp目录下删除对应的pid文件  --ls /tmp/*.pid)

b) WordCountMapReduce.java文件导出为jar(需要填写文件名,如:XXX.jar)

c) /opt/modules/hadoop-2.5.0/bin/yarn jar WordCountMapReduce.jar com.myblue.myhdfs.WordCountMapReduce /input /output

 

 

 

 

 

 

 

====计算每个省份的PV=======================================================

 

数据来源:

** web服务器的日志文件(20150828)

 

案例:

** web服务器的日志文件(20150828)

** web服务器生产日志文件

** 数据字典

** 36个字段

 

需求:

** 计算每个省份的PV

** provinceId

 

常见的统计指标:

** PV  page view

用户每访问一个页面就记录一条日志,如果是多次访问同一个页面会累计

** UV  unique visitor

独立访客(cookie

** 独立IP

 

思路:依据provinceId字段去统计

** provinceId作为key,  value1

 

package com.myblue.myhdfs;

import java.io.IOException;

import org.apache.commons.lang.StringUtils;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.fs.FileSystem;

import org.apache.hadoop.fs.Path;

import org.apache.hadoop.io.IntWritable;

import org.apache.hadoop.io.LongWritable;

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.conf.Configured;

import org.apache.hadoop.util.Tool;

import org.apache.hadoop.util.ToolRunner;

 

public class WebPvMapReduce extends Configured implements Tool {

 

public static class ModuleMapper extends

Mapper<LongWritable, Text, IntWritable, IntWritable> {

 

protected void map(LongWritable key, Text value, Context context)

throws IOException, InterruptedException {

 

String lineValue = value.toString();

String[] splits = lineValue.split("\t");

 

//过滤非法数据,若该行数据少于30字段,则视为非法数据,不再处理

if (splits.length < 30) {

//参数:计数器组,计数器名

context.getCounter("Web Pv Counter", "Length limit 30").increment(1L);

return;

}

 

String url = splits[1];// 2个字段为url

if (StringUtils.isBlank(url)) {

context.getCounter("Web Pv Counter", "Url is Blank").increment(1L);

return;

}

 

String provinceIdValue = splits[23];// 24个字段为provinceId

if (StringUtils.isBlank(provinceIdValue)) {

context.getCounter("Web Pv Counter", "Province is Blank").increment(1L);

return;

}

 

int provinceId = 0;

try {

provinceId = Integer.parseInt(provinceIdValue);

} catch (Exception e) {

System.out.println(e);

return;

}

 

IntWritable mapOutputKey = new IntWritable();

mapOutputKey.set(provinceId);

IntWritable mapOutputValue = new IntWritable(1);//本例输出恒为1

context.write(mapOutputKey, mapOutputValue);

}

}

 

public static class ModuleReducer extends

Reducer<IntWritable, IntWritable, IntWritable, IntWritable> {

 

protected void reduce(IntWritable key, Iterable<IntWritable> values,

Context context) throws IOException, InterruptedException {

 

int sum = 0;

for (IntWritable value : values) {

sum += value.get();

}

 

IntWritable outputValue = new IntWritable();

outputValue.set(sum);

context.write(key, outputValue);

}

}

 

public int run(String[] args) throws Exception {

 

// 创建作业

Configuration conf = new Configuration();

Job job = Job.getInstance(conf);

job.setJarByClass(getClass());

 

// 输入、输出路径

FileInputFormat.addInputPath(job, new Path(args[0]));

Path outPath = new Path(args[1]);

FileSystem dfs = FileSystem.get(conf);

if (dfs.exists(outPath)) {

dfs.delete(outPath, true);

}

FileOutputFormat.setOutputPath(job, outPath);

 

// mapper

job.setMapperClass(ModuleMapper.class);

job.setMapOutputKeyClass(IntWritable.class);

job.setMapOutputValueClass(IntWritable.class);

 

// reducer

job.setReducerClass(ModuleReducer.class);

job.setOutputKeyClass(IntWritable.class);

job.setOutputValueClass(IntWritable.class);

 

// 提交作业

return job.waitForCompletion(true) ? 0 : 1;

}

 

public static void main(String[] args) throws Exception {

 

args=new String[]{"/input2","/output2"};

// 使用ToolRunner运行作业

Configuration conf = new Configuration();

int status = ToolRunner.run(conf, new WebPvMapReduce(), args);

System.exit(status);

}

}

 

 

 

测试:

$ hdfs dfs -mkdir /input2

$ hdfs dfs -put 2015082818 /input2

$ /opt/modules/hadoop-2.5.0/bin/yarn jar WebPvMapReduce.jar com.myblue.myhdfs.WebPvMapReduce /input2 /output2

 

 

 

====YARN================================================

 

YARN架构

** 集群资源管理、作业和任务管理

** hadoop2.0以前

** jobtracker

** tasktracker

** hadoop2.0以后

** resourcemanager

** nodemanager

** resourcemanager

--接收客户端请求  bin/yarn jar xxx.jar wordcount /input /output

--启动/监控ApplicationMaster

--监控NodeManager

--资源分配与调度

** nodemanager

--单个节点上的资源管理

--处理来自ResourceManager的命令

--处理来自ApplicationMaster的命令

** applicationmaster

--当前这个任务的管理者,任务运行结束,applicationmaster会消失

--数据切分

--为应用程序申请资源,并分配给任务使用

--任务监控与容错

** Container

--对任务运行环境的抽象,封装了CPU、内存等多维资源以及环境变量、启动命令等任务运行相关的信息

 

再次认识Hadoop

** HDFS

--分布式文件系统的架构、存储数据

--namenode

--datanode

** yarn

--集群资源管理、作业和任务管理

--resourcemanager

--nodemanager

 

通常集群资源配置:

** 内存

yarn.nodemanager.resource.memory-mb8G   64G  128G

 

**  CPU

yarn.nodemanager.resource.cpu-vcores8核  16

 

**  内存不够,会直接影响job任务运行成败

**  CPU不够,只会影响job任务运行的快慢

 

 

Day04

一、前一天的问题:

1.编写mapreduce程序

Driver

1.// 设置运行jobjar类  打jar包,提交到yarn时必须加这一行

//否则会报:ClassNoFound

job.setJarByClass(this.getClass());

 

2.获取文件系统对象

//推荐写法

Path outPath = new Path(args[1]);

FileSystem fs = outPath.getFileSystem(conf);

 

FileSystem fs = New  FileSystem()  //这样获取的对象是本地文件系统

Wrong FShdfs://              expected file:///

 

3.nativeio method  jdk安装了最新版本 更换jre libariy

 

4.mapred.LocalJobRunner: 1 / 1 copied.  本地运行,不需要启动任何的守护进程

 

二、mapreducemapreduce个数) map任务split切片 reduce个数 partition

 

map个数:由任务切片spilt决定的,默认情况下一个split的大小就是block

 由参与任务的文件个数决定的

 number of splits:1

 

 对于大文件,一般选择split=block,如果split<block 则会增加map执行的并发度,但是会造成在节点之间拉取数据

 

 对于小文件,默认一个文件启动一个map,这样会启动多个map,增大节点资源消耗,此时可以使用使用InputFormat将多个小文件加入到一个split,并适当增大split的大小,这样会减少map启动的个数,减少并发度,减少资源消耗

 

reduce个数:由分区个数决定 可以由用户在程序中Driver自定义job.setNumReduceTasks(3);一个ruduce对应一个结果文件part_0000

 

partiton(分区):用来指定map输出的key交给哪个reuducer处理 默认是通过对map输出的keyhashcode 对指定的reduce个数求模(取余)

key.hashcode() % N=job.setNumReduceTasks(n)

 

Group 分组:map输出的相同key放到一个分组

 

Sort 排序: 根据key进行排序

 

三、完全分布式的安装

1、集群规划

角色分配

 

组件PC1   PC2    PC3

HDFS    Namenode     SecondaryNamenode

  Datanode      DatanodeDatanode

Yarn   RecourceManager

  Nodemanager   Nodemanager        Nodemanager

Histrory  HistroryServer                                

 

2、基本环境准备

2.1系统和软件【3台】

CentOS 6.5    hadoop 2.5.0     jdk1.70—67

2.2 配置IPDNSroot

配置静态IP

DNS

//检查主机映射

$ cat /etc/hosts

 

//检查主机名

$cat /etc/sysconfig/network

 

//检查IPDNS

$ cat /etc/sysconfig/network-scripts/ifcfg-eth0

 

2.3关闭防火墙 (3) root

# service iptables stop

# chkconfig iptables off

 

检查:

$ sudo service iptables status

iptables: Firewall is not running.

 

$ sudo chkconfig --list | grep iptables

0:off1:off2:off3:off4:off5:off6:off

 

关闭Linux安全子系统

# vi /etc/sysconfig/selinux

 

2.4创建相同普通用户名和密码 【3台】

# useradd hadoop

# echo 123456 | passwd --stdin hadoop

2.5配置主机映射   【三台都需要需要添加】

# vi /etc/hosts

192.168.7.9 yu.com

192.168.7.10 gcf.com

192.168.7.11 feng.com

 

2.6卸载自带的jdk

# rpm -qa | grep jdk

# rpm -e --nodeps tzdata-java-2012j-1.el6.noarch

# rpm -e --nodeps java-1.6.0-openjdk-1.6.0.0-1.50.1.11.5.el6_3.x86_64

# rpm -e --nodeps java-1.7.0-openjdk-1.7.0.9-2.3.4.1.el6_3.x86_64

 

配置Java环境变量

# vi /etc/profile

 

#JAVA_HOME

export JAVA_HOME=/opt/modules/jdk1.7.0_67

export PATH=$PATH:$JAVA_HOME/bin

 

生效配置

source /etc/profile

 

检查Java环境变量

java -version

java version "1.7.0_67"

Java(TM) SE Runtime Environment (build 1.7.0_67-b01)

 

二、配置NTP服务

 

*.PC1作为整个集群的时间同步服务器

*.集群中所有其他服务器都来这台服务器PC1同步时间

 

1.检查每台服务器所在的时区

 $ date -R

Thu, 23 Mar 2017 11:13:57 +0800

 

如果不是+0800,如要通过如下命令调整

# rm  -rf /etc/localtime        ---如果时区不是+0800

# ln -s /usr/share/zoneinfo/Asia/Shanghai   /etc/localtime

 

2.安装ntp服务

# rpm -qa | grep ntp      --查看ntp软件包是否已安装

ntp-4.2.6p5-1.el6.centos.x86_64

ntpdate-4.2.6p5-1.el6.centos.x86_64

 

# yum  -y install ntp     --如果没有那就需要安装ntp

 

3.修改ntp的配置文件(PC1

# vi /etc/ntp.conf

去掉第18行的# 修改成自己的网段

restrict 192.168.7.0 mask 255.255.255.0 nomodify notrap

注释掉以下几行(22行)

 #server 0.centos.pool.ntp.org iburst

     #server 1.centos.pool.ntp.org iburst

     #server 2.centos.pool.ntp.org iburst

     #server 3.centos.pool.ntp.org iburst

 

     CentsOS6.4 去掉注释第35 36

     CentsOS6.5 去手动添加以下内容

     server 127.127.1.0     #local clock

     fudge 127.127.1.0  stratum 10

 

     4、同步服务器的时间(PC1

     # ntpdate cn.pool.ntp.org    -->操作这一步时关闭ntp服务

23 Mar 11:36:56 ntpdate[26856]: step time server 173.255.246.13 offset -12.240613 sec

     5、启动ntp服务(默认式开始)PC1 root用户操作

     # service ntpd start

     # chkconfig ntopd on

     $ sudo chkconfig --list | grep ntpd

 

     $ sudo ntpdate 202.120.2.101

 9 Jun 15:27:49 ntpdate[2689]: the NTP socket is in use, exiting  //ntpd一旦开启就不能手动同步时间

 

6、如果另外两台的ntp的进程开启,那么需要关闭

# service ntpd stop

# chkconfig ntpd off

 

 

7.23台向第一台同步时间

# ntpdate yu.com

16 Feb 17:43:27 ntpdate[2554]: adjust time server 192.168.7.9 offset -0.001412 sec

 

8.制定周期性时间同步计划任务(PC2PC3定时向PC1手动同步时间)

PC2 PC310分钟同步一次时间

# crontab -e

*/10 * * * * /usr/sbin/ntpdate yu.com

 

[注意]:如果确实无法向第一台同步时间,请在交互窗口(可以同时设置3台时间)执行手动设置时间

# date -s "11:48:00 2017/3/23"

 

三、配置SSH免密钥登录

使用ssh登录的时候不需要用户名密码

$ sbin/start-dfs.sh

 

$ ssh-keygen   

*  回车,生产当前主机的公钥和私钥

 

//分发密钥(要向3台都发送)

$ ssh-copy-id yu.com

$ ssh-copy-id gcf.com

$ ssh-copy-id feng.com

 

PC1~PC3

$ ssh-keygen

$ ssh-copy-id yu.com 

$ ssh-copy-id gcf.com 

$ ssh-copy-id feng.com

 

分发完成之后会在用户主目录下.ssh目录生成以下文件

$ ls .ssh/

authorized_keys  id_rsa  id_rsa.pub  known_hosts

 

测试失败,需要先删除.ssh目录,重做一遍

 

四、安装Hadoop

1.下载上传到Linux并解压hadoop.tar.gz

$ tar -zxf hadoop-2.5.0.tar.gz -C /opt/modules/

 

2.删除${HADOOP_HOME}/share/doc

$ rm -rf doc/

 

3.配置java环境支持在${HADOOP_HOME}/etc/hadoop

hadoop-env.sh   mapred-env.sh   yarn-env.sh中配置

 

export JAVA_HOME=/opt/modules/jdk1.7.0_67

 

4.配置slaves(集群中所有的主机)

yu.com

gcf.com

feng.com

 

5.=======core-site.xml===

<!--指定第一台作为NameNode-->

<property>

<name>fs.defaultFS</name>

<value>hdfs://yu.com:8020</value>

</property>

 

<property>

<name>hadoop.tmp.dir</name>

<value>/opt/modules/hadoop-2.5.0/data</value>

</property>

 

=============hdfs-site.xml==========

<!-- 分布式副本数设置为3 -->

<property>

        <name>dfs.replication</name>

        <value>3</value>

    </property>

 

<!-- secondarynamenode主机名:端口号 -->

<property>

        <name>dfs.namenode.secondary.http-address</name>

        <value>gcf.com:50090</value>

    </property>

 

<!-- namenodeweb访问主机名:端口号 -->

    <property>

        <name>dfs.namenode.http-address</name>

        <value>yu.com:50070</value>

</property>

 

<!-- 关闭权限检查用户或用户组 -->

<property>

        <name>dfs.permissions.enabled</name>

        <value>false</value>

    </property>

 

=================mapred-site.xml=======

<property>

        <name>mapreduce.framework.name</name>

        <value>yarn</value>

    </property>

 

<property>

        <name>mapreduce.jobhistory.address</name>

        <value>yu.com:10020</value>

    </property>

 

<property>

        <name>mapreduce.jobhistory.webapp.address</name>

        <value>yu.com:19888</value>

    </property>

 

================yarn-site.xml======

<property>

        <name>yarn.resourcemanager.hostname</name>

        <value>feng.com</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-aggregation.retain-seconds</name>

        <value>86400</value>

    </property>

    ===============================

 

    5.配置slaves

yu.com

gcf.com

feng.com

 

【注意事项】:

1.slaves中配置集群中所有的主机名

2.所有节点上的配置文件内容都是一样的(联盟模式例外)

3.要按照集群规划配置所属进程

 

五、(PC1)分发hadoop(已经配置好的)目录到其他两台(PC2PC3)服务器上

scp -r PC1hadoop目录(带路径) PC2:/要复制到的目录

 

$ scp -r /opt/modules/hadoop-2.5.0/ gcf.com:/opt/modules/

$ scp -r /home/gu/ruan/hadoop-2.5.0/etc  feng.com:/home/gu/ruan/hadoop-2.5.0/etc

 六、格式化Namenode

 PC1上的${HADOOP_HOME}/bin

 $ bin/hdfs namendoe -format

【注意】

1.先将PC1hadoop配置目录分发到PC2PC3

2.保证3台上的配置内容一模一样

3.先确保将3台之前残留的data logs删除掉

4.最后格式化

 七、启动进程

 PC1上使用如下命令启动HDFS

 $ sbin/start-dfs.sh

 PC3上使用如下命令启动YARN

 $ sbin/start-yarn.sh

 停止进程

 PC1上使用如下命令停止HDFS

 $ sbin/stop-dfs.sh

 PC3上使用如下命令停止YARN

 $ sbin/stop-yarn.sh

【注意】

修改任何配置文件,请先停止所有进程,然后重新启动

八、检查启动是否正常

3台上jps查看进程,参考之前的集群规划

 

PC1:

28626 DataNode

28883 NodeManager

28989 Jps

28531 NameNode

 

 

PC2:

7528 DataNode

7826 Jps

7717 NodeManager

7583 SecondaryNameNode

 

PC3

7622 NodeManager

7922 Jps

7527 ResourceManager

7405 DataNode

Day05

搭建完全分布式注意的地方

1.3台服务器的时间应该一致,至少不应该相差太大

2.SSH免密钥必须要在3台上进行生成密钥和分发密钥,(必须要给自己也要发一份,也就是每台要分发3次)

3.必须使用相同的用户名和密码

4.选其中一台进行配置(*-env.sh ,*-site.xml,slaves,然后使用scp命令 分发到另外两台

**5.集群(这里是3台)中的配置文件必须一模一样

6.配置完成最好重启3台服务器,在规划为namenode所在节点进行bin/hdfs namenode -format格式化

7.启动进程自动关闭(root和普通用户交叉启动进程造成的)

1).ll logs 是否存在root用户所属的日志文件(.log .out

2).检查 ll /tmp/*.pid 有没有root用户所属的.pid

3).切换root用户删除rm -f /tmp/*.pid 删除${HADOOP_HOME}/data ${HADOOP_HOME}/logs/*

4).切换成普通用户,重新格式化namenode

 

一、Yarn的运行原理(执行流程)

1.clientyarn提交job,首先找ResourceManager分配资源,

2.ResourceManager开启一个Container,Container中运行一个Application manager

3.Application manager找一台nodemanager启动Application master,计算任务所需的计算

4.Application masterApplication managerYarn)申请运行任务所需的资源

5.Resource scheduler将资源封装发给Application master

6.Application master将获取到的资源分配给各个nodemanager

7.各个nodemanager得到任务和资源开始执行map task

8.map task执行结束后,开始执行reduce task

9.map taskreduce task将执行结果反馈给Application master

10.Application master将任务执行的结果反馈pplication manager

 

二、shuffle过程

map()的输出到reduce()的输入,中间的过程被称为shuffle过程。

map side

1.在写入磁盘之前,会先写入环形缓冲区(circular memory buffer),默认100M(mapreduce.task.io.sort.mb可修改),当缓冲区内容达到80M(mapre

duce.map.sort.spill.percent可修改),缓冲区内容会被溢写到磁盘,形成一个spill file文件

2.分区:在写入磁盘之前,会先进分区(partition),partition的数量是由reducer的数量决定的

 job.setNumReduceTasks(2);

 默认是用map输出的<key,value>keyhashcodeNumReduceTasks的个数取余,相同的分到一个区

 

3.排序:在每一个partition中,都会有一个sort by key

 

4.combiner:如果有combiner function,sort之后会执行combiner,相当于map阶段的rudece 【满足数学运算的交换律和结合律】

 

5.merge:数个spill files会合并(merge成一个分过区的排过序的文件

 

6.compress压缩the map output

 

mapreduce.task.io.sort.factor一次性合并小文件的数量 默认10

mapreduce.map.output.compress 启用压缩,默认是false

org.apache.hadoop.io.compress.DefaultCodec默认使用的压缩算法

 

reduce side

1.解压缩:如果在map side 已经压缩过,在合并排序之前要先进行解压缩

2.sort phase(merge)

3.group phase:将相同keyvalue分到一组,形成一个集合

 

三、【案例分析一:网站PV UV分析】

学习内容:

1.离线hadoop大数据分析的一个ETL数据过滤清洗阶段

2.了解应用hadoop分析网站统计指标

3.网站统计分析的基本指标

 

电商(淘宝、京东、一号店等)生产环境下,周期性性,多维度分析:

1.124小时(0~24)网站的PV UV  独立IP等等

2.多维度,基于时间、地域,平台等等

 

1.网站基本统计指标

PV(Page View)

即页面浏览量或点击量,是衡量一个网站或网页用户访问量。具体的说,PV值就是所有访问者在24小时(0点到24点)内看了某个网站多少个页面或某个网页多少次。PV是指页面刷新的次数,每一次页面刷新,就算做一次PV流量。

度量方法就是从浏览器发出一个对网络服务器的请求(Request),网络服务器接到这个请求后,会将该请求对应的一个网页(Page)发送给浏览器,从而产生了一个PV。那么在这里只要是这个请求发送给了浏览器,无论这个页面是否完全打开(下载完成),那么都是应当计为1PV

 

UV(Unique Visitor)

即独立访客数,指访问某个站点或点击某个网页的不同cookie的人数,在同一天内再次访问该网站则不计数。UV提供了一定时间内不同观众数量的统计指标,而没有反应出网站的全面活动。通过cookie是判断UV值的一种方式(另外也可以通过IP地址来判断UV值):

Cookie分析UV值:

当客户端第一次访问某个网站服务器的时候,网站服务器会给这个客户端的电脑发出一个Cookie,通常放在这个客户端电脑的C盘当中。在这个Cookie中会分配一个独一无二的编号,这其中会记录一些访问服务器的信息,如访问时间,访问了哪些页面等等。当你下次再访问这个服务器的时候,服务器就可以直接从你的电脑中找到上一次放进去的Cookie文件,并且对其进行一些更新,但那个独一无二的编号是不会变的。

 

VV(Visit View)

即产生的会话数量

 

独立IP

IP可以理解为独立IP的访问用户,指1天内使用不同IP地址的用户访问网站的数量,同一IP无论访问了几个页面,独立IP数均为1。但是假如说两台机器访问而使用的是同一个IP,那么只能算是一个IP的访问。

 

IP -》  国家  省  市

 

2.需求:根据省份统计日志中网站PV

1.字段长度大于30才为有效记录

2.url不为空为有效记录

3.provinceId不为空为有效记录

4.统计

 

map---split(1split就是1map方法)

split---block(默认1:1的对应关系)

reduce的数量默认是1

 

 

案例1:手机上网流量统计

 

数据源:

HTTP_20130313143750

每个电话号码每上一次网络,就会生成一条日志数据

 

需求目标:

 手机号码上行数据包总数 下行数据包总数 上行总流量 下行总流量

1312341243112381782334242342

136223112381722334214234211231

1312341243112380182834  23

......

 

MapReduce设计:

** key是什么?

--电话号码

** value是什么?

--后面四个字段

 

keyvalue list

13123412431(123,2423,3453,234),(789,1231,4353,234),(1231,231,342,23) ...

13622311238(1233,23,342353,23234),(78239,123231,42353,2234) ...

............

 

最终结果:

13123412431(1232313,241231323,23133453,1231234)

13622311238(6666,62,889,99999999)

............

 

----DataTotalWritable------

 

package com.myblue.myhdfs;

 

import java.io.DataInput;

import java.io.DataOutput;

import java.io.IOException;

import org.apache.hadoop.io.Writable;

 

public class DataTotalWritable implements Writable {

 

// 上行数据包总数

private long upPackNum ;

// 下行数据包总数

private long downPackNum ;

// 上行总流量

private long upPayLoad ;

// 下行总流量

private long downPayLoad ;

 

public DataTotalWritable() {

}

 

public DataTotalWritable(long upPackNum, long downPackNum, long upPayLoad,long downPayLoad) {

this.set(upPackNum, downPackNum, upPayLoad, downPayLoad);

}

 

public void set (long upPackNum, long downPackNum, long upPayLoad,long downPayLoad) {

this.upPackNum = upPackNum;

this.downPackNum = downPackNum;

this.upPayLoad = upPayLoad;

this.downPayLoad = downPayLoad;

}

 

public long getUpPackNum() {

return upPackNum;

}

 

public void setUpPackNum(long upPackNum) {

this.upPackNum = upPackNum;

}

 

public long getDownPackNum() {

return downPackNum;

}

 

public void setDownPackNum(long downPackNum) {

this.downPackNum = downPackNum;

}

 

public long getUpPayLoad() {

return upPayLoad;

}

 

public void setUpPayLoad(long upPayLoad) {

this.upPayLoad = upPayLoad;

}

 

public long getDownPayLoad() {

return downPayLoad;

}

 

public void setDownPayLoad(long downPayLoad) {

this.downPayLoad = downPayLoad;

}

 

//^为异或运算, << 带符号左移, >>带符号右移, >>> 无符号右移

@Override

public int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result + (int) (downPackNum ^ (downPackNum >>> 32));

result = prime * result + (int) (downPayLoad ^ (downPayLoad >>> 32));

result = prime * result + (int) (upPackNum ^ (upPackNum >>> 32));

result = prime * result + (int) (upPayLoad ^ (upPayLoad >>> 32));

return result;

}

 

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

DataTotalWritable other = (DataTotalWritable) obj;

if (downPackNum != other.downPackNum)

return false;

if (downPayLoad != other.downPayLoad)

return false;

if (upPackNum != other.upPackNum)

return false;

if (upPayLoad != other.upPayLoad)

return false;

return true;

}

 

@Override

public String toString() {

return upPackNum + "\t"+ downPackNum + "\t"

+ upPayLoad + "\t"+ downPayLoad ;

}

 

public void write(DataOutput out) throws IOException {

out.writeLong(upPackNum);

out.writeLong(downPackNum);

out.writeLong(upPayLoad);

out.writeLong(downPayLoad);

}

 

public void readFields(DataInput in) throws IOException {

this.upPackNum = in.readLong() ;

this.downPackNum = in.readLong() ;

this.upPayLoad = in.readLong() ;

this.downPayLoad = in.readLong() ;

}

 

}

 

----DataTotalMapReduce-----------

 

package com.myblue.myhdfs;

 

import java.io.IOException;

import org.apache.commons.lang.StringUtils;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.conf.Configured;

import org.apache.hadoop.fs.FileSystem;

import org.apache.hadoop.fs.Path;

import com.myblue.myhdfs.DataTotalWritable;

import org.apache.hadoop.io.LongWritable;

import org.apache.hadoop.io.Text;

import org.apache.hadoop.mapreduce.Mapper;

import org.apache.hadoop.mapreduce.Reducer;

import org.apache.hadoop.mapreduce.Job;

import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;

import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import org.apache.hadoop.util.Tool;

import org.apache.hadoop.util.ToolRunner;

 

public class DataTotalMapReduce extends Configured implements Tool {

 

public static class DataTotalMapper extends

Mapper<LongWritable, Text, Text, DataTotalWritable> {

 

@Override

protected void map(LongWritable key, Text value, Context context)

throws IOException, InterruptedException {

 

//split by '\t'

String[] splits = value.toString().split("\t") ;

 

//以手机号码作为output key

String phoneNum = splits[1];

Text mapOutputKey = new Text();

mapOutputKey.set(phoneNum);

 

// set map output value

long upPackNum = Long.parseLong(splits[6]) ;

long downPackNum = Long.parseLong(splits[7]) ;

long upPayLoad = Long.parseLong(splits[8]) ;

long downPayLoad = Long.parseLong(splits[9]) ;

DataTotalWritable mapOutputValue = new DataTotalWritable() ;

mapOutputValue.set(upPackNum, downPackNum, upPayLoad, downPayLoad);

 

//map output

context.write(mapOutputKey, mapOutputValue);

}

}

 

public static class DataTotalReducer extends

Reducer<Text, DataTotalWritable, Text, DataTotalWritable> {

 

@Override

protected void reduce(Text key, Iterable<DataTotalWritable> values,

Context context) throws IOException, InterruptedException {

 

long upPackNumSum = 0;

long downPackNumSum = 0;

long upPayLoadSum = 0;

long downPayLoadSum = 0;

 

//iterator

for(DataTotalWritable value : values){

upPackNumSum += value.getUpPackNum() ;

downPackNumSum += value.getDownPackNum() ;

upPayLoadSum += value.getUpPayLoad() ;

downPayLoadSum += value.getDownPayLoad()  ;

}

 

// set output value

DataTotalWritable outputValue = new DataTotalWritable() ;

outputValue.set(upPackNumSum, downPackNumSum, upPayLoadSum, downPayLoadSum);

 

// output

context.write(key, outputValue);

}

}

 

public int run(String[] args) throws Exception {

 

//Job

Configuration conf = super.getConf();

Job job = Job.getInstance(conf);

job.setJarByClass(getClass());

 

//Mapper

job.setMapperClass(DataTotalMapper.class);

job.setMapOutputKeyClass(Text.class);

job.setMapOutputValueClass(DataTotalWritable.class);

 

//Reducer

job.setReducerClass(DataTotalReducer.class);

job.setOutputKeyClass(Text.class);

job.setOutputValueClass(DataTotalWritable.class);

 

//输入路径

Path inPath = new Path(args[0]);

FileInputFormat.addInputPath(job, inPath);

//输出路径

Path outPath = new Path(args[1]);

FileSystem dfs = FileSystem.get(conf);

if (dfs.exists(outPath)) {

dfs.delete(outPath, true);

}

FileOutputFormat.setOutputPath(job, outPath);

 

//Submit Job

boolean isSuccess = job.waitForCompletion(true);

return isSuccess ? 0 : 1;

}

 

public static void main(String[] args) throws Exception {

 

args = new String[] {"hdfs://blue01.mydomain:8020/input2",

"hdfs://blue01.mydomain:8020/output2"};

 

// run job

Configuration conf = new Configuration();

int status = ToolRunner.run(conf,new DataTotalMapReduce(),args);

 

System.exit(status);

}

}

 

 

 

 

 

===================案例2Join=================================================

 

数据文件:

customer文件

1,Stephanie Leung,555-555-5555

2,Edward Kim,123-456-7890

3,Jose Madriz,281-330-8004

4,David Stork,408-555-0000

 

order文件

3,A,12.95,02-Jun-2008

1,B,88.25,20-May-2008

2,C,32.00,30-Nov-2007

3,D,25.02,22-Jan-2009

 

目标:

1,B,88.25,20-May-2008,Stephanie Leung,555-555-5555

2,C,32.00,30-Nov-2007,Edward Kim,123-456-7890

3,D,25.02,22-Jan-2009,Jose Madriz,281-330-8004

3,A,12.95,02-Jun-2008,Jose Madriz,281-330-8004

 

 

思路:

选用: Join

 

map阶段:

** map task依次读取两个文件,切割,并设置keyvalue,cidkey,同时给来自不同的文件的value打一个标签

   value ==  flag +  value

   

reduce阶段:

** Join

 

 

Map读入

<偏移量,这一行值>

Map()输出

--customer文件输出

<1,customer_[Stephanie Leung,555-555-5555]>

<2,customer_[Edward Kim,123-456-7890]>

...

 

--order文件输出

<3,order_[A,12.95,02-Jun-2008]>

<1,order_[B,88.25,20-May-2008]>

<3,order_[D,25.02,22-Jan-2009]>

...

 

Reduce()输入

<key,( ,  ,  , ) >

<1,(customer_[Stephanie Leung,555-555-5555],order_[B,88.25,20-May-2008])

<2,(customer_[Edward Kim,123-456-7890],order_[C,32.00,30-Nov-2007])

<3,(customer_[Jose Madriz,281-330-8004],order_[A,12.95,02-Jun-2008],order_[D,25.02,22-Jan-2009])

<4,(customer_[David Stork,408-555-0000])

 

----DataJoinWritable-------------

 

package com.myblue.myhdfs;

 

import java.io.DataInput;

import java.io.DataOutput;

import java.io.IOException;

import org.apache.hadoop.io.Writable;

 

public class DataJoinWritable implements Writable {

 

private String flag;

private String data;

 

public DataJoinWritable() {

}

 

public DataJoinWritable(String flag, String data) {

this.set(flag, data);

}

public void set(String flag, String data) {

this.flag = flag;

this.data = data;

}

 

public String getFlag() {

return flag;

}

 

public void setFlag(String flag) {

this.flag = flag;

}

 

public String getData() {

return data;

}

 

public void setData(String data) {

this.data = data;

}

 

@Override

public int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result + ((data == null) ? 0 : data.hashCode());

result = prime * result + ((flag == null) ? 0 : flag.hashCode());

return result;

}

 

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

DataJoinWritable other = (DataJoinWritable) obj;

if (data == null) {

if (other.data != null)

return false;

} else if (!data.equals(other.data))

return false;

if (flag == null) {

if (other.flag != null)

return false;

} else if (!flag.equals(other.flag))

return false;

return true;

}

 

@Override

public String toString() {

return flag + "," + data ;

}

 

public void write(DataOutput out) throws IOException {

//用与平台无关的方式使用UTF-8编码将一个字符串写入输出流

out.writeUTF(getFlag());

out.writeUTF(getData());

}

 

public void readFields(DataInput in) throws IOException {

this.flag = in.readUTF() ;

this.data = in.readUTF() ;

}

}

 

----DataJoinMapReduce--------------

 

package com.myblue.myhdfs;

 

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.conf.Configured;

import org.apache.hadoop.fs.FileSystem;

import org.apache.hadoop.fs.Path;

import com.myblue.myhdfs.DataJoinWritable;

import org.apache.hadoop.io.LongWritable;

import org.apache.hadoop.io.NullWritable;

import org.apache.hadoop.io.Text;

import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;

import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import org.apache.hadoop.util.Tool;

import org.apache.hadoop.util.ToolRunner;

import org.apache.hadoop.mapreduce.Mapper;

import org.apache.hadoop.mapreduce.Reducer;

import org.apache.hadoop.mapreduce.Job;

 

public class DataJoinMapReduce extends Configured implements Tool {

 

public static class DataJoinMapper extends

Mapper<LongWritable, Text, Text, DataJoinWritable> {

 

@Override

protected void map(LongWritable key, Text value, Context context)

throws IOException, InterruptedException {

 

String[] splits = value.toString().split(",");

 

//output key,以连接值为key

String cid = splits[0];

Text mapOutputKey = new Text();

mapOutputKey.set(cid);

 

//output value

DataJoinWritable mapOutputValue = new DataJoinWritable();

 

// length == 3 ==> customer

if (splits.length == 3) {

String name = splits[1];

String phoneNum = splits[2];

 mapOutputValue.set("customer", name + "," + phoneNum);

}

 

// length == 4 ==> order

if (splits.length == 4) {

String name = splits[1];

String price = splits[2];

String date = splits[3];

mapOutputValue.set("order", name + "," + price + "," + date);

`}

 

context.write(mapOutputKey, mapOutputValue);

}

}

 

public static class DataJoinReducer extends

Reducer<Text, DataJoinWritable, NullWritable, Text> {

 

@Override

protected void reduce(Text key, Iterable<DataJoinWritable> values, Context context)

throws IOException, InterruptedException {

 

String customerInfo = null;

List<String> orderList = new ArrayList<String>();

 

for (DataJoinWritable value : values) {

if ("customer".equals(value.getFlag())) {

customerInfo = value.getData();

} else if ("order".equals(value.getFlag())) {

orderList.add(value.getData());

}

}

 

Text outputValue = new Text();

for (String order : orderList) {

outputValue.set(key.toString() + "," + order + "," + customerInfo);

context.write(NullWritable.get(), outputValue);

}

}

}

 

public int run(String[] args) throws Exception {

 

Configuration conf = super.getConf();

Job job = Job.getInstance(conf);

job.setJarByClass(getClass());

 

//Mapper

job.setMapperClass(DataJoinMapper.class);

job.setMapOutputKeyClass(Text.class);

job.setMapOutputValueClass(DataJoinWritable.class);

 

//Reducer

job.setReducerClass(DataJoinReducer.class);

job.setOutputKeyClass(NullWritable.class);

job.setOutputValueClass(Text.class);

 

//输入路径

Path inPath = new Path(args[0]);

FileInputFormat.addInputPath(job, inPath);

//输出路径

Path outPath = new Path(args[1]);

FileSystem dfs = FileSystem.get(conf);

if (dfs.exists(outPath)) {

dfs.delete(outPath, true);

}

FileOutputFormat.setOutputPath(job, outPath);

 

//Submit Job

boolean isSuccess = job.waitForCompletion(true);

return isSuccess ? 0 : 1;

}

 

public static void main(String[] args) throws Exception {

 

args = new String[] {"hdfs://blue01.mydomain:8020/input2",

"hdfs://blue01.mydomain:8020/output2"};

 

Configuration conf = new Configuration();

int status = ToolRunner.run(conf,new DataJoinMapReduce(), args);

 

System.exit(status);

}

}

 

-----------------------------------

 

 

 

 

 

 

 

 

 

mapreduce中的Join

** MapJoin  

** 一个表比较小,另外一个表非常大

   会把小表数据完整的放入到大表关联的每台nodemanager节点的内存中去,

   [map task]依次匹配内存中小表数据         

**  reduceJoin

** 两张表通常都是大文件

** Join的操作是在Reduce端执行

** semi Join

** mapJoinreduceJoin结合

** mapper在读取block数据处理的时候,如果有相关字段则保留,否则过滤掉。然后把需要的数据传递给reduce端进行join

 

====Shuffle==============================================================

 

MapReduce程序

** 离线数据分析、数据清洗(过滤脏数据)

** 执行命令:bin/yarn jar 包名.类名 参数

 

MapReduce Shuffle

数据从map task输出到reduce task输入的这段过程

** map的输入: split

** 默认情况下,一个block就是一个split,一个split对应一个map

** 尽量保证每个map的输入数据是来自同一个block

** 如果设计多个block为一个split,可能会造成大量额外流量

** 合理控制map个数

 

>>Input

<0,hadoop mapreduce>

<14,hbase hadoop>

>>map()

** map() --> value.toString().split("\t")

** output

<hadoop,1> <mapreduce,1> <hbase,1> <hadoop,1>

 

----Shuffle---------------

 

>>>>>>>> map shuffle

>>> 环形缓存区

默认大小100M   mapreduce.task.io.sort.mb

>>> partition分区

** HashPartitioner

** 决定数据交给哪个reduce处理

1hadoop   hbase-->reduce1

2mapreduce--> reduce2

3...--> reduce3

>>> sort

**  按照key进行字典顺序排序

>>> combine (可选,并非所有的情况都可以使用combine)

** 默认情况下,相当于map阶段局部reduce

>>> spill

** 当环形缓存区容量达到80M(0.8) mapreduce.map.sort.spill.percent

** 会将缓存区的数据写入本地磁盘临时目录(不是HDFS)

>>> merge

** 把很多小文件合并成一个大文件

>>> compress (可选)

** 减轻网络IO的压力

 

>>>>>>>> reduce shuffle application master

每个reduce会去map的输出结果中拉取自己对应的分区数据

merge合并

** 按照key进行文件合并

group分组

** 将相同keyvalue值放到一起,形成list

** <hadoop,(1,1)> <mapreduce,1> ...

 

----reduce-------------

 

>>reduce

<hadoop,(1,1)><mapreduce,1><hbase,1>

>>output

** 数据汇总

** hadoop 2mapreduce 1hbase 1 ...

 

设置reduce个数:

** 当前job任务

job.setNumReduceTasks(n);

** 永久生效

配置文件 mapred-site.xml

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Day06

回顾:

[MapReduce的个数]

map的个数由什么决定   切片

1.每一个文件会有1map(不足128M

2.大于128M文件存储一个一个的blockmap个数就是block的个数

***.avi文件 有10block 10map

129M文件切成2block,一个128M,另一个1M,最后一个块小于block1.1

split 大小就和block大小一致

max0min(block.size, split.max)

reducede 个数

默认情况下1,输出目录只有一个part**文件

reduce的个数可以设定

设置3reduce,输出目录里面的part*文件有3

 

key.hashcode(整形数据 int) 取模 partition 个数

设置了 partition 个数如果3

a  1

b  2

c  3

d  4

e  5

f  6

 

3 取模

a d -> reduce 0

b e -> reduce 1

c f -> reduce 2

 

分区就是增加并行度,分到不同的节点进行计算

 job.setNumReduceTasks(2);

MapReduce <key -> value>

1.分区

2.分组

3.排序

都是针对于key完成

自定义key    ->  实现WritableComparebale序列化接口

自定义value  ->  实现Writable序列化接口

自定义分区

自定义分区

 

====二次排序=================================================

 

思路:

** MapReduce特性:自动对key进行排序

** 把需要排序的第一字段和第二字段组合成一个新的key

(可选)

** 修改分区规则--针对原始key进行分区

** 修改分组规则--针对原始key进行分组

 

具体实现:

** 自定义Key数据类型,实现WritableComparable接口

(可选)

** 自定义分区函数类,实现Partitioner接口

** 自定义分组类

** 继承WritableComparator

** 继承RawComparator接口

 

----PairWritable-------------------

 

package com.myblue.mymapreduce;

 

import java.io.DataInput;

import java.io.DataOutput;

import java.io.IOException;

import org.apache.hadoop.io.WritableComparable;

 

//自定义类型

public class PairWritable implements WritableComparable<PairWritable> {

 

private String first;

private int second;

 

public PairWritable() {

}

 

public PairWritable(String first, int second) {

this.set(first, second);

}

public void set(String first, int second) {

this.first = first;

this.second = second;

}

 

public String getFirst() {

return first;

}

 

public void setFirst(String first) {

this.first = first;

}

 

public int getSecond() {

return second;

}

 

public void setSecond(int second) {

this.second = second;

}

 

@Override

public int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result + ((first == null) ? 0 : first.hashCode());

result = prime * result + second;

return result;

}

 

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

PairWritable other = (PairWritable) obj;

if (first == null) {

if (other.first != null)

return false;

} else if (!first.equals(other.first))

return false;

if (second != other.second)

return false;

return true;

}

 

@Override

public String toString() {

return first + "," + second ;

}

 

public void write(DataOutput out) throws IOException {

out.writeUTF(first);

out.writeInt(second);

}

 

public void readFields(DataInput in) throws IOException {

this.first = in.readUTF();

this.second = in.readInt();

}

 

//比较两个对象的大小

public int compareTo(PairWritable o) {

 

//先比较第一个值

int result = this.getFirst().compareTo(o.getFirst());

 

if( result != 0 ){//比较出大小

return result;

}else

return Integer.valueOf(getSecond()).compareTo(Integer.valueOf(o.getSecond()));

}

}

 

----SecondarySortMapReduce-------------------

 

package com.myblue.mymapreduce;

 

import java.io.IOException;

import org.apache.hadoop.mapreduce.Mapper;

import org.apache.hadoop.mapreduce.Reducer;

import org.apache.hadoop.mapreduce.Job;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.conf.Configured;

import org.apache.hadoop.fs.FileSystem;

import org.apache.hadoop.fs.Path;

import org.apache.hadoop.io.LongWritable;

import org.apache.hadoop.io.Text;

import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;

import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import org.apache.hadoop.util.Tool;

import org.apache.hadoop.util.ToolRunner;

 

public class SecondarySortMapReduce extends Configured implements Tool {

 

public static class SecondarySortMapper extends

Mapper<LongWritable, Text, PairWritable, LongWritable> {

 

@Override

protected void map(LongWritable key, Text value, Context context)

throws IOException, InterruptedException {

 

String[] splits = value.toString().split(",") ;

 

//output key

PairWritable mapOutputKey = new PairWritable();

mapOutputKey.set(splits[0], Integer.valueOf(splits[1]));

 

//output Value

LongWritable mapOutputValue = new LongWritable() ;

mapOutputValue.set(Long.valueOf(splits[1]));

 

context.write(mapOutputKey, mapOutputValue);

}

}

 

public static class SecondarySortReducer extends

Reducer<PairWritable, LongWritable, Text, LongWritable> {

 

@Override

protected void reduce(PairWritable key, Iterable<LongWritable> values,

Context context) throws IOException, InterruptedException {

 

Text outputKey = new Text();

for(LongWritable value : values){

outputKey.set(key.getFirst());

context.write(outputKey, value);

}

}

}

 

public int run(String[] args) throws Exception {

 

Configuration conf = super.getConf();

Job job = Job.getInstance(conf);

job.setJarByClass(getClass());

 

//Mapper

job.setMapperClass(SecondarySortMapper.class);

job.setMapOutputKeyClass(PairWritable.class);

job.setMapOutputValueClass(LongWritable.class);

 

// 1.Partition,可以注释

job.setPartitionerClass(FirstPartitioner.class);

// 2.sort

// job.setSortComparatorClass(cls);

// 3.combine

// job.setCombinerClass(WordCountReducer.class);

// 4.compress

// conf.set("mapreduce.map.output.compress", "false");

// 5.group,可以注释

job.setGroupingComparatorClass(FirstGroupingComparator.class);

 

//Reducer

job.setReducerClass(SecondarySortReducer.class);

job.setOutputKeyClass(Text.class);

job.setOutputValueClass(LongWritable.class);

 

Path inPath = new Path(args[0]);

FileInputFormat.addInputPath(job, inPath);

Path outPath = new Path(args[1]);

FileSystem dfs = FileSystem.get(conf);

if (dfs.exists(outPath)) {

dfs.delete(outPath, true);

}

FileOutputFormat.setOutputPath(job, outPath);

 

boolean isSuccess = job.waitForCompletion(true);

return isSuccess ? 0 : 1;

}

 

public static void main(String[] args) throws Exception {

 

args = new String[]{"hdfs://blue01.mydomain:8020/input",

"hdfs://blue01.mydomain:8020/output"};

 

Configuration conf = new Configuration();

int status = ToolRunner.run(conf,new SecondarySortMapReduce(),args);

 

System.exit(status);

}

}

 

----FirstPartitioner-------------------

 

package com.myblue.mymapreduce;

 

import org.apache.hadoop.io.LongWritable;

import org.apache.hadoop.mapreduce.Partitioner;

 

public class FirstPartitioner extends Partitioner<PairWritable, LongWritable>{

 

public int getPartition(PairWritable key, LongWritable value,

int numPartitions) {

 

// [0-9] [a-n] [o-z]

//if(key.matches("[0-9].*")){

//return 0;

//}else if(key.matches("[a-n].*")){

//return 1;

//}else

//return 2;

 

return (key.getFirst().hashCode() & Integer.MAX_VALUE) % numPartitions;

}

}

 

----FirstGroupingComparator-------------------

 

package com.myblue.mymapreduce;

 

import org.apache.hadoop.io.RawComparator;

import org.apache.hadoop.io.WritableComparator;

 

public class FirstGroupingComparator implements RawComparator<PairWritable> {

 

public int compare(PairWritable o1, PairWritable o2) {

return o1.getFirst().compareTo(o2.getFirst());

}

 

public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {

return WritableComparator.compareBytes(b1, 0, l1-4, b2, 0, l2-4);

}

}

 

一、学习内容

1.Zookeeper  (文件系统 角色 选举机制 watch

2.HA (Namenode HA)   ZKFC(fail over)   隔离机制(fence "篱笆")  元数据同步(QJM

3.HA (ResourceManager HA)

二、Zookeeper

(一)、文件系统(数据结构)

 Znode1.代表zookeeper文件系统中的一个目录,2.代表 实体的客户端(Namenode))

 动物 -> hadoop 中的节点 Namende

(二)、Watch事件

1.NameNode启动,然后向Zookeeper,触发注册事件,同时会创建一个唯一的目录

2.通过心跳信息,来确认节点的状态(存活或者宕机)

3.如果宕机,失去心跳信息,触发节点丢失事件,删除这个目录

Zookeeper是一个多server的服务(一台服务器就是一个server

leader

fllower

(三)、投票(理解企业中节点为什么是奇数个 2n+1

leader的候选人必须获取到超过半数的选票 n+1

zookeeper集群中存活的节点数据必须过半数容错率

3台  挂掉1台     33%

4台  挂掉1台     25%

1zookeeper的选举过程中,为了保证选举过程最后能选出leader,就一定不能出现两台机器得票相同的僵局,所以一般的,要求zk集群的server数量一定要是奇数,也就是2n+1台,

2如果集群出现问题,其中存活的机器必须大于n+1台,否则leader无法获得多数server的支持,系统就自动挂掉。所以一般是3个或者3个以上节点。要使Leader获得多数Server的支持,则Server总数必须是奇数2n+1,且存活的Server的数目不得少于n+1

32n+1 2n+2失效节点的容忍度是一致性的,那么这样的话,就没有必要多安装一个节点

 

Zookeeper的功能以及工作原理 - FelixZh - 博客园  http://www.cnblogs.com/felixzh/p/5869212.html

选举流程(2种)

1.basic paxos

2.fast paxos(毛遂自荐)

 

zookeeper(动物管理员) 安装

(一)伪分布式

##安装ZooKeeper

$ tar -zxf  /opt/software/zookeeper-3.4.5.tar.gz -C  /opt/modules/waremodules/

 

##新建一个Zookeeperdata目录

$ mkdir zkData   --//可以不用手动创建,启动自动生成

 

 ##修改配置文件${ZOOKEEPER_HOME}/conf

  1$ cp zoo_sample.cfg zoo.cfg

  2vi  zoo.cfg

 dataDir=/opt/modules/zookeeper-3.4.5/zkData

 

##启动zookeeper

bin/zkServer.sh start

8967 QuorumPeerMain

 

##查看zookeeper的状态

bin/zkServer.sh status

 

JMX enabled by default

Using config: /opt/modules/zookeeper-3.4.5/bin/../conf/zoo.cfg

Mode: standalone    单机模式

 

(二)完全分布式

1.安装JDK(3PC都要安装JDK)

配置环境变量

2.安装完全分布式集群

1)安装zk

2)配置zoo.cfg文件

dataDir=/opt/modules/zookeeper-3.4.5/zkData

server.1=hadoop.ibeifeng.com.cn01:2888:3888

server.2=hadoop.ibeifeng.com.cn02:2888:3888

server.3=hadoop.ibeifeng.com.cn03:2888:3888

3)创建zkData目录,在zkData目录目录下创建myid文件,编辑myid,内同就是此台serverid,就是zoo.cfg中指定的server.1

 

4)从第一台(PC1)分发zookeeper目录

/opt/modules目录下

$ scp -r zookeeper/ feng.com:/home/gu/ruan

 

5)修改第2PC2)、3(PC3)台的myid文件

vi myid

修改对应的id(根据conf/zoo.zfg中绑定到server.n的主机名对应)

 

6)启动(3台上)

$ bin/zkServer.sh start

 

7)检查进程

jps

3050 QuorumPeerMain

3111 Jps

 

8)检查并核对状态(3台上)

$ bin/zkServer.sh status

 

 

JMX enabled by default

Using config: /opt/modules/zookeeper-3.4.5/bin/../conf/zoo.cfg

Mode: follower

 

JMX enabled by default

Using config: /opt/modules/zookeeper-3.4.5/bin/../conf/zoo.cfg

Mode: follower

 

 bin/zkServer.sh status

JMX enabled by default

Using config: /opt/modules/zookeeper-3.4.5/bin/../conf/zoo.cfg

Mode: leader

 

9)访问zookeeper文件系统

在进程启动正常的情况下

$ bin/zkCli.sh connect feng.com:2181

 

[zk: localhost:2181(CONNECTED) 0] ls /     --查看根目录

[zookeeper]

[zk: localhost:2181(CONNECTED) 1] ls /zookeeper  --查看zookeeper目录

[quota]

[zk: localhost:2181(CONNECTED) 2] ls /zookeeper/quota

[]

[zk: localhost:2181(CONNECTED) 3] help   --查看支持的所命令

 

ZooKeeper -server host:port cmd args

connect host:port

get path [watch]

ls path [watch]

set path data [version]

rmr path

 

 

Hadoop Ha (High avilable)

Namenode HA

集群规划(3)

PC01PC02PC03

NameNodeNameNode

ZKFCZKFC

ResourceManager

DataNodeDataNodeDataNode

JournalNodeJournalNodeJournalNode

NodeManagerNodeManagerNodeManager

ZooKeeperZooKeeperZooKeeper

 

)安装hadoop

 

)配置环境文件

hadoop-env.sh

mapred-env.sh

yarn-env.sh

export JAVA_HOME=/opt/modules/jdk1.7.0_67

 

三)配置4site.xml文件

 

1.========core-site.xml========

<!--NameNode HA的逻辑访问名称-->

<property>

<name>fs.defaultFS</name>

<value>hdfs://ns1</value>

</property>

 

<property>

<name>hadoop.tmp.dir</name>

<value>/opt/modules/hadoop-2.5.0/data</value>

</property>

 

2.=================hdfs-site.xml=============

<!-- 分布式副本数设置为3 -->

<property>

        <name>dfs.replication</name>

        <value>3</value>

    </property>

<!--指定hdfsnameservicens1,需要和core-site.xml中的保持一致 -->

<property>

<name>dfs.nameservices</name>

<value>ns1</value>

</property>

 

<!-- ns1下面有两个NameNode,分别是nn1nn2 -->

<property>

<name>dfs.ha.namenodes.ns1</name>

<value>nn1,nn2</value>

</property>

 

<!-- nn1RPC通信地址 -->

<property>

<name>dfs.namenode.rpc-address.ns1.nn1</name>

<value>yu.com:8020</value>

</property>

<!-- nn1http通信地址 -->

<property>

<name>dfs.namenode.http-address.ns1.nn1</name>

<value>yu.com:50070</value>

</property>

 

<!-- nn2RPC通信地址 -->

<property>

<name>dfs.namenode.rpc-address.ns1.nn2</name>

<value>gcf.com:8020</value>

</property>

<!-- nn2http通信地址 -->

<property>

<name>dfs.namenode.http-address.ns1.nn2</name>

<value>gcf.com:50070</value>

</property>

 

<!-- 指定NameNode的元数据在JournalNode上的存放位置 -->

<property>

<name>dfs.namenode.shared.edits.dir</name>

<value>qjournal://yu.com:8485;gcf.com:8485;feng.com:8485/ns1</value>

</property>

<!-- 指定JournalNode在本地磁盘存放数据的位置 -->

<property>

<name>dfs.journalnode.edits.dir</name>

<value>/opt/modules/hadoop-2.5.0/journal</value>

</property>

 

<!-- 配置隔离机制方法,多个机制用换行分割,即每个机制暂用一行

sshfence:Active出问题后,standby切换成Active,此时,原Active又没有停止服务,这种情况下会被强制杀死进程。

shell(/bin/true)NN Active和它的ZKFC一起挂了,没有人通知ZKZK长期没有接到通知,standby要切换,此时,standby调一个shell(脚本内容),这个脚本返回true则切换成功。

-->

<property>

<name>dfs.ha.fencing.methods</name>

<value>

sshfence

shell(/bin/true)

</value>

</property>

 

<!-- 使用sshfence隔离机制时需要ssh免登陆 -->

<property>

<name>dfs.ha.fencing.ssh.private-key-files</name>

<value>/home/hadoop/.ssh/id_rsa</value>

</property>

 

<!-- 配置sshfence隔离机制超时时间 -->

<property>

<name>dfs.ha.fencing.ssh.connect-timeout</name>

<value>30000</value>

</property>

 

<!-- 关闭权限检查用户或用户组 -->

<property>

        <name>dfs.permissions.enabled</name>

        <value>false</value>

    </property>

 

3.=============mapred-site.xml

<property>

        <name>mapreduce.framework.name</name>

        <value>yarn</value>

    </property>

 

<property>

        <name>mapreduce.jobhistory.address</name>

        <value>yu.com:10020</value>

    </property>

 

<property>

        <name>mapreduce.jobhistory.webapp.address</name>

        <value>yu.com:19888</value>

    </property>

 

  4.============yarn-site.xml

  <property>

        <name>yarn.resourcemanager.hostname</name>

        <value>feng.com</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-aggregation.retain-seconds</name>

        <value>86400</value>

    </property>

 

5.=================slaves

yu.com

gcf.com

feng.com

 

)分发配置

$ scp etc/hadoop/core-site.xml etc/hadoop/hdfs-site.xml etc/hadoop/slaves etc/hadoop/yarn-site.xml /etc/hadoop/ feng.com:/home/gu/ruan/hadoop-2.5.0/etc/hadoop/

 

$ scp etc/hadoop/core-site.xml etc/hadoop/hdfs-site.xml  feng.com:/opt/modules/hadoop-2.5.0/etc/hadoop/

 

五)启动HDFS HA

## 注意:每一个步骤都严格按照以下步骤执行

1.删除datalogs目录(3台上,有必须删掉)

$ rm -rf data logs

 

2.启动zk3台上都要)

$ bin/zkServer.sh start

 

3.启动journalnode3台上都要)

$ sbin/hadoop-daemon.sh start journalnode

 

4.[nn1]格式化namenode(PC1 也就是nn1)

$ bin/hdfs namenode -format   

$ sbin/hadoop-daemon.sh start namenode

 

5.[nn2]同步nn1的元数据(PC2 也就是nn2)

$ bin/hdfs namenode -bootstrapStandby

$ sbin/hadoop-daemon.sh start namenode

 

6.查看web界面

http://yu.com:50070       ##standby

http://gcf.com:50070       ##standby

 

7.手动切换namenode的状态

$ bin/hdfs haadmin -transitionToActive nn1  ##切换active

$ bin/hdfs haadmin -transitionToStandby nn1  ##切换成standby

 

六)开启故障自动转移

1.配置故障转移

1=====core-site.xml

<property>

<name>ha.zookeeper.quorum</name>

<value>yu.com:2181,gcf.com:2181,feng.com:2181</value>

</property>

 

2====hdfs-site.xml

<property>

<name>dfs.ha.automatic-failover.enabled</name>

<value>true</value>

</property>

 

<property>

<name>dfs.client.failover.proxy.provider.ns1</name>

<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>

</property>

 

2.分发配置文件

$ scp etc/hadoop/core-site.xml  etc/hadoop/hdfs-site.xml feng.com:/home/gu/ruan/hadoop-2.5.0/etc/hadoop/

 

3.启动故障转移服务

1)首先停止hdfszk

$ sbin/stop-dfs.sh

 

$ bin/zkServer.sh stop##关闭zk(3台服务器)

重启

$ bin/zkServer.sh start##启动zk(3台服务器)

 

2)初始化zkfc[PC1也就是nn1]

$ bin/hdfs zkfc -formatZK  ##初始化ZKFC

 

17/03/27 16:49:18 INFO ha.ActiveStandbyElector: Successfully created /hadoop-ha/ns1 in ZK.

 

$ sbin/start-dfs.sh##启动hdfs

 

bin/hdfs haadmin -getServiceState nn1     #查看nn1状态

bin/hdfs haadmin -getServiceState nn2     #查看nn2状态

 

[PC1]

[hadoop@hadoop hadoop-2.5.0]$ jps

4196 JournalNode

4356 DFSZKFailoverController

4012 DataNode

3920 NameNode

3586 QuorumPeerMain

4458 Jps

 

[PC2]

[hadoop@hadoop hadoop-2.5.0]$ jps

4117 Jps

3849 DataNode

3786 NameNode

3926 JournalNode

3633 QuorumPeerMain

4045 DFSZKFailoverController

 

[PC3]

[hadoop@hadoop hadoop-2.5.0]$ jps

3387 DataNode

3461 JournalNode

3551 Jps

3231 QuorumPeerMain

 

 

 

 

 

 

 

 

 

 

 

 

 

五、ResourceManager HA

一、集群规划(3)

PC01PC02PC03

NameNodeNameNode

ZKFCZKFC

ResourceManagerResourceManager

DataNodeDataNodeDataNode

JournalNodeJournalNodeJournalNode

NodeManagerNodeManagerNodeManager

ZooKeeperZooKeeperZooKeeper

 

二、修改配置文件

 

=====yarn-site.xml

<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-aggregation.retain-seconds</name>

        <value>86400</value>

    </property>

 

 

<!--启用resourcemanager ha-->

<property>

   <name>yarn.resourcemanager.ha.enabled</name>

   <value>true</value>

</property>

 

<property>

   <name>yarn.resourcemanager.cluster-id</name>

   <value>rmcluster</value>

</property>

 

<property>

   <name>yarn.resourcemanager.ha.rm-ids</name>

   <value>rm1,rm2</value>

</property>

 

<property>

   <name>yarn.resourcemanager.hostname.rm1</name>

   <value>gcf.com</value>

</property>

 

<property>

   <name>yarn.resourcemanager.hostname.rm2</name>

   <value>feng.com</value>

</property>

 

<!--指定zookeeper集群的地址-->

<property>

   <name>yarn.resourcemanager.zk-address</name>  

   <value>yu.com:2181,gcf.com:2181,feng.com:2181</value>

</property>

 

<!--启用自动恢复-->

<property>

   <name>yarn.resourcemanager.recovery.enabled</name>

   <value>true</value>

</property>

 

<!--指定resourcemanager的状态信息存储在zookeeper集群-->

<property>

   <name>yarn.resourcemanager.store.class</name>

   <value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>

</property>

 

 

三、分发配置文件

yarn-site.xml分发到其他两台

scp etc/hadoop/yarn-site.xml gcf.com:/opt/modules/hadoop-2.5.0/etc/hadoop/

 

scp etc/hadoop/yarn-site.xml feng.com:/opt/modules/hadoop-2.5.0/etc/hadoop/

 

四、启动ResourceManagere

PC2上:

sbin/start-yarn.sh

 

pc3上单独启动:

sbin/yarn-daemon.sh start resourcemanager

 

 

PC1

jps

5468 DataNode

5934 NodeManager

5653 JournalNode

5820 DFSZKFailoverController

5371 NameNode

3586 QuorumPeerMain

6058 Jps

 

PC2

jps

5023 NodeManager

4825 DFSZKFailoverController

4554 NameNode

4621 DataNode

4714 JournalNode

5359 Jps

4927 ResourceManager

3633 QuorumPeerMain

 

[PC3]

$ jps

3792 DataNode

3986 NodeManager

3881 JournalNode

4178 Jps

4120 ResourceManager

3231 QuorumPeerMain

 

 

 

 

 

 

 

 

 

 

 

 

Day07

一、HDFS使用讲解

1.测试NameNode HA

-在处于activeNamenode上使用kill -9  pid(NameNode)

-web界面查看切换结果

2.Namenode元数据在本地存放的目录

[扩展] 安装tree

切换root用户

# yum install tree -y

 

 

/opt/modules/hadoop-2.5.0/data/dfs/name/current/

 

元数据

├── fsimage_0000000000000000256

├── fsimage_0000000000000000256.md5

├── fsimage_0000000000000000316

├── fsimage_0000000000000000316.md5

 

edit文件

├── edits_0000000000000000001-0000000000000000002

├── edits_0000000000000000003-0000000000000000004

├── edits_0000000000000000005-0000000000000000006

├── edits_0000000000000000007-0000000000000000008

├── edits_0000000000000000009-0000000000000000010

 

正在写入的日志文件

├── edits_inprogress_0000000000000000360

 

3.HDFS block的元数据本地存储

/opt/modules/hadoop-2.5.0/data/dfs/data/current/

├── dfsUsed

               ├── finalized

                  ├── blk_1073741835

                  ├── blk_1073741835_1011.meta

                  ├── blk_1073741836

                  ├── blk_1073741836_1012.meta

                  ├── blk_1073741837

                  ├── blk_1073741837_1013.meta

                  ├── blk_1073741838

                  ├── blk_1073741838_1014.meta

                  ├── blk_1073741839

                  └── blk_1073741839_1015.meta

 

4.程序开发中如何访问hdfs

hdfs//ns1/input

 

5.使用IDE开发MapRedcue或者HDFS API

-在工程下面创建source folder

src/resource

-将当前namenode HA的配置文件core-site.xml hdfs-site.xml拷贝到工程中的src/resource

 

二、ResouceManager的使用讲解

1.查看ResourceManager的状态

$ bin/yarn rmadmin -getServiceState rm1   

active##查看rm1的状态

$ bin/yarn rmadmin -getServiceState rm2   ##查看rm2的状态

standby

2.web界面,如果访问的是处于standby状态的resoucemanager会提示以下信息,并且会自动跳转到处于active的那台上

This is standby RM. Redirecting to the current active RM: http://feng.com:8088/

三、Namenode 联盟 联邦

Namenode 的水平扩展

每个Namenode 相当于一个州(51个,每一个都比较自治),组合起来就是一个美联邦政府

相当于硬盘分区 每一个分区(C D E F 盘),独立访问

业务隔离

方便管理

Federation即为“联邦”,该特性允许一个HDFS集群中存在多个NameNode同时对外提供服务,这些NameNode分管一部分目录(水平切分),彼此之间相互隔离,但共享底层的DataNode存储资源。

 

Namenode1(业务1)   namenode2(业务2)   namenode3(业务3

*存储空间充分利用

*业务隔离,分类管理  

四、配置NameNode联盟

一)、集群规划

==集群规划

PC01         PC02  PC03

hadoop-senior01hadoop-senior02hadoop-senior03

namenode        namenode

datanode        datanode      datanode

 

二)、修改配置文件

======core-site.xml=======

[PC1]

<property>

<name>fs.defaultFS</name>

<value>hdfs://yu.com:8020</value>

</property>

 

<property>

<name>hadoop.tmp.dir</name>

<value>/opt/modules/hadoop-2.5.0/data</value>

</property>

 

***********需要单独修改

[PC2]

<property>

<name>fs.defaultFS</name>

<value>hdfs://gcf.com:8020</value>

</property>

 

<property>

<name>hadoop.tmp.dir</name>

<value>/opt/modules/hadoop-2.5.0/data</value>

</property>

**************

 

=========hdfs-site.xml===========

<!-- 分布式副本数设置为3 -->

<property>

        <name>dfs.replication</name>

        <value>3</value>

    </property>

 

<property>

<name>dfs.nameservices</name>

<value>ns1,ns2</value>

</property>

 

 

<!-- ns1RPC通信地址 -->

<property>

<name>dfs.namenode.rpc-address.ns1</name>

<value>yu.com:8020</value>

</property>

 

<!-- ns1http通信地址 -->

<property>

<name>dfs.namenode.http-address.ns1</name>

<value>yu.com:50070</value>

</property>

 

<!-- ns2RPC通信地址 -->

<property>

<name>dfs.namenode.rpc-address.ns2</name>

<value>gcf.com:8020</value>

</property>

<!-- ns2http通信地址 -->

<property>

<name>dfs.namenode.http-address.ns2</name>

<value>gcf.com:50070</value>

</property>

 

==========mapred-site.xml=========

<property>

        <name>mapreduce.framework.name</name>

        <value>yarn</value>

    </property>

<property>

        <name>mapreduce.jobhistory.address</name>

        <value>yu.com:10020</value>

    </property>

<property>

        <name>mapreduce.jobhistory.webapp.address</name>

        <value>yu.com:19888</value>

    </property>

 

===========yarn-site.xml=========

  <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-aggregation.retain-seconds</name>

        <value>86400</value>

    </property>

 

<property>

<name>yarn.resourcemanager.hostname</name>

<value>feng.com</value>

</property>

 

三)、分发配置文件

   scp etc/hadoop/core-site.xml etc/hadoop/hdfs-site.xml etc/hadoop/mapred-site.xml etc/hadoop/yarn-site.xml gcf.com:/opt/modules/hadoop-2.5.0/etc/hadoop/

 

   scp etc/hadoop/core-site.xml etc/hadoop/hdfs-site.xml etc/hadoop/mapred-site.xml etc/hadoop/yarn-site.xml feng.com:/opt/modules/hadoop-2.5.0/etc/hadoop/

 

四)、在ns1(PC1)ns2(PC2)上执行

bin/hdfs namenode -format -clusterId hdfs-cluster

$ sbin/hadoop-daemon.sh start namenode

 

五)、启动所有节点的datanode

sbin/hadoop-daemon.sh start datanode

 

[PC1]

[hadoop@hadoop hadoop-2.5.0]$ jps

2761 DataNode

4478 Jps

2686 NameNode

 

[PC2]

[hadoop@hadoop hadoop-2.5.0]$ jps

4851 Jps

2769 DataNode

2694 NameNode

 

[PC3]

[hadoop@hadoop hadoop-2.5.0]$ jps

4682 Jps

2654 DataNode

 

 

 

 

 

 

 

 

 

五、【案例:二次排序】

name      money

zhangsan  125

lisi      135

wangwu   60

zhangsan   56

wangwu     80

lisi      650

zhangsan  50

wangwu     6

lisi     900

 

二次排序:第一次排要求按照姓名的首字母进行排

  第二次排序要求按照同一个人的消费金额进行排

 

分析实现的思路

key#value  value

 

统计结果

lisi   135

lisi   650

lisi   900

wangwu  6

wangwu  60

wangwu   80

zhangsan  50

zhangsan  56

zhangsan  125

 

使用默认分组 PairWritable

lisi,900 [ 900 ]

lisi,650 [ 650 ]

lisi,135 [ 135 ]

wangwu,80 [ 80 ]

wangwu,60 [ 60 ]

wangwu,6 [ 6 ]

zhangsan,125 [ 125 ]

zhangsan,56 [ 56 ]

zhangsan,50 [ 50 ]

 

使用自定义分组 PairWritable.getFisrt()

lisi,900 [ 900 650 135 ]

wangwu,80 [ 80 60 6 ]

zhangsan,125 [ 125 56 50 ]

 

.Join

 

1.map Join

适用场景:一个大表、一个小表的情况  25MB

map端,小表会被加载到处理大表的blockmap方法所在的NodeManager的内存中,具体方式是重写Mapper类的setup()方法,将小表的数据从HDFS读出来,保存到某一个变量中,在map()方法中,就可以读取到小表的数据和大表的数据,然后先进行joinjoin的结果大大减小,这样,就可以减小网络和磁盘的IO,降低reduce()方法处理数据的压力。

 

2.reduce Join

适用场景:两个大表的情况

两张表通常都是大文件,Join的操作是在Reduce端执行,由于文件过大,载入内存是不现实的,可以在发送到reduce之后再进行join.

每次在map端得到数据之后,就打一个标签将标签和数据一起发送到reduce,在reduce端根据标签和具体的业务需求完成join

 

 

3.semi Join(半连接)

适用场景:一张小表、一张大表

将小表加载到map端执行大表所在的NodeManager的内存中,map()方法执行的时候,会过滤掉无用的数据,将参与join的数据传输到reduce端,在reduce端完成真正的join过程,这种方式就是semi join,reduce join的一种特例

 

==========================================================================

reduce join实现

customer.txt

1,Stephanie Leung,555-555-5555

2,Edward Kim,123-456-7890

3,Jose Madriz,281-330-8004

4,David Stork,408-555-0000

 

order.txt

3,A,12.95,02-Jun-2008

1,B,88.25,20-May-2008

2,C,32.00,30-Nov-2007

3,D,25.02,22-Jan-2009

 

代码实现:

import java.io.DataInput;

import java.io.DataOutput;

import java.io.IOException;

 

import org.apache.hadoop.io.Writable;

 

public class CustomerOrderBean implements Writable{

private String flag;

private String data;

 

@Override

public String toString() {

return flag + "," + data;

}

 

public void set(String flag, String data) {

this.flag = flag;

this.data = data;

}

 

public CustomerOrderBean() {

}

 

public String getFlag() {

return flag;

}

 

public void setFlag(String flag) {

this.flag = flag;

}

 

public String getData() {

return data;

}

 

public void setData(String data) {

this.data = data;

}

 

public void write(DataOutput out) throws IOException {

out.writeUTF(flag);

out.writeUTF(data);

}

 

public void readFields(DataInput in) throws IOException {

this.flag = in.readUTF();

this.data = in.readUTF();

}

 

}

 

 

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

 

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.fs.Path;

import org.apache.hadoop.io.LongWritable;

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;

 

public class CustomerOrderMapReduce {

 

public static void main(String[] args) throws Exception {

Configuration configuration = new Configuration();

//1.get Job

Job job = Job.getInstance(configuration);

 

//2.set Jar

job.setJarByClass(CustomerOrderMapReduce.class);

 

//3.set Mapper

job.setMapperClass(CustomerOrderMapper.class);

job.setMapOutputKeyClass(LongWritable.class);

job.setMapOutputValueClass(CustomerOrderBean.class);

 

//3.5 set Partition

//job.setPartitionerClass(MyPartitioner.class);

//set number of Reducer

//job.setNumReduceTasks(new Integer(args[2]));

//job.setNumReduceTasks(3);

 

//3.6 set Combiner

//job.setCombinerClass(PVReducer.class);

 

//4.set Reducer

job.setReducerClass(CustomerOrderReducer.class);

job.setOutputKeyClass(LongWritable.class);

job.setOutputValueClass(Text.class);

 

//5.PathIn  PathOut

FileInputFormat.setInputPaths(job, new Path(args[0]));

FileOutputFormat.setOutputPath(job, new Path(args[1]));

 

//6.submit

job.waitForCompletion(true);

}

 

public static class CustomerOrderMapper extends Mapper<LongWritable, Text, LongWritable, CustomerOrderBean>{

CustomerOrderBean bean = new CustomerOrderBean();

LongWritable k = new LongWritable();

@Override

protected void map(LongWritable key, Text value, Context context)

throws IOException, InterruptedException {

String[] split = value.toString().split(",");

/**

 * 数组的长度等于3的时候,说明是customer表的数据

 * 1,Stephanie Leung,555-555-5555

 */

if (split.length == 3) {

bean.set("customer", split[1]+","+split[2]);

k.set(Long.valueOf(split[0]));

context.write(k, bean);

}

/**

 * 说明是order表 的数据

 * 3,A,12.95,02-Jun-2008

 */

if (split.length == 4) {

bean.set("order", split[1]+","+split[2]+","+split[3]);

k.set(Long.valueOf(split[0]));

context.write(k, bean);

}

}

}

 

/**

 * key:value

 * 1:{(customer,Stephanie Leung,555-555-5555)(order,B,88.25,20-May-2008)}

 * ...

 * ...

 */

public static class CustomerOrderReducer extends Reducer<LongWritable, CustomerOrderBean, LongWritable, Text>{

Text v = new Text();

@Override

protected void reduce(LongWritable key,

Iterable<CustomerOrderBean> iterable,

Context context)

throws IOException, InterruptedException {

 

String customerStr = null;

List<String> orderList = new ArrayList<String>();

 

for (CustomerOrderBean bean : iterable) {

String flag = bean.getFlag();

//如果flag等于customer说明是customer表的数据

if (flag.equals("customer")) {

//customerStr = "Stephanie Leung,555-555-5555";

customerStr = bean.getData();

}else {

//"B,88.25,20-May-2008"

orderList.add(bean.getData());

}

}

 

/**

 * Join过程

 */

for (String orderData : orderList) {

v.set(customerStr+","+orderData);

context.write(key, v);

}

}

}

}

 

结果

1       Stephanie Leung,555-555-5555,B,88.25,20-May-2008

2       Edward Kim,123-456-7890,C,32.00,30-Nov-2007

3       Jose Madriz,281-330-8004,D,25.02,22-Jan-2009

3       Jose Madriz,281-330-8004,A,12.95,02-Jun-2008

=================================================

map读取源文件时,如何区分出是File1还是File2

 

joinMapper()<>{

FileSplit fileSplit = (FileSplit)context.getInputSplit();  

  String path =  fileSplit.getPath().getname().toString();  

path文件来源路径+文件名

if(path.contains("tab1")){

数据来源于File1

按指定字符区切分

String strs = valuse.split("\t");

mapoutkey.set(strs[0])

mapoutvalue.set("tag1"+strs[1,]+"\t"+...)

context.write(mapoutkey,mapoutvalue)

}

if(path.contains("tab2")){

数据来源于File2

按指定字符区切分

String strs = valuse.split("\t");

mapoutkey.set(strs[0])

mapoutvalue.set("tag2"+strs[1,]+"\t"+...)

context.write(mapoutkey,mapoutvalue)

}

 

补充:

3hadoop2.xHadoop1.x区别:

 

12.x1.x从性能上有很大增强

2Hadoop1中的JobTracker是一个功能集中的部分,负责资源的分配和任务的分配,所以JobTracker单点出问题就会造成整个集群无法使用了,而且MapReduce模式是集成在Hadoop1中,不易分解;Hadoop2中,ResourceManager(RM)就是负责资源的分配,NodeManager(NM)是从节点上管理资源的,而ApplicationMaster(AM)就是一个负责任务分配的组件,根据不同的模式有不同的AM,因此MapReduce模式有自己独有的AM;

31.x版本没有Namenode Federation功能,只能有一个NameNode;而2.x添加了,还可以有多个NameNode同时运行,每个负责集群中的一部分 (41.x版本没有Namenode Ha功能,只能有一个NameNode;而2.x添加了,解决了namenode单点故障问题 (5)解决对MapReduce之外的框架支持问题。

 

4HDFS数据安全性如何保证

1)、存储在HDFS系统上的文件,会分割成128M大小的block存储在不同的节点上,block的副本数默认3份,也可配置成更多份;

2)、第一个副本一般放置在与client(客户端)所在的同一节点上(若客户端无datanode,则随机放),第二个副本放置到与第一个副本同一机架的不同节点,第三个副本放到不同机架的datanode节点,当取用时遵循就近原则;

3)datanodeblock为单位,每3s报告心跳状态,做10min内不报告心跳状态则namenode认为block已死掉,namonode会把其上面的数据备份到其他一个datanode节点上,保证数据的副本数量;

4)datanode会默认每小时把自己节点上的所有块状态信息报告给namenode

5)、采用safemode模式:datanode会周期性的报告block信息。Namenode会计算block的损坏率,当阀值<0.999f时系统会进入安全模式,HDFS只读不写。 HDFS元数据采用secondaryname备份或者HA备份

 

6MapReduce运行流程?

1).首先对输入数据源进行切片

2).master调度worker执行map任务

3).worker读取输入源片段

4).worker执行map任务,将任务输出保存在本地

5).master调度worker执行reduce任务,reduce worker读取map任务的输出文件

6).执行reduce任务,将任务输出保存到HDFS

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

==================================总结===============================

 

1.Hadoop是什么、生态系统组件功能?

 

  :1).Hadoop是一个能够对大量数据进行分布式处理的软件框架。具有可靠、高效、可伸缩的特点。

     2).HDFS,MapReduce,Hive,ZooKeeper,Yarn

 

2.简要叙述一下YARN的功能、如何分配资源调度应用的,以运行MapReduce WordCount程序为例。

 

  答:1.clientyarn提交job,首先找ResourceManager分配资源(CPU 内存)

      2.ResourceManager开启一个Container,Container中运行一个Application manager

      3).Application manager找一台nodemanager启动Application master,计算任务所需的计算

      4).Application masterApplication managerYarn)申请运行任务所需的资源

      5).Resource scheduler将资源封装发给Application master

      6).Application master将获取到的资源分配给各个nodemanager

      7).各个nodemanager得到任务和资源开始执行map task

      8).map task执行结束后,开始执行reduce task

      9).map taskreduce task将执行结果反馈给Application master

      10.Application master将任务执行的结果反馈Application manager

 

    如:单词统计,分隔符是\t

hadoopmapreduce

sparkstorm

maphadoopmapreduce

reducestormhadoop

hbasemapstorm

 

$map 输入

$按行读取数据,然后转换成key-value  key 为偏移量  value为这一行数据

<0,hadoopmapreduce>

<13,sparkstorm>

<24,maphadoopmapreduce>

<41,reducestormhadoop>

<52,hbasemapstorm>

** map 输出

<hadoop,1> <mapreduce,1> <spark,1> <storm,1> <map,1> <hadoop,1>  ...

$ 中间结果临时存储在本地目录,而非HDFS

 

$ reduce

$ 从相关nodemanager拉取map输出的结果

$ 运行reduce函数

$ 输入 reduce 的输入就是Map的输出

<hadoop,(1,1,1)> <storm,(1,1,1)> <hbase,1> ...

$ 输出

hadoop3

storm3

hbase1  ...

 

$ 结果写入HDFS

hadoop3

storm3

hbase1  ...

 

3.描述MapReduce中的mapreduce执行过程?

 

  答:MapReduce分布式并行计算框架,分而治之的思想 编程模型

1.一个简单的MapRedcue包含两个过程,一个Map阶段(map 映射),一个Reduce(化简)阶段

2.第一个阶段Map Task,并发的各司其职的读取,完全并行

3.第二个阶段Redcue Task,处理的数据要依赖于map阶段  reduce个数少于map个数

4.整个过程是以key value形式进行数据传递

 

input/input)   -》  Map Task -Reduce task -output(/out)

 

4.HDFS HA集群中,ZooKeeper作用是什么?JournalNode作用是什么?由谁负责fsimageedits文件的合并工作,并且是如何合并的?

 

  答:1.Zookeeper  (文件系统 角色 选举机制 watch

      $NameNode启动,然后向Zookeeper,触发注册事件,同时会创建一个唯一的目录

      $通过心跳信息,来确认节点的状态(存活或者宕机)

      $如果宕机,失去心跳信息,触发节点丢失事件,删除这个目录

 

     2).两个NameNode为了数据同步,会通过JournalNodes的进程进行相互通信。当active状态的NameNode的命名空间有任何修改时,会告知大部分的JournalNodes进程。standby状态的NameNode有能力读取JNs中的变更信息,并且一直监控edit log的变化,把变化应用于自己的命名空间。standby可以确保在集群出错时,命名空间状态已经完全同步。

 

     3).SecondaryNameNode.合并流程:当开始合并的时候,SecondaryNameNode会把fsimageedits复制到自己服务器的内存中,开始合并,合并后生成一个叫fsimage.ckpt*的文件。将fsimage.ckpt*文件复制到NameNode上,成功后将原有的fsiamge删除,并将fsimage.ckpt*文件重新命名fsimage。当Secondarynamenodeeditsfsimage拷贝走之后,NameNode会立刻生成一个edits.new文件,用于记录新来的元数据,当合并完成之后,原有的edits文件才会被删除,并将edits.new文件重命名为edits文件。

 

5.HDFS的存储机制是什么及如何保证数据安全性?

 

  答:遵循:一次写入多次读取,就近原则

    $ 第一个副本放在运行客户端程序的节点,如果该节点位于集群外,就随机选择一个节点

$ 第二个副本放在和第一个副本不同机架的随机节点

$ 第三个副本放在与第二副本同一机架的随机节点

$ 如果需要存放其他副本,则在集群中随机选择其他节点,系统会尽量避免过多副本集中在同一个机架的现象

 

6.简要描述如何安装配置一个Apache开源版的Hadoop2.5.0版本),完全分布式,列出步骤及注意点

 

  答:Hadoop分布环境搭建的步骤:

   1.环境准备(同时要规划节点)

      静态Ip地址的配置(包括DNS

      主机名称的更改

      配置所需的映射

      防火墙的关闭

      各节点规划是否合理

      创建一个普通用户。

   2.JDK的安装

        环境的配置

        # vi /etc/profile(root用户)

   3.hadoop的安装(实际上就是在对应的目录下解压安装)

       环境的配置

        hadoop-env.sh  mapred-env.sh  yarn-env.sh

       文件的配置

        hdfs-site.xml  core-site.xml  mapred-site.xml  yarn-site.xml

       格式化(在没有报错的时候)

        $ bin/hdfs namenode -format  

       在命令行开启相对应的进程

        Jps检查是否开启

       测试环境是否存在问题

         Web

       http://对应的IP地址或主机名:50070/  HDFS中的文件或目录显示是否正常(默认会有tmp目录,

       如果没有可以通过新建一个目录来查看)

       http://对应的IP地址或主机名:8088/

 

7.现有如下文件:trans.txt,账号,时间(yyyy-MM-dd),金额

  请简要说明一下如何使用MapReduce,得到按账号升序,账号年消费额降序排列的结果文件?

    1,2015-02-13,234.45

    1,2015-04-12,56778

    2,2016-12-03,45.32

    ...

 

  答:选用Join

    map阶段:

       map task依次读取两个文件,切割,并设置keyvalue,cidkey,同时给文件的value打一个标签,及判定为日期在前面打上d(后续按升序排序),判定为消费额在前面打上m(后续按降序排序)。

    reduce阶段:

       将相同keyValue合并放在一起。

 

8.描述MapReduce中的二次排序的思路

 

  答:  $ MapReduce特性:自动对key进行排序

$ 把需要排序的第一字段和第二字段组合成一个新的key

    (可选)

$ 修改分区规则--针对原始key进行分区

$ 修改分组规则--针对原始key进行分组

    具体实现:

$ 自定义Key数据类型,实现WritableComparable接口

    (可选)

$ 自定义分区函数类,实现Partitioner接口

$ 自定义分组类

$ 继承WritableComparator

$ 继承RawComparator接口

 

9.分别描述namenodedatanodesecondnamenode的作用

 

  答:1).namenode 是资源(内存、CPU等)的管理者负责资源的调度。同时管理文件系统的元数据,及块和节点之间的关系,用户对文件的操作信息。

      2).每个集群节点均有一个从属DataNode,它为读/写请求提供服务以及按照NameNode的指令执行数据块创建、删除和复制。

      3).secondnamenode的整个目的是在HDFS中提供一个检查点。它只是namenode的一个助手节点。及负责fsimageedits文件的合并操作。

  

10)描述HDFSblock的存放策略,以及按自己的理解说出该策略的优点。

 

   答:1.采用block之后文件可以非常大,因为block可以存储在集群上的任一台机器上。(这样就具有了分布式文件系统的基础,比如可以做负载平衡,可以做冗余以避免文件的损坏或机器故障等。)

       2.存储子系统的职责单一化。(只负责block的读写,文件的权限控制等可由其它系统负责。)

       3.采用replication策略实现高可用性更适宜。(当某个block不可访问时,HDFS将自动复制相应的块从而维持备份的次数。)

       4.方便于管理(备份、恢复、删除)。   

       5.提高文件的读写速度。

       6.减轻cpu和内存的压力。

       7.适合处理比较大的文件。(小文件不占优势)

       

 

 

 

 

 

posted @ 2017-07-05 18:40  茗羽阁  阅读(922)  评论(0编辑  收藏  举报