作为一名大学生,接触到大数据技术后,我被 Hadoop 的强大功能所吸引。Hadoop 是一个开源的分布式计算平台,能够处理大规模数据集,在大数据领域应用广泛。以下是我在学习 Hadoop 过程中的一些经验分享,希望对同样感兴趣的同学有所帮助。
hadoop概念
Hadoop 是一个开源的分布式计算和存储框架,由 Apache 基金会开发和维护。
Hadoop 为庞大的计算机集群提供可靠的、可伸缩的应用层计算和存储支持,它允许使用简单的编程模型跨计算机群集分布式处理大型数据集,并且支持在单台计算机到几千台计算机之间进行扩展。
Hadoop 使用 Java 开发,所以可以在多种不同硬件平台的计算机上部署和使用。其核心部件包括分布式文件系统 (Hadoop DFS,HDFS) 和 MapReduce。
一、Hadoop 环境搭建
首先,我们需要在本地或虚拟机上搭建 Hadoop 环境。以下是基于 Ubuntu 系统的基本步骤:
- 安装 Java:Hadoop 运行依赖 Java 环境,使用以下命令安装 OpenJDK:
sudo apt-get update sudo apt-get install openjdk-8-jdk
安装完成后,通过
java -version
命令检查 Java 是否安装成功。 - 下载和配置 Hadoop:从官方网站(https://hadoop.apache.org/releases.html)下载适合的 Hadoop 版本,并解压到指定目录,例如
/usr/local/hadoop
。
然后,编辑hadoop-env.sh
文件,设置 Java 路径。
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://localhost:9000</value>
</property>
</configuration>
hdfs-site.xml
:
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:/usr/local/hadoop/hdfs/namenode</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:/usr/local/hadoop/hdfs/datanode</value>
</property>
</configuration>
mapred-site.xml
:
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>
- 启动 Hadoop 集群:
首先,格式化 HDFS 文件系统:
hdfs namenode -format
然后,启动 Hadoop 服务:
start-dfs.sh
start-yarn.sh
start-yarn.sh
通过jps
命令可以查看启动的进程,包括NameNode
、DataNode
、ResourceManager
和NodeManager
等,说明 Hadoop 集群启动成功。
Hadoop默认的四个核心配置文件
- core-site.xml : 核心模块配置
- hdfs-site.xml: hdfs文件系统模块配置
- mapred-site.xml: MapReduce模块配置
- yarn-site.xml : yarn模块配置
关于HDFS的学习
1.前言
(1)文件系统
文件系统是一种存储和组织数据的方法,实现了数据的存储、分级组织、访问和获取等操作,使得用户对文件访问和查找变得容易;
文件系统使用树形目录的抽象逻辑概念代替了硬盘等物理设备使用数据块的概念,用户不必关心数据底层存在硬盘哪里,只需要记住这个文件的所属目录和文件名即可;
比如windows操作系统
- 数据:指存储的内容本身,比如文件、视频、图片等
- 元数据:又称之为解释性数据,记录数据的数据;一般指文件大小、最后修改时间、底层存储位置、属性、所属用户、权限等信息。
-
2.HDFS简介
Hadoop分布式文件系统。HDFS主要是解决大数据如何存储问题的。
HDFS是一种能够在普通硬件上运行的分布式文件系统,它是高度容错的,适应于具有大数据集的应用程序,它非常适于存储大型数据 (比如 TB 和 PB)。
HDFS使用多台计算机存储文件, 并且提供统一的访问接口, 像是访问一个普通文件系统一样使用分布式文件系统。
3.HDFS重要特性
主从架构
分块存储
副本机制
元数据记录
抽象统一的目录树结构(namespace)
(1)主从架构
HDFS集群是标准的master/slave主从架构集群。
一般一个HDFS集群是有一个Namenode和一定数目的Datanode组成。
Namenode是HDFS主节点,Datanode是HDFS从节点,两种角色各司其职,共同协调完成分布式的文件存储服务。
2)分块存储
HDFS中的文件在物理上是分块存储(block)的,默认大小是128M(134217728),不足128M则本身就是一块。
块的大小可以通过配置参数来规定,参数位于hdfs-default.xml中:dfs.blocksize。
(3)副本机制
文件的所有block都会有副本。副本系数可以在文件创建的时候指定,也可以在之后通过命令改变。
副本数由参数dfs.replication控制,默认值是3,也就是会额外再复制2份,连同本身总共3份副本。
4)元数据管理
在HDFS中,Namenode管理的元数据具有两种类型:
文件自身属性信息
文件名称、权限,修改时间,文件大小,复制因子,数据块大小。
文件块位置映射信息
记录文件块和DataNode之间的映射信息,即哪个块位于哪个节点上。
(5)namespace
HDFS支持传统的层次型文件组织结构。用户可以创建目录,然后将文件保存在这些目录里。
文件系统名字空间的层次结构和大多数现有的文件系统类似:用户可以创建、删除、移动或重命名文件。
Namenode负责维护文件系统的namespace名称空间,任何对文件系统名称空间或属性的修改都将被Namenode记录下来。
HDFS会给客户端提供一个统一的抽象目录树,客户端通过路径来访问文件,形如:hdfs://namenode:port/dira/dir-b/dir-c/file.data。
4.HDFS常用命令如图
运行首个 MapReduce 任务
- 编写 WordCount 示例
- Mapper 类:
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
private final static IntWritable one = new IntWritable(1);
private Text word = new Text();
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String[] words = value.toString().split(" ");
for (String w : words) {
word.set(w);
context.write(word, one);
}
}
}
JAVA API HDFS 前置工作 - 配置环境
Windows 下 JDK 配置
下载 JDK 安装包:从 Oracle 官网下载适合 Windows 系统的 JDK 版本,如 JDK 8 或更高版本。
安装 JDK:运行安装程序,按照提示完成安装。
配置环境变量:
新建JAVA_HOME变量,值为 JDK 的安装路径,例如C:\Program Files\Java\jdk1.8.0_xxx。
在Path变量中添加%JAVA_HOME%\bin和%JAVA_HOME%\jre\bin。
验证安装:打开命令提示符,输入java -version,如果显示 JDK 版本信息,则配置成功。
Windows 下 HADOOP 配置
下载 Hadoop 安装包:从 Hadoop 官网下载适合 Windows 系统的 Hadoop 版本。
解压安装包:将下载的压缩包解压到指定目录,例如C:\hadoop。
配置环境变量:
新建HADOOP_HOME变量,值为 Hadoop 的解压路径,例如C:\hadoop。
在Path变量中添加%HADOOP_HOME%\bin。
配置 Hadoop 相关文件:
编辑C:\hadoop\etc\hadoop\core - site.xml,添加以下内容:
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://localhost:9000</value>
</property>
</configuration>
编辑C:\hadoop\etc\hadoop\hdfs - site.xml
,添加以下内容:
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>C:\hadoop\data\namenode</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>C:\hadoop\data\datanode</value>
</property>
</configuration>
格式化 HDFS:打开命令提示符,进入C:\hadoop\bin目录,执行hdfs namenode - format命令。
启动 HDFS:执行start - dfs.cmd命令启动 HDFS 服务。
配置 Maven 仓库
下载并安装 Maven:从 Maven 官网下载 Maven 安装包,运行安装程序完成安装。
配置 Maven 环境变量:
新建MAVEN_HOME变量,值为 Maven 的安装路径,例如C:\Program Files\Apache\maven。
在Path变量中添加%MAVEN_HOME%\bin。
配置本地 Maven 仓库:编辑C:\Program Files\Apache\maven\conf\settings.xml文件,设置本地仓库路径,例如:
<localRepository>C:\maven\repository</localRepository>
- 编写 MapReduce 代码:参考前面的 WordCount 示例,在项目中编写 MapReduce 相关代码。
- 配置运行环境:在 IntelliJ IDEA 中配置 Hadoop 运行环境,设置 Hadoop 的安装路径等参数。
应用 JAVA API HDFS
- 创建文件
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
public class CreateFileHDFS {
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path file = new Path("/user/test/new_file.txt");
if (fs.createNewFile(file)) {
System.out.println("File created successfully.");
} else {
System.out.println("File already exists.");
}
fs.close();
}
}
- 解释:这段代码通过 Java API 在 HDFS 的
/user/test
目录下创建一个名为new_file.txt
的文件。 - 读取文件
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
public class ReadFileHDFS {
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path file = new Path("/user/test/new_file.txt");
if (fs.exists(file)) {
FSDataInputStream in = fs.open(file);
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = in.read(buffer)) > 0) {
System.out.println(new String(buffer, 0, bytesRead));
}
in.close();
}
fs.close();
}
}
解释:这段代码通过 Java API 读取 HDFS 中/user/test/new_file.txt
文件的内容
下面再来讲讲
HDFS(分布文件系统)
首先,我们需要在 Java 代码中引入 Hadoop 的相关依赖:
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
接下来,展示如何连接 HDFS 并进行简单的文件操作,比如创建目录和上传文件:
public class HdfsExample {
public static void main(String[] args) {
try {
// 创建 Hadoop 配置对象
Configuration conf = new Configuration();
// 设置 HDFS 相关参数,这里使用本地 Hadoop 环境,默认端口 9000
conf.set("fs.defaultFS", "hdfs://localhost:9000");
// 获取 HDFS 文件系统对象
FileSystem fs = FileSystem.get(conf);
// 创建目录
Path dirPath = new Path("/user/student/input");
if (!fs.exists(dirPath)) {
fs.mkdirs(dirPath);
System.out.println("目录创建成功");
} else {
System.out.println("目录已存在");
}
// 上传本地文件到 HDFS
Path localPath = new Path("C:/data/sample.txt");
Path hdfsPath = new Path("/user/student/input/sample.txt");
fs.copyFromLocalFile(localPath, hdfsPath);
System.out.println("文件上传成功");
// 关闭文件系统连接
fs.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
在上述代码中,我们首先配置了 Hadoop 的连接信息,然后通过 FileSystem
类实现了目录创建和文件上传的操作。如果在执行过程中出现错误,会打印出堆栈信息,方便我们调试。
二、Hadoop 核心组件之 MapReduce
MapReduce 是 Hadoop 的核心编程模型,用于大规模数据集的并行处理。它将数据处理任务分解为两个阶段:Map 阶段和 Reduce 阶段。
(二)WordCount 示例代码解析
下面以经典的 WordCount 程序为例,详细解析 MapReduce 的代码实现。
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;
// Mapper 类
public class WordCountMapper extends Mapper<Object, Text, Text, IntWritable> {
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 {
// 将输入的一行文本按空格分割成单词
StringTokenizer itr = new StringTokenizer(value.toString());
while (itr.hasMoreTokens()) {
// 设置每个单词为键,值为 1
word.set(itr.nextToken());
context.write(word, one);
}
}
}
// Reducer 类
public class WordCountReducer 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 class WordCount {
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
// 创建一个新的 MapReduce 作业
Job job = Job.getInstance(conf, "word count");
job.setJarByClass(WordCount.class);
// 设置 Mapper 和 Reducer 类
job.setMapperClass(WordCountMapper.class);
job.setCombinerClass(WordCountReducer.class);
job.setReducerClass(WordCountReducer.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);
}
}
在这个 WordCount 示例中:
WordCountMapper
类负责将输入的文本数据按行读取,并将每行的单词分割出来,每个单词作为键,值为1
,通过context.write
方法输出。WordCountReducer
类接收Mapper
输出的相同单词的键值对列表,将这些值累加起来,得到每个单词的最终计数,并输出结果。WordCount
主类则负责配置整个 MapReduce 作业,包括设置Mapper
、Reducer
类,定义输入输出路径和键值对类型,最后提交作业并等待执行完成。
当我们在 Hadoop 环境中运行这个程序时,它会读取指定输入路径下的文本文件,统计每个单词的出现次数,并将结果输出到指定的输出路径。
通过对 HDFS 和 MapReduce 的学习和实践,我深刻体会到了 Hadoop 在大数据处理方面的强大能力。虽然在学习过程中遇到了不少困难,比如环境配置问题、代码调试等,但每一次解决问题都让我对 Hadoop 的理解更加深入。希望以上的内容能够帮助到正在学习 Hadoop 的同学们,让我们一起在大数据的海洋中继续探索前行!