背景

公司的物流业务系统目前实现了使用storm集群进行过门事件的实时计算处理,但是还有一个需求,我们需要存储每个标签上传的每条明细数据,然后进行定期的标签报表统计,这个是目前的实时计算框架无法满足的,需要考虑离线存储和计算引擎。

标签的数据量是巨大的,此时存储在mysql中是不合适的,所以我们考虑了分布式存储系统HDFS。目前考虑的架构是,把每条明细数据存储到HDFS中,利用Hive或者其他类SQL的解析引擎,定期进行离线统计计算。

查找相关资料后,我下载了深入理解Haddoop这本书,从大数据的一些基础原理开始调研,这一系列的笔记就是调研笔记。

系列文章:

深入理解Hadoop读书笔记1

深入理解Hadoop读书笔记2

深入理解Hadoop-基础部分

这篇笔记主要是参考慕课网的 Hadoop3基础与电商行为日志分析 新手也能学会的大数据入门课这门课程,之所以加入基础部分,是因为跟着书籍目录在搭建好Linux下的Hadoop的运行环境后,继续往下看书时,发现在IDEA部分卡住了,所以回过头参考视频来学习如何使用IDEA开发,以及学习HDFS的API和MapReduce的一部分API,通过实操简单入门。

1. HDFS的API使用

深入理解Hadoop读书笔记2](https://www.cnblogs.com/ging/p/13565645.html)中讲解过Hadoop在Linux环境下的部署,在虚拟机中安装好Hadoop后,我们需要使用IDEA来进行开发调试。

下面会讲解Linux下使用IDEA,通过HDFS的JAVA API,来连接并操作虚拟机中的HDFS创建一个文件夹的具体过程。

IDEA的安装和破解这里略过,默认读者是有一定JAVA开发经验的。

安装好IDEA后,新建一个maven的项目,这里选择下面的quickstart模板。

建立好项目后,修改pom文件,增加hadoop-client相关,因为我虚拟机中安装的是2.10.0版本,所以这里也使用相同的客户端版本。

 <dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.10.0</version>
</dependency>

然后建立一个Class文件,添加下面的代码,即可实现,远程连接HDFS并在其中新建一个路径为/hdfs/test的文件夹。

这里有几个要点需要注意:

  1. HDFS进行伪分布式部署的时候,core-site.xml中填写的是localhost,现在需要修改为虚拟机的ip地址,否则使用下面代码连接HDFS时会报下面的异常。

    failed on connection exception: java.net.ConnectException:Connection refused
    <configuration>
    <property>
    <name>fs.defaultFS</name>
    <value>hdfs://192.168.202.129:9000</value>
    </property>
    </configuration>
  2. 用户名需要填写为HDFS中的文件夹拥有者的用户名

    用命令查看下可知,文件夹的所有者为ging

    ging@ubuntu:~/hadoop/hadoop-2.10.0$ bin/hdfs dfs -ls /
    Found 3 items
    drwxr-xr-x - ging supergroup 0 2020-09-01 23:47 /hdfs
    drwx------ - ging supergroup 0 2020-08-30 20:26 /tmp
    drwxr-xr-x - ging supergroup 0 2020-08-30 20:27 /user

完整代码如下:

package org.example;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path; import java.net.URI; public class HDFSApp { public static void main(String[] args) throws Exception {
//注意URI中为虚拟机中的HDFS的地址和端口
FileSystem fileSystem = FileSystem.get(new URI("hdfs://192.168.202.129:9000"), new Configuration(), "ging");
//给定一个路径,新建一个文件夹,并打印返回结果
boolean result = fileSystem.mkdirs(new Path("/hdfs/test"));
System.out.println(result);
}
}

返回结果:

Connected to the target VM, address: '127.0.0.1:59339', transport: 'socket'
true
Disconnected from the target VM, address: '127.0.0.1:59339', transport: 'socket'

除了上面用来演示讲解的创建文件夹功能,下面的代码还记录了,常用的基本HDFS的JAVA API,可以参考

package org.example;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.util.Progressable;
import org.junit.After;
import org.junit.Before;
import org.junit.Test; import java.io.*;
import java.net.URI; /**
* Unit test for simple App.
*/
public class AppTest { public static final String HDFS = "hdfs://192.168.202.129:9000";
private Configuration configuration;
private FileSystem fileSystem; @Before
public void setUp() throws Exception {
System.out.println("---setup---");
configuration = new Configuration();
fileSystem = FileSystem.get(new URI(HDFS), configuration, "ging");
} @Test
public void mkdirs() throws IOException {
boolean result = fileSystem.mkdirs(new Path("/hdfs/test/test"));
System.out.println(result);
} @Test
public void text() throws Exception {
FSDataInputStream inputStream = fileSystem.open(new Path("/user/ging/input/core-site.xml"));
IOUtils.copyBytes(inputStream, System.out, 1024);
} @Test
public void create() throws Exception {
FSDataOutputStream outputStream = fileSystem.create(new Path("/hdfs/test/test/a.txt"));
outputStream.writeUTF("hello world");
outputStream.flush();
outputStream.close();
} @Test
public void rename() throws Exception {
Path oldPath = new Path("/hdfs/test/test/a.txt");
Path newPath = new Path("/hdfs/test/test/b.txt");
boolean rename = fileSystem.rename(oldPath, newPath);
System.out.println(rename);
} @Test
public void copyFromLocal() throws Exception {
Path local = new Path("C:\\Users\\wgg96\\Documents\\personal-code\\suanfa-note\\CMakeLists.txt");
Path remote = new Path("/hdfs/test/test/c.txt");
fileSystem.copyFromLocalFile(local, remote);
} @Test
public void copyBigFileWithProgress() throws Exception {
InputStream inputStream = new BufferedInputStream(new FileInputStream(new File("C:\\Users\\wgg96\\Documents\\安装包\\开发\\jdk-8u251-windows-x64.exe"))); FSDataOutputStream outputStream = fileSystem.create(new Path("/hdfs/test/test/d.exe"), new Progressable() {
@Override
public void progress() {
System.out.print(".");
}
}); IOUtils.copyBytes(inputStream, outputStream, 4096);
} /**
* TODO 这里在windows系统下跑会报异常
*
* @throws Exception
*/
@Test
public void copyToLocal() throws Exception {
fileSystem.copyToLocalFile(new Path("/hdfs/test/test/d.exe"), new Path("/tmp/d.exe"));
} @Test
public void listFile() throws Exception {
FileStatus[] fileStatuses = fileSystem.listStatus(new Path("/hdfs/test/test/"));
for (FileStatus fileStatus : fileStatuses) {
String isDir = fileStatus.isDirectory() ? "文件夹" : "文件";
String permission = fileStatus.getPermission().toString();
short replication = fileStatus.getReplication();
String owner = fileStatus.getOwner();
String group = fileStatus.getGroup();
String path = fileStatus.getPath().toString();
System.out.println(isDir + "\t" +
permission + "\t" +
replication + "\t" +
owner + "\t" +
group + "\t" +
path + "\t"
);
}
} @After
public void tearDown() {
configuration = null;
fileSystem = null;
System.out.println("---teardown---");
}
}

2. MapReduce的API使用

这部分内容,是使用MapReduce编写了一个词频统计任务,代码中使用了两种模式

  • 输入输出使用HDFS -对应了APP
  • 输入输出使用本地路径模式 -对应了APPLocal

核心代码如下

Mapper

package org.example;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper; import java.io.IOException; /**
* LongWritable:偏移量
* Text:每一行的字符串
* Text:单词
* IntWritable:单词词频,map阶段,默认为1
*/
public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable> { @Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//分割每一行
String oriText = value.toString();
String[] strings = oriText.split("\t"); //拿到一个单词就把词频写到上下文中
for (String word : strings) {
context.write(new Text(word), new IntWritable(1));
}
}
}

Reducer

package org.example;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer; import java.io.IOException;
import java.util.Iterator; /**
* Text:词频统计中的每一个单词
* Iterable<IntWritable> : 词频统计中对应的多个1,可以理解成一个列表
* Text:输出每一个单词
* IntWritable:每个单词的总词频
*/
public class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable> { @Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
Iterator<IntWritable> iterator = values.iterator();
int finalCount = 0;
while (iterator.hasNext()) {
IntWritable intWritable = iterator.next();
finalCount += intWritable.get();
}
context.write(key, new IntWritable(finalCount));
}
}

APPLocal

package org.example;

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.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; import java.io.File;
import java.io.IOException; /**
* Hello world!
*/
public class AppLocal { public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
// System.setProperty("HADOOP_USER_NAME", "ging");
Configuration configuration = new Configuration();
// configuration.set("fs.defaultFS", "hdfs://192.168.202.129:9000");
Job job = Job.getInstance(configuration); job.setJarByClass(AppLocal.class);
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class); //增加combiner操作
job.setCombinerClass(WordCountReducer.class); job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class); File file = new File("/home/ging/Documents/hadoop-learn/output");
System.out.println(deleteDir(file)); FileInputFormat.setInputPaths(job, new Path("/home/ging/a.txt"));
FileOutputFormat.setOutputPath(job, new Path("output")); boolean result = job.waitForCompletion(true);
System.out.println(result);
} /**
* delete file
* @param src
* @return
*/
private static boolean deleteDir(File src) {
try {
if (src.isFile()) {
src.delete();
} else {
String[] list = src.list();
for (String s : list) {
deleteDir(new File(src, s));
}
src.delete();
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}

APP

package org.example;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
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.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; import java.net.URI; /**
* Hello world!
*/
public class App { public static void main(String[] args) throws Exception {
System.setProperty("HADOOP_USER_NAME", "ging");
Configuration configuration = new Configuration();
configuration.set("fs.defaultFS", "hdfs://192.168.202.129:9000");
Job job = Job.getInstance(configuration); job.setJarByClass(App.class);
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class); //增加combiner操作
job.setCombinerClass(WordCountReducer.class); job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class); FileSystem fileSystem = FileSystem.get(new URI("hdfs://192.168.202.129:9000"), configuration, "ging"); Path output = new Path("/hdfs/test/output");
if (fileSystem.exists(output)) {
fileSystem.delete(output, true);
} FileInputFormat.setInputPaths(job, new Path("/hdfs/test/input"));
FileOutputFormat.setOutputPath(job, output); boolean result = job.waitForCompletion(true);
System.out.println(result);
}
}

深入理解Hadoop读书笔记-3的更多相关文章

  1. Hadoop读书笔记(二)HDFS的shell操作

    Hadoop读书笔记(一)Hadoop介绍:http://blog.csdn.net/caicongyang/article/details/39898629 1.shell操作 1.1全部的HDFS ...

  2. Hadoop读书笔记(四)HDFS体系结构

    Hadoop读书笔记(一)Hadoop介绍:http://blog.csdn.net/caicongyang/article/details/39898629 Hadoop读书笔记(二)HDFS的sh ...

  3. java内存区域——深入理解JVM读书笔记

    本内容由<深入理解java虚拟机>的部分读书笔记整理而成,本读者计划连载. 通过如下图和文字介绍来了解几个运行时数据区的概念. 方法区:它是各个线程共享的区域,用于内存已被VM加载的类信息 ...

  4. 00-深入理解C#读书笔记说明

    带着问题去看书 尝试着,根据每一小节,先列出大纲.然后根据自己原先的认知和理解以及不理解,对每一个小的chapter,我会先自我提问,带着问题去阅读,然后把我的理解以及不理解记录下来,对于错误的地方做 ...

  5. [hadoop读书笔记] 第十五章 sqoop1.4.6小实验 - 将mysq数据导入hive

    安装hive 1.下载hive-2.1.1(搭配hadoop版本为2.7.3) 2.解压到文件夹下 /wdcloud/app/hive-2.1.1 3.配置环境变量 4.在mysql上创建元数据库hi ...

  6. [hadoop读书笔记] 第十五章 sqoop1.4.6小实验 - 将mysq数据导入HBASE

    导入命令 sqoop import --connect jdbc:mysql://192.168.200.250:3306/sqoop --table widgets --hbase-create-t ...

  7. [hadoop读书笔记] 第十五章 sqoop1.4.6小实验 - 数据在mysq和hdfs之间的相互转换

    P573 从mysql导入数据到hdfs 第一步:在mysql中创建待导入的数据 1.创建数据库并允许所有用户访问该数据库 mysql -h 192.168.200.250 -u root -p CR ...

  8. [hadoop读书笔记] 第十章 管理Hadoop集群

    P375 Hadoop管理工具 dfsadmin - 查询HDFS状态信息,管理HDFS. bin/hadoop dfsadmin -help 查询HDFS基本信息 fsck - 检查HDFS中文件的 ...

  9. [hadoop读书笔记] 第九章 构建Hadoop集群

    P322 运行datanode和tasktracker的典型机器配置(2010年) 处理器:两个四核2-2.5GHz CPU 内存:16-46GN ECC RAM 磁盘存储器:4*1TB SATA 磁 ...

  10. [hadoop读书笔记] 第五章 MapReduce工作机制

    P205 MapReduce的两种运行机制 第一种:经典的MR运行机制 - MR 1 可以通过一个简单的方法调用来运行MR作业:Job对象上的submit().也可以调用waitForCompleti ...

随机推荐

  1. 在linux上Git配置多个SSH-Key

    Git配置多个SSH-Key SSH Key 背景 当有多个git账号时,比如: a. 一个gitee,用于公司内部的工作开发: b. 一个github,用于自己进行一些开发活动: c.一个gitla ...

  2. Pytorch损失函数总结

    损失函数 nn.L1Loss 创建一个衡量输入中每个元素之间的平均绝对误差 (MAE) 的标准XX和目标是的是的. nn.MSELoss 创建一个标准,用于测量输入中每个元素之间的均方误差(平方 L2 ...

  3. Windows环境配置Nginx服务实现负载均衡

    系统环境:win10 测试服务:.net6.0+webapi 一.本地创建一个webapi项目 二.新建一个api控制器,里面编写一个测试方法 三.我直接把这一个项目复制了3份,然后修改控制器方法中的 ...

  4. CDS标准视图:功能位置描述 I_FunctionalLocationText

    视图名称:功能位置描述 I_FunctionalLocationText 视图类型:基本视图 视图代码: 点击查看代码 @EndUserText.label: 'Functional Location ...

  5. [车联网/以太网] SOME/IP 协议

    概述: SOME/IP 协议 车载以太网协议栈总共可划分为5层: 物理层 数据链路层 网络层 传输层 应用层 其中本文所要描述的SOME/IP就是一种应用层协议. SOME/IP协议内容按照AUTOS ...

  6. cxGrid列的OnValidate事件处理程序

    procedure TForm1.cxGrid1DBTableView1AColumnPropertiesValidate(Sender: TObject; var DisplayValue: Var ...

  7. 【译】融入人工智能的 eShop – 全面的智能应用示例

    原文 | Jeremy Likness 翻译 | 郑子铭 人工智能 (AI) 是一种强大的工具,它可以增强您的应用程序,提供更好的个性化定制体验,满足客户的独特需求,同时提高内部运营的质量和效率.虽然 ...

  8. 从倒水问题到盛最多水的容器:一道经典的双指针应用题|LeetCode 11 盛最多水的容器

    LeetCode 11 盛最多水的容器 点此看全部题解 LeetCode必刷100题:一份来自面试官的算法地图(题解持续更新中) 生活中的算法 你有没有遇到过这样的场景:家里要举办派对,需要准备一个大 ...

  9. Codeforces 1110D Jongmah 题解 [ 蓝 ] [ 线性 dp ] [ 观察 ]

    Jongmah:小清新麻将 dp 题. 观察 首先观察这两个操作的性质,不难发现我们出掉的所有的顺子只要累计出了三次,这三次顺子就一定可以化作出三次相同的单牌. 而我们只需要最大化操作次数,显然这三次 ...

  10. 在使用HOperatorSet.Draw忘记点击右键结束方法无法关闭窗体问题如何规避

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/17270056.html 可以在离开窗体或者关闭窗体事件中调用HOperatorSet.HIOC ...