Overview
Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS。HDFS有高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件上;而且它提供高吞吐量(high throughput)来访问应用程序的数据,适合那些有着超大数据集(large data set)的应用程序。HDFS放宽了(relax)POSIX的要求,可以以流的形式访问(streaming access)文件系统中的数据。Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,而MapReduce则为海量的数据提供了计算。
比较社区版和商业版
Apache社区版 优点:完全开源,社区开发者多,文档资料多 ;
缺点:版本管理比较混乱,集群的部署安装配置复杂,集群运维复杂。
CDH版本:基于Apache协议,开源。 bug少:基于稳定版本Apache Hadoop,并应用了最新Bug修复或Feature的patch,部署方便。
一、Hadoop环境搭建:
1.JDK安装(略):请参照网上的其他教程安装并配置环境变量:
export JAVA_HOME=/home/hadoop/app/jdk1.7.0_51
export PATH=$JAVA_HOME/bin:$PATH
2.下载hadoop:
http://archive.cloudera.com/cdh5/cdh/5/ 2.6.0-cdh5.7.0
或:wget http://archive.cloudera.com/cdh5/cdh/5/hadoop-2.6.0-cdh5.7.0.tar.gz
3.Hadoop配置文件修改:
~/app/hadoop-2.6.0-cdh5.7.0/etc/hadoop
hadoop-env.sh
export JAVA_HOME=/home/hadoop/app/jdk1.7.0_51 core-site.xml
<property>
<name>fs.defaultFS</name>
<value>hdfs://localhost:8020</value>
</property> <property>
<name>hadoop.tmp.dir</name>
<value>/home/hadoop/app/tmp</value>
</property> hdfs-site.xml
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
4.格式化HDFS
注意:这一步操作,只是在第一次时执行,每次如果都格式化的话,那么HDFS上的数据就会被清空
命令:bin/hdfs namenode -format
5.启动HDFS
sbin/start-dfs.sh
验证是否启动成功:
进程命令:jps,出现下面三个进程则表示启动成功
DataNode
SecondaryNameNode
NameNode
浏览器
http://localhost:50070/
6.停止HDFS
sbin/stop-dfs.sh
遇到的问题:hadoop上传文件错误org.apache.hadoop.ipc.RemoteException(java.io.IOException)
搭建好hadoop后使用hadoop fs -put 命令上传文件发现失败,报了以下错误:
看它的报错信息好像是节点没有启动,但是我的节点都启动起来了,使用jps也能查看到节点信息。
使用hadoop dfsadmin -report命令查看磁盘使用情况,发现出现以下问题:
节点下存储空间都是空的,问题应该就是出现在这了。
查阅资料发现造成这个问题的原因可能是使用hadoop namenode -format格式化时格式化了多次造成那么spaceID不一致,解决方案:
1、停止集群(切换到/sbin目录下)
$./stop-all.sh
2、删除在hdfs中配置的data目录(即在core-site.xml中配置的hadoop.tmp.dir对应文件件)下面的所有数据;
$ rm -rf /home/zengyouxuan/tmp/hadoop/*
3、重新格式化namenode(切换到hadoop目录下的bin目录下)
$ ./hadoop namenode -format
4、重新启动hadoop集群(切换到hadoop目录下的sbin目录下)
$./start-all.sh
再使用hadoop dfsadmin -report查看使用情况,结果如下图所示:
二、HDFS架构
1 Master(NameNode/NN) 带 N个Slaves(DataNode/DN)
HDFS/YARN/HBase
1个文件会被拆分成多个Block
blocksize:128M
130M ==> 2个Block: 128M 和 2M
NN:
1)负责客户端请求的响应
2)负责元数据(文件的名称、副本系数、Block存放的DN)的管理
DN:
1)存储用户的文件对应的数据块(Block)
2)要定期向NN发送心跳信息,汇报本身及其所有的block信息,健康状况
A typical deployment has a dedicated machine that runs only the NameNode software. Each of the other machines in the cluster runs one instance of the DataNode software.The architecture does not preclude running multiple DataNodes on the same machine but in a real deployment that is rarely the case.
NameNode + N个DataNode
建议:NN和DN是部署在不同的节点上
replication factor:副本系数、副本因子
All blocks in a file except the last block are the same size
2.HDFS的优缺点
优点:高容错,适合批处理,适合大数据处理,可在廉价机器上部署;缺点:低延迟的数据访问,不适合小文件存储
三、分布式计算框架MapReduce
1.特点:易于编程,良好的扩展性,高容错性,海量数据的离线处理
不擅长的场景:实时计算,流式计算,DAG计算
2.MapReduce编程模型(以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.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 WordCount {
public static class TokenizerMapper
extends Mapper<Object, Text, Text, IntWritable>{ //map
private final static IntWritable one = new IntWritable(1);
private Text word = new Text();
public void map(Object key, Text value, Context context
) throws IOException, InterruptedException { //重写map方法
StringTokenizer itr = new StringTokenizer(value.toString());
while (itr.hasMoreTokens()) {
word.set(itr.nextToken());
context.write(word, one);
}
}
}
public static class IntSumReducer
extends Reducer<Text,IntWritable,Text,IntWritable> {
private IntWritable result = new IntWritable();
public void reduce(Text key, Iterable<IntWritable> values,
Context context
) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
result.set(sum);
context.write(key, result);
}
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "word count");
job.setJarByClass(WordCount.class);
job.setMapperClass(TokenizerMapper.class);
job.setCombinerClass(IntSumReducer.class);
job.setReducerClass(IntSumReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}