Hadoop学习笔记
Hadoop的整体框架
Hadoop由HDFS、MapReduce、HBase、Hive和ZooKeeper等成员组成,最重要的两个组成元素是HDFS(底层用于存储集群中所有存储节点文件的文件系统)和MapReduce(上层用来执行MapReduce程序的MapReduce引擎)。
Pig是一个基于Hadoop的大规模数据分析平台
Chukwa是基于Hadoop的集群监控系统
hive是基于Hadoop的一个工具,提供完整的sql查询功能,可以将sql语句转换为MapReduce任务进行运行
ZooKeeper:高效的,可扩展的协调系统,存储和协调关键共享状态
HBase是一个开源的,基于列存储模型的分布式数据库
HDFS是一个分布式文件系统。有着高容错性的特点,并且设计用来部署在低廉的硬件上,适合那些有着超大数据集的应用程序
MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算
下图是一个典型的Hadoop试验集群的部署结构 和 Hadoop各组件之间是如何依赖共存
HDFS工作原理:(Client文件获取、NameNode文件管理和DataNode文件存储)
文件写入:
1、 Client向NameNode发送写入请求
2、 NameNode根据文件大小和文件块配置情况,返回给Client其管理部分的DataNode的信息
3、 Client将文件划分为多个文件,根据DataNode的地址信息,按顺序写入每一个DataNode块中。
文件读取:
1、 Client向NameNode发送读取请求
2、 NameNode返回文件存储信息的DataNode信息
3、 Client读取文件信息
MapReduce工作原理:(Map任务的分解和Reduce 结果的汇总)
MapReduce的核心是Map(映射)和Reduce(化简)。
Map函数:接受一个键值对,产生一组中间键值对。Map/Reduce框架会把Map函数产生的键值对里的键相同的value传递给一个Reduce函数。
Reduce函数:接受一个键和相关的一组值,将这组值合并成规模更小的值(通常只有一个或零个值)。
PS:MapReduce的前提条件(1)待处理的数据集可以分解成许多小的数据集(2)而且每一个小数据集都可以完全并行地进行处理
Hadoop的安装配置(伪分布式)
1、 准备安装文件Centos7
2、 Linux系统设置
1) 修改IP地址
2) Ip绑定,修改主机名,安装jdk
3) 关闭防火墙systemctldistable iptables
4) SSH免密登录:
<1>生成密钥:ssh-keygen –t rsa ,生成文件位于用户目录下的.ssh文件中(.ssh为隐藏文件,可以通过ls -a查看)
<2>免密命令:cp id_rsa.pub authorized_keys
<3>查看ssh localhost
(生成方式)
ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys
3、 安装Hadoop
1) 解压Hadoop文件
2) 配置环境变量/etc/profile执行source /etc/ptofile
3) 修改Hadoop的配置文件,它们位于$HADOOP_HOME/etc/hadoop目录下的hadoop-env.sh、core-site.xml、hdfs-site.xml.template、mapred-site.xml
修改hadoop-env.sh文件:
EXPORTJAVA_HOME=jdk的路径
如果内存低于1G,则修改EXPORTHADOOP_HEAPSIZE=100
修改core-site.xml文件:
在configuration中添加以下配置:
<property>
<name>fs.default.name</name>
<value>hdfs://主机ip:9000</value>
<description>change your own hostname</description>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/usr/local/hadoop/tmp</value>
</property>
修改hdfs-site.xml文件:
在configuration中添加以下配置文件:
<name>dfs.namenode.name.dir</name>
<value>file:/usr/local/hadoop/hdfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:/usr/local/hadoop/hdfs/data</value>
</property>
<name>dfs.replication</name>
<value>1</value>
</property>
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
修改mapred-site.xml.template文件:
<property>
<name>mapred.job.tracker</name>
<value>hadoop-master:9001</value>
<description>change your own hostname</description>
</property>
4、 初始化Hadoop:hadoopnamenode –format
5、 启动Hadoop:
1)一次性启动所有的进程:start-a/ill.sh
2)单独启动HDFS和MapReduce:start-dfs.sh和 start-mapred.sh
3)分别启动各个进程:
hadoop-daemon.sh start namenode
hadoop-daemon.sh start datanode
hadoop-daemon.sh start econdarynamenode
hadoop-daemon.sh start jobtracker
hadoop-daemon.sh start tasktracker
一、高大上的MapReduce
1.1 MapReduce介绍
MapReduce的思想就是“分而治之”。
(1) MapReduce负责“分”,把复杂的任务分解成若干个“简单的任务”进行处理。“简单任务”有三层含义:一是数据或者计算规模相比原来要大大的减少;二是就近计算原则,任务分配到所需的数据节点上计算;三是小任务可以并行计算,相互之间没有依赖关系。
(2) Reduce负责对Map阶段的结果进行汇总。Reduce的个数,修改mapred-site.xml的mapred.reduce.tasks参数,默认值1
1.2 MapReduce工作机制
上图的MapReduce工作机制包含四个实体
实体一:客户端,用来提交MapReduce作业
实体二:JobTracker,用来协调作业的运行
实体三:TaskTrack,处理作业划分后的任务
实体四:HDFS,用来在其他实体间共享作业文件
整个工作过程中有如下的工作环节
环节一:作业的提交
环节二:作业的初始化
环节三:作业的分配(TaskTracker)
环节四:作业的执行(Mapper Reducer)
环节五:进程与状态的更新
环节六:作业的完成
MapReduce输入和输出均是<key, value>键值对
1.3MapReduce的处理流程
以单词计数为例,统计一个文本中的每个单词出现的次数。
(1) Map任务处理
(2) Reduce任务处理
二、第一个MapReduce程序:WordCount
WordCount单词计数主要完成的功能是:统计一系列文本文件中每个单词出现的次数
2.1初始化word.txt并上传到HDFS
创建一个文件,内容:
Hello Edison Chou
Hello Hadoop RPC
Hello Wncud Chou
Hello Hadoop MapReduce
Hello Dick Gu
通过Shell命令将其上传到一个指定目录中,这里指定为:/hadoop/input
2.2自定义Map函数
在Hadoop中,Map函数位于内置类org.apache.hadoop.mapreduce.Mapper<KETIN,VALUEIN,KEYOUT,VALUEOUT>中,Reduce函数位于内置类org.apache.hadoop.mapreduce.Reduce<KETIN,VALUEIN,KEYOUT,VALUEOUT>中。
重写map函数:
public static class MyMapperextends Mapper<LongWritable,Text,Text,LongWritable> {
protected void map(LongWritable key,Textvalue,Mapper<LongWriteable,Text,Text,LongWritable>.Context context)
throwsIOException, InterruptedException {
String[] splitedArr = value.toString().split(“ ”);//map函数中通过空格符分隔文本内容
for(String word:splitedArr) {
context.write(new Text(word), new LongWritable(1L));
}
}
}
重写reduce函数:
public voidclass MyReducerextends Reducer<Text,LongWritable,Text,LongWritable> {
protectedvoidreduce(Textkey,Iterable<LongWritable>values,Reducer<Text,LongWritable,Text,LongWritable>context)throws IOException,InterruptedException{
long count = 0L;
for(LongWritable value:values) {
count += value.get();
}
context.write(key, new LongWritable(count));
}
}
2.3设置Main函数
在Main函数中,主要做了三件事:一是指定输入、输出目录;二是指定自定义的Mapper类和Reducer类;三是提交作业。
1、设定输入目录(或者以参数形式输入)
public static final String INPUT_PATH = "hdfs://hadoop-master:9000/hadoop /input/words.txt";
2、设定输出目录(必须是空目录)
public static final String OUTPUT_PATH = "hdfs://hadoop-master:9000/ hadoop/output/wordcount";
3、Main函数主要代码:
publicstaticvoid main(String[] args) throws Exception {
Configuration conf = new Configuration();
// 0.0:首先删除输出路径的已有生成文件
FileSystem fs = FileSystem.get(new URI("hdfs://hadoop-master:9000"),conf);
Path outPath = new Path(OUTPUT_PATH);
if (fs.exists(outPath)) {
fs.delete(outPath, true);
System.out.println("存在此输出路径,已删除!!!");
}
Job job = Job.getInstance(conf,"WordCount");
job.setJarByClass(WordCount.class);
// 1.0:指定输入目录
FileInputFormat.setInputDirRecursive(job,true);
FileInputFormat.addInputPath(job, new Path(INPUT_PATH));
// 1.1:指定对输入数据进行格式化处理的类(可以省略)
job.setInputFormatClass(TextInputFormat.class);
// 1.2:指定自定义的Mapper类
job.setMapperClass(MyMapper.class);
// 1.3:指定map输出的<K,V>类型(如果<k3,v3>的类型与<k2,v2>的类型一致则可以省略)
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(LongWritable.class);
// 1.4:分区(不可以省略),如果省略,就会出问题。
// Type mismatch in key from map: expected org.apache.hadoop.io.Text, received org.apache.hadoop.io.LongWritable
job.setPartitionerClass(HashPartitioner.class);
// 1.4:指定自定义的Reducer类
job.setReducerClass(MyReducer.class);
// 1.5:指定reduce输出的<K,V>类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(LongWritable.class);
// 1.6:指定输出目录
FileOutputFormat.setOutputPath(job, outPath);
// 1.7:指定对输出数据进行格式化处理的类(可以省略)
job.setOutputFormatClass(TextOutputFormat.class);
// 1.8:提交作业 boolean success = job.waitForCompletion(true);
if (success) {
System.out.println("Success");
System.exit(0);
} else {
System.out.println("Failed");
System.exit(1);
}
}
三、搭建windows的Hadoop开发环境
3.1环境准备
系统环境:windows 7 或者windows 10
Java环境:jdk 1.8及以上
IDE工具:idea 2017
其他软件:Hadoop 2.8.0 、hadoop-common-2.2.0-bin-master.zip
3.2 配置环境
(1)将Hadoop 2.8.0解压,用hadoop-common-2.2.0-bin-master.zip中的对应版本的bin替换Hadoop中的bin目录。在环境变量通添加HADOOP_HOME,在path中添加%HADOOP_HOME%\bin。重启电脑,使之生效。
(2)a. 在CentOS7 的/目录下创建testFile目录,新建文件words.txt文件填写内容。
b. 创建输入目录mkdir –R /hadoop/input,添加到hadoop中:hadoop fs –mkdir /hadoop/input
c. 查看输入目录:hadoopfs –ls /hadoop/input
d.将words.txt上传到输入目录中:hadoopfs –put /testFile/words.txt /hadoop/input
e. 创建输出目录mkdir/hadoop/output,添加到hadoop 中:hadoop fs –mkdir /hadoop/output
(3)配置idea的环境:
配置项目的hadoop的jar包(在hadoop的etc/hadoop下)
配置项目执行结果输出
配置项目运行的参数(参数作用是,输入目录args[0]、输出目录 agrs[1])
3.3注意事项
代码中有一个分区的设置,必须设置,否则程序会报错:
分区(可以省略),如果省略,就会出问题。Type mismatch in key from map: expected org.apache.hadoop.io.Text, received org.apache.hadoop.io.LongWritable
job.setPartitionerClass(HashPartitioner.class);