大数据学习理解前言

为什么学习大数据,第一方面是对编程这方面感兴趣,我希望通过我的逻辑,去实现代码,来创造出价值,然后供我恰饭。世界上最美好的事情是,做自己爱做的事情,并且能够赚到钱,然后可以恰饭,仅此而已。

Hadoop入门学习

Hadoop的思想之源来自于Google的三篇论文:

GFS —> HDFS

Map-Reduce —> MR

BigTable —> HBase。

Hadoop三大发行版本

Hadoop三个发行版本:Apache、Cloudera、Hortonworks

​ Apache版本最原始(最基础)的版本,对于入门学习最好。

​ CLoidear在大型互联网企业中用的较多。

​ Hortonworks文档最好。

Hadoop的优势(4高)

高可靠性:Hadoop底层维护多个数据副本,默认为3个,所以即使Hadoop某个计算元素或者存储出现故障,也不会导致数据丢失。

高扩展性:在集群间分配任务数据,可方便扩展数以千计的节点。

高效性:在MapReduce,Hadoop的并行工作的,以加速任务处理。

高容错性:能够自动将失败的任务重新分配。

Hadoop1.x和2.x区别

把资源调用又抽象出来,抽出一个yarn

简单说明Hadoop各个模块作用

基础模块:

  • HDFS:大数据量的处理

  • MapReduce:大量数据的计算,和业务有关。Map负责拆数据,reduce负责合数据

  • Yarn:负责资源的调度,分配每个job的执行,所需要的资源

  • Common:通用的一些程序

拓展模块:

  • Hive:对MapReduce封装,可以利用”sql”来运行任务,注意这里的sql是打引号的。后面具体再说!
  • Hbase:对hdfs的封装,支持增删改查
Hadoop各个模块说明

HDFS:

  • NameNode:存储文件的元数据,如,文件名称,文件目录结构,文件属性(文件大小,所属权限,副本数…),以及每个文件对应的块列表和DataNode,等。所以,理论只有一个。
  • DataNode:在本地文件系统存储文件块信息,校验…。所以理论每个服务器都会有一个DataNode
  • Secondary NameNode(2nn):用来监控HDFS状态的辅助后台程序,每隔一段时间获取HDFS的元数据。我把他理解成专门辅助NameNode的一个程序,防止NameNode挂掉就GG了,毕竟NameNode存放着文件重要的元数据。

Yarn:

比较复杂的分配资源,详细看下图

我们尝试去理解下各个模块的意思,可能有错误,但是后续会慢慢的理解。

  • ResourceManager:对Yarn上的模块进行管理分配,是一个leader。所以理论只有一个leader。
  • NodeManager:管理本节点的资源,所以,理论一个Hadoop应该会有一个。
  • ApplicationMaster:正如名称:Application,对MR的job的申请,和任务的执行做出处理。
  • Container:一个资源总的抽象模块

MapReduce:

Map阶段:并行处理数据,主要先Map运行完毕才会执行Reduce。

Reduce阶段:对Map的结果进行汇总

下载Hadoop

下载地址:

1
https://archive.apache.org/dist/hadoop/common/hadoop-2.7.2/

下载完解压、配置环境变量。目前Hadoop流行版本就是2.7

注意配置的是bin和sbin

Hadoop本地运行模式

Grep案例

创建测试输入目录

1
mkdir input

复制配置文件到输入目录中

1
cp etc/hadoop/*.xml input

执行hadoop官方案例

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

hadoop-mapreduce-examples-2.7.2.jar是hadoop本地的测试案例

grep是执行哪个官方案例,input是输入目录,output是输入目录,后面是正则表达式

最终结果:

1
1       dfsadmin
WordCount案例

创建测试目录

1
mkdir wcinput

进入测试目录,创建文件

1
touch wc.input

在文件里写入内容,这里我用的是自己的日志文件,就不放出来了,然后执行命令

1
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.2.jar wordcount wcInput wcoutput

最终结果就是计算出所有英文出现的次数,这里就不放出结果了。

Hadoop伪分布式模式运行

配置文件+启动hdfs

需要修改3个配置文件。

获取当前java路径,配置进etc/hadoop/hadoop-env.sh脚本里

1
2
# The java implementation to use.
export JAVA_HOME=/usr/local/jdk1.8.0_231

配置nameNode地址和hadoop产生文件地址,在etc/hadoop/core-site.xml里

1
2
3
4
5
6
7
8
9
10
11
<!-- 指定HDFS中NameNode的地址 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://hadoop101:9000</value>
</property>

<!-- 指定Hadoop运行时产生文件的存储目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/module/hadoop-2.7.2/data/tmp</value>
</property>

配置副本数,etc/hadoop/hdfs-site.xml

1
2
3
4
5
<!-- 指定HDFS副本的数量 -->
<property>
<name>dfs.replication</name>
<value>1</value>
</property>

格式化nameNode

1
hdfs namenode -format

启动namenode

1
sbin/hadoop-daemon.sh start namenode

启动datanode

1
sbin/hadoop-daemon.sh start datanode

jsp查看进程看是否启动成功,然后访问页面,注意关闭防火墙

1
ip:50070
基础操作命令

核心操作文件命令,前缀是hdfs dfs ….,后面命令和linux差不多

如创建文件夹,在后台页面的Browse Directory可以看到

1
hdfs dfs -mkdir -p /temp/input

上传文件

1
hdfs dfs -put 本地路径 hdfs路径
hadoop运行模式下的启动官方案例

其实,和上面的没什么区别,不过路径变为hdfs路径了

1
jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.2.jar wordcount /temp/input /temp/output

最终的输出也会在hdfs下面看到。

启动yarn并运行mapReduce

修改配置文件,修改etc/hadoop/yarn-env.sh

1
2
# some Java parameters
export JAVA_HOME=/usr/local/jdk1.8.0_231

修改yarn-site.xml,地址填我们的本地地址

1
2
3
4
5
6
7
8
9
10
11
<!-- Reducer获取数据的方式 -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>

<!-- 指定YARN的ResourceManager的地址 -->
<property>
<name>yarn.resourcemanager.hostname</name>
<value>ip</value>
</property>

配置mapred-env.sh

1
export JAVA_HOME=/usr/local/jdk1.8.0_231

配置mapred-site.xml

1
2
3
4
5
<!-- 指定MR运行在YARN上 -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>

启动ResourceManager

1
sbin/yarn-daemon.sh start resourcemanager

启动NodeManager

1
sbin/yarn-daemon.sh start nodemanage

yarn后台访问地址

1
ip:8088

我们跑一个官方案例,yarn后台是能看到记录的,这里就不上图片了,麻烦。我们还能看到历史运行情况,但是我们需要配置一下文件。

在配置mapred-site,xml增加

1
2
3
4
5
6
7
8
9
10
<!-- 历史服务器端地址 -->
<property>
<name>mapreduce.jobhistory.address</name>
<value>hadoop101:10020</value>
</property>
<!-- 历史服务器web端地址 -->
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>hadoop101:19888</value>
</property>

启动历史服务器

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

这里直接点击job后面的history就能进到后台页面。我们看到了关于这个任务的基本信息。但是想看到详细的日志运行信息,需要在启动一个服务。

配置文件yarn-site.xml增加

1
2
3
4
5
6
7
8
9
10
11
<!-- 日志聚集功能使能 -->
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>

<!-- 日志保留时间设置7天 -->
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>604800</value>
</property>

我们需要重启yarn所有服务,先stop

1
2
3
sbin/yarn-daemon.sh stop resourcemanager
sbin/yarn-daemon.sh stop namemanager
sbin/mr-jobhistory-daemon.sh stop historyserver

在启动即可。我们重新运行一下官方案例,再点击web端的log就能看到详细的运行日志信息。

Hadoop完全分布模式运行

搭建Linux集群

我们服务器很多,需要改配置的地方很多,不可能一个服务器一个服务器操作,所以需要搭建集群分发脚本,改好的配置文件,一个命令cp过去就行。具体的搭建教程,在我的博客【Linux搭建项目】里。

修改配置文件

我们修改配置文件之前,需要合理的分配资源,就是哪个服务器搭建什么项目,比如namenode,datanode怎么分配。这些是通过配置文件去控制的。所以我们需要知道这些模块的作用,在上面简单复习下。

配置Hadoop核心文件:

vi core-site.xml,我们指定NameNode地址,就像是分布式的注册中心,我们指定了一个注册中心,注册了上去,交给注册中心去管理。

1
2
3
4
5
6
7
8
9
10
11
<!-- 指定HDFS中NameNode的地址 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://hadoop01:9000</value>
</property>

<!-- 指定Hadoop运行时产生文件的存储目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/module/hadoop-2.7.2/data/tmp</value>
</property>

配置Hadoop的env脚本

vi hadoop-env.sh,一般都是设置JAVA_HOME

小提示:echo ${JAVA_HOME}可以取到设置java环境变量的值

1
export JAVA_HOME=/opt/module/jdk1.8.0_251

配置HDFS

vi hdfs-site.xml,设置副本数,和辅助的2nn

1
2
3
4
5
6
7
8
9
10
11
<!-- 指定Hadoop副本数 -->
<property>
<name>dfs.replication</name>
<value>3</value>
</property>

<!-- 指定Hadoop辅助名称节点主机配置 -->
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>hadoop03:50090</value>
</property>

配置Yarn脚本:

vi yarn-env.sh,还是设置JAVA_HOME

1
export JAVA_HOME=/opt/module/jdk1.8.0_251

配置Yarn配置文件:

vi yarn-site.xml,这里设置Reduce获取数据的方式,和yarn的lerder的地址,我们设置一个就好了,这里我们可以发现,为什么NameNode和ResourceManager单独设置一个ip,就是指定类似注册到这个服务器中,由这个leader来管理。

1
2
3
4
5
6
7
8
9
10
11
<!-- Reducer获取数据的方式 -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>

<!-- 指定YARN的ResourceManager的地址 -->
<property>
<name>yarn.resourcemanager.hostname</name>
<value>hadoop02</value>
</property>

配置MapRed脚本

vi mapred-env.sh,一样是配置JAVA_HOME

1
export JAVA_HOME=/opt/module/jdk1.8.0_251

配置MapRed xml文件

这里步骤多一点,复制模板,在修改文件,然后是指定MR运行在yarn上就ok了

cp mapred-site.xml.template mapred-site.xml

vi mapred-site.xml

1
2
3
4
5
<!-- 指定MR运行在Yarn上 -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>

指定MR运行在Yarn上这是什么意思呢?个人理解MR计算,需要调用资源,当然是交给yarn呢!!!

总结下:

我们三台服务器,所以每个服务器运行不同的模块

  • Hadoop01:NameNode、DataNode、NodeManager
  • Hadoop02:DataNode、ResourceManager、NodeManager
  • Hadoop03:DataNode、SecondaryNameNode、NodeManager

表格形式:

Hadoop01 Hadoop02 Hadoop03
HDFS NameNode、DataNode DataNode SecondaryNameNode、DataNode
YARN NodeManager ResourceManager、NodeManager NodeManager
集群的启动

一般我们是一台一台启动,这样太慢,hadoop自带集群启动脚本。

配置启动服务器配置:

vi ${HADOOP_HOME}/etc/hadoop/slaves,把服务器地址填进去,注意,不能有空格,否者报错。然后分发到其他服务器

1
2
3
hadoop01
hadoop02
hadoop03

启动之前需要格式化下NameNode

1
bin/hdfs namenode -format

然后启动hdfs

1
sbin/start-dfs.sh

启动yarn

注意我们的ResourceManager在哪台服务器上,就在哪台服务器启动

1
sbin/start-yarn.sh

这样就启动起来了

1
ip:50070访问后台

可以看到后台的服务都上去了

linux集群时间同步

我们linux集群执行定时任务的时候,如果时间不同步,肯定会出现问题,所以我们需要同步时间的应用【ntp】,和linux自带的定时任务【corntab】同步脚本。具体查看,在我的博客【Linux搭建项目】里。

HDFS学习

为什么需要HDFS

我们一个系统无法满足数据的存储,我们需要把数据分配到各个磁盘里去,所以我们需要一个系统来管理对台服务器上的数据,这就是分布式管理系统,HDFS就是分布式文件管理系统,不过是文件分布式管理系统的一种。

HDFS的定义

一个分布式的文件系统,就是由很多系统来实现文件管理。适合一次写入多次读出,文件已经存入无法修改,他的目录信息,和具体块的数据是分开的。

HDFS优缺点

优点:

高容错性,可插拔数据,自动同步副本数据,就算挂一个,也会很快的同步一个副本数据。可以建立在廉价的数据上去。并且是个处理GB、TB、PB大量的数据。

缺点:

无法像传统关系型数据库一样进行低延迟的数据访问,这个涉及到实时处理,后面再说。

小文件太多的话影响查询效率,因为HDFS是要存放一个文件的元数据,不管文件多大,存放的元数据大小都是差不多,如果小文件多的话,对应的元数据多,导致效率低下,小文件加起来实际并没有多少数据。

一个文件只能一个线程写,不允许多线程。

文件内容只能追加(append),不能修改。

HDFS组成架构

我们根据图片来理解一下。

NameNode:存放的是元数据,什么是元数据,文件的目录、大小、位置、在哪个副本…等等一些文件信息,所以他是一个管理者,他来分配我们请求过来的job。

DataNode:存放的是块数据,我们理解成实际的数据,既然分配的活都给NameNode干了,我就接收命令,读写就完事了。

HDFS块(block)概念

把文件分成一块一块的数据方便操作,但是实际上还是一块数据,不管多小的数据也会占一块的数据,而很大的数据也分为很多块数据。但是具体占的容量还是实际大小,个人理解这也是一个分布式。老的hadoop默认64M,新的默认128M。

HDFS Shell命令

前缀:hadoop fs -具体命令

举例:

创建多级目录

1
hadoop fs -mkdir -p /temp/demo

删除文件

1
hadoop fs -rm -r /temp

复制文件,从一个hdfs文件复制到另一个hdfs文件路径里

1
hadoop fs -cp /temp /demo

hdfs复制文件到本地

1
hadoop fs -coryToLocal /temp /demo

复制本地到hdfs

1
hadoop fs -coryFromLocal /temp /demo

上传是put、下载是get、下载多个是getmerge。我们发现除了一些特定的命令,大部分命令和linux命令没什么区别,这里我们就不多说了,以后就会慢慢熟悉了,这里不多说。下面是fs命令的帮助,看下大概都能了解了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
Usage: hadoop fs [generic options]
[-appendToFile <localsrc> ... <dst>]
[-cat [-ignoreCrc] <src> ...]
[-checksum <src> ...]
[-chgrp [-R] GROUP PATH...]
[-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]
[-chown [-R] [OWNER][:[GROUP]] PATH...]
[-copyFromLocal [-f] [-p] [-l] <localsrc> ... <dst>]
[-copyToLocal [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-count [-q] [-h] <path> ...]
[-cp [-f] [-p | -p[topax]] <src> ... <dst>]
[-createSnapshot <snapshotDir> [<snapshotName>]]
[-deleteSnapshot <snapshotDir> <snapshotName>]
[-df [-h] [<path> ...]]
[-du [-s] [-h] <path> ...]
[-expunge]
[-find <path> ... <expression> ...]
[-get [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-getfacl [-R] <path>]
[-getfattr [-R] {-n name | -d} [-e en] <path>]
[-getmerge [-nl] <src> <localdst>]
[-help [cmd ...]]
[-ls [-d] [-h] [-R] [<path> ...]]
[-mkdir [-p] <path> ...]
[-moveFromLocal <localsrc> ... <dst>]
[-moveToLocal <src> <localdst>]
[-mv <src> ... <dst>]
[-put [-f] [-p] [-l] <localsrc> ... <dst>]
[-renameSnapshot <snapshotDir> <oldName> <newName>]
[-rm [-f] [-r|-R] [-skipTrash] <src> ...]
[-rmdir [--ignore-fail-on-non-empty] <dir> ...]
[-setfacl [-R] [{-b|-k} {-m|-x <acl_spec>} <path>]|[--set <acl_spec> <path>]]
[-setfattr {-n name [-v value] | -x name} <path>]
[-setrep [-R] [-w] <rep> <path> ...]
[-stat [format] <path> ...]
[-tail [-f] <file>]
[-test -[defsz] <path>]
[-text [-ignoreCrc] <src> ...]
[-touchz <path> ...]
[-truncate [-w] <length> <path> ...]
[-usage [cmd ...]]

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

HDFS客户端(api操作)

配置开发环境hadoop环境

本人是win10环境,选择win的hadoop jar包,文件在我的git上,自己下,配置的环境和配置JAVA环境一样,这里就不多说了。

然后new一个maven环境,pom文件引入依赖文件即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>jdk.tools</groupId>
<artifactId>jdk.tools</artifactId>
<version>1.8</version>
<scope>system</scope>
<systemPath>${JAVA_HOME}/lib/tools.jar</systemPath>
</dependency>
</dependencies>

还需要引入一个日志配置文件,名称:log4j.properties

1
2
3
4
5
6
7
8
log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
hdfs客户端操作API

第一步:获取配置操作对象,这个肯定是有的,我们可以设置一些专属的配置。

1
Configuration conf = new Configuration();

这里就不演示了,直接看API,或者百度如何使用即可。

第二步:获取hdfs操作对象,也就是文件操作对象,我们我们需要传入三个参数

  • Hadoop集群地址
  • 上面的配置文件
  • 操作的用户,这个很重要,hdfs也是分用户的,和linux一样
1
FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop01:9000"), conf, "root");

第三步:操作文件对象API,进行文件操作。举例创建文件夹

1
fileSystem.mkdirs(new Path("/demo/hdfs/test"));

第四步,关闭文件对象IO

1
fileSystem.close();

我们可以发现通过文件对象API大致能知道这些API的作用,下面是图片。

简单说几个api:

copyFromLocalFile:本地上传文件,注意第一个参数是要上传的文件的路径,第二个是要上传到哪里的文件路径。

copyToLocalFile:下载文件到本地,注意第一个参数是要下载的文件的路径,第二个是要下载到哪里的文件路径。

open:参数是路径,返回的是HDFS输入流对象。

create:参数是路径,返回的是HDFS输出流对象。

其他的api看下名称即可,就不多说了。这一块虽然是重点,但是没必要都把api都过一遍,需要的时候在练习即可。

不过,值得注意的是,永远要记得一个概念,我想从hdfs下载文件到本地,那么输入流肯定是hdfs,输出流肯定是本地。反之上传的话,那么输入流肯定是本地,输出流是hdfs。这样我们自己定义一下hfds操作的api,使用open和create这两个api来进行上传下载操作。

具体的例子:

HDFS上传原理:

第一步:上传文件请求到HDFS客户端,客户端调用分布式文件系统(DistributedFileSystem),有分布式文件系统请求Name Node上传文件,正如我们说的Name Node是一个master。

第二步:Name Node响应给DistributedFileSystem,可以上传文件。

第三步:既然允许我上传,那我就请求上传第一个block,我们说过,hdfs的文件是分block(块)的,个人感觉这种架构存储,是为了分布式多处理。一个job可以处理多个block,而我们是分布式的,我处理A1服务器的block01,另一个线程处理A2服务的block02,那就很舒服的。

第四步:你请求了我上传到哪个Data Node,那我就给你,然后看看配置文件,一看你是三个副本啊(这里简单举个例子,可能有其他操作),那我给你三个Data Node节点那就ok了,如果没有3个,那就能给多少就给多少。

第五步:我接收到了给的Data Node信息,那我能干什么?当然是传数据了,我上传数据相当于什么?相当于本地往hdfs写数据啊,所以,需要FSDataOutputStream(FS输出流)对象,我写数据就完事了。我拿到FSDataOutputStream不可能直接咔咔往的Data Node里写,那我请求下看能不能写啊,于是请求建立通道

第六步:Data Node收到请求后,表示没有问题,那就应答FSDataOutputStream ok,直接来吧!

第七步:我FSDataOutputStream,收到成功信号后,那就直接传就完事了。客户端开始往第一个Data Node传第一个block(会先从本地磁盘读取数据放到本地内存缓存里),一个packet为单位,第一个Data Node传完后,第一个Data Node传第二个,第二个接收完,由第二个传第三个。第一个Data Node,每传好一个packet就会放到应答队列里等待应答。

第八步:我全部传完,要给大哥说下,于是给Name Node说我好了!!!开始请求上传第二个Block直到完成。

Zookeeper学习

Hadoop-HA学习

Hive学习

Flume学习

Kafka学习

HBase学习

Sqoop学习

Azkaban学习

Oozie学习