Hadoop的基本概念
- 处理海量数据时,为了降低成本,使用普通PC机,将硬件损坏视为常态,通过软件来保证可靠性。
- Hadoop的核心组成:
- HDFS:分布式文件系统,存储海量数据;
- MapReduce:并行处理框架,实现任务处理和调度。
- Hadoop的作用:搭建大型数据仓库,进行PB级数据处理。
HDFS
HDFS(Hadoop Distributed File System)
- HDFS文件被拆分成块进行存储,是文件存储处理的逻辑单元。每一块的默认大小为64M。
- NameNode是管理节点,存放文件元数据。包括文件与数据块的映射表,和数据块与数据节点的映射表。
- DataNode是工作节点,存放数据块
数据管理策略
- 每个数据快三个副本,分布在两个机架内的三个节点,防止硬件损坏。
- 心跳检测。DataNode定期向NameNode发送心跳消息,告知NameNode是否还处于active状态。
- 二级NameNode,定期同步NameNode元数据影像文件和修改日志,防止NameNode故障丢失。
HDFS文件读取流程
客户端向NameNode请求读取数据,NameNode返回是否存在和数据块位置,客户端据此读取。
HDFS文件写入流程
客户端将文件拆分成块,向NameNode请求写入。NameNode返回空白DataNode位置,客户端将数据块写入,流水线复制入不同机架。完成操作后通知NameNode,更新元数据。
HDFS的文件系统特点
- 有文件冗余,防止硬件故障;
- 流式的数据访问:一次写入,多次读取,不支持修改;
- 适合存储大文件,适合进行批量读写,吞吐量高。
- 不适合交互式应用,难以满足低延迟要求(和数据库形成对比),不支持多用户并发。
Hadoop不同版本的基础架构
- Hadoop1.X,由JobTracher和TaskTracker进行任务调度管理。TaskTracker执行MapReduce作业,JobTracher管理TaskTracker。 TaskTracker定期向JobTracher发送心跳。
- Hadoop2.0以后的版本移除了JobTracher和TaskTracker,改由Yarn平台的ResorceManager负责集群中所有资源的管理和分配,NodeManager负责Hadoop集群中单个计算节点。
Yarn的设计减少了JobTracher的资源消耗,也减小了Hadoop1.X中单点故障的风险。同时Spark和Storm作业也可以在Yarn平台上运行,充分利用资源。
MapReduce
Map把一个函数应用于集合中的所有成员,Reduce对结果集进行分类和归纳。Map和Reduce两个函数可能会并行运行,即使不是在同一系统的同一时刻。
MapReduce的四个阶段
* Split阶段:自动对文本进行分割
* Map阶段(代码实现):在分割之后的每一对<key, value>
进行用户自定义的Map处理,再生成新的<key, value>
对
* Shuffle阶段:对输出的结果集归拢、排序(个人认为此步骤是最关键的,也是调优的重点。)
* Reduce阶段(代码实现):通过Reduce操作生成最后结果
工作流程(WordCount举例):
- 在一个MapReduce任务中,Partitioner的数量, Reduce任务的数量, 最终输出文件的数量三者是相等的。
- 在一个Reducer中,所有数据都会被按照升序排序,所以如果part输出文件包含key值,则一定是有序的。
Shuffle过程:
- Map端Shuffle:
- Reduce端Shuffle:
WordCount源码
import java.io.IOException;
import java.util.StringTokenizer;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.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.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
public class WordCount {
public static class WordCountMap extends
Mapper<LongWritable, Text, Text, IntWritable> {
private final IntWritable one = new IntWritable(1);
private Text word = new Text();
public void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
String line = value.toString();
StringTokenizer token = new StringTokenizer(line);
while (token.hasMoreTokens()) {
word.set(token.nextToken());
context.write(word, one);
}
}
}
public static class WordCountReduce extends
Reducer<Text, IntWritable, Text, IntWritable> {
public void reduce(Text key, Iterable<IntWritable> values,
Context context) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
context.write(key, new IntWritable(sum));
}
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = new Job(conf);
job.setJarByClass(WordCount.class);
job.setJobName("wordcount");
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
job.setMapperClass(WordCountMap.class);
job.setReducerClass(WordCountReduce.class);
job.setInputFormatClass(TextInputFormat.class);
job.setOutputFormatClass(TextOutputFormat.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
job.waitForCompletion(true);
}
}
MapReduce算法及参数调优
理想的输入文件:
由于NameNode大小有限,大量的小文件会给HDFS带来性能上的问题。故HDFS适合存放整块的大文件,对于大量的小文件可以采用压缩、合并等优化策略,如设置文件输入类型为
CombineFileInputFormat
格式。关于Map任务的个数问题:
一个file被分成多个固定大小的block,若有最后一个block未被填满则可以相隔一段继续填充其他file数据,将所有数据位置信息存储在NameNode。
一般一个DataNode的Map任务数量控制在10~100比较合适。若想增加Map任务数量可以增大
mapred.map.tasks
,若想减少Map任务数量可以增大mapred.min.split.size
。若想减少Map任务数量但是有很多小文件,可以先将小文件压缩合并。增设Combine
数据经过Map端输出后会进行网络混洗,经过Shuffle后进入Reduce,在数据量很大的情况下会产生巨大的网络开销,故可以现在本地按照key进行一次排序与合并,即Combine。多数情况下,Combine和Reduce的逻辑是一致的。
Reduce任务数量调整:大数据情况下,建议相对较大以提高利用率(最大值72)
- 通过调节
mapred.reduce.tasks
- 通过调用
job.setNumReduceTasks(int n)
方法
- 通过调节
调优方法待续…