Hadoop大数据技术复习资料
钟兴宇
1.选择题15空,共30分。
Hadoop以HDFS(Hadoop Distributed File System,Hadoop 分布式文件系统)和MapReduce(Google MapReduce 的开源实现)为核心。
hadoop三种安装方式:单体,伪分布式,完全分布式
Hadoop集群启动时个进程的启动顺序:namenode,datanode,secondnamenode,resourcemanger,NodeManager
Mapreduce是一个分布式运算程序的编程框架,是用户开发“基于hadoop的数据分析应用”的核心框架;
Mapreduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一个hadoop集群上;
HBase是一种构建在HDFS之上的分布式、面向列的存储系统。在需要实时读写、随机访问超大规模数据集时,可以使用HBase。
HBase的访问接口包括Java api,shell命令,hive
2.填空题10空,共20分。
hadoop集群的通信协议是ssh。
hdfs的体系结构:
hdfs有namenode、secondraynamenode、datanode组成。为n+1模式
- NameNode负责管理和记录整个文件系统的元数据
- DataNode 负责管理用户的文件数据块,文件会按照固定的大小(blocksize)切成若干块后分布式存储在若干台datanode上,每一个文件块可以有多个副本,并存放在不同的datanode上,Datanode会定期向Namenode汇报自身所保存的文件block信息,而namenode则会负责保持文件的副本数量
- HDFS的内部工作机制对客户端保持透明,客户端请求访问HDFS都是通过向namenode申请来进行
- secondraynamenode负责合并日志
HDFS读流程
- client跟namenode通信查询元数据,namenode通过查询元数据,找到文件块所在的datanode服务器
- 挑选一台datanode(就近原则,然后随机)服务器,请求建立socket流
- datanode开始发送数据(从磁盘里面读取数据放入流,以packet为单位来做校验,大小为64k)
- 客户端以packet为单位接收,现在本地缓存,然后写入目标文件
shuffle机制
- mapreduce中,map阶段处理的数据如何传递reduce阶段,是mapreduce框架中最关键的一个流程,这个流程就叫shuffle;
- shuffle: 洗牌、发牌——(核心机制:数据分区,排序,缓存);
- 具体来说:就是将maptask输出的处理结果数据,分发给reducetask,并在分发的过程中,对数据按key进行了分区和排序*;*
shuffle是MR处理流程中的一个过程,它的每一个处理步骤是分散在各个map task和reduce task节点上完成的,整体来看,分为3个操作:
- 分区partition
- Sort根据key排序
- Combiner进行局部value的合并
具体来说就是将maptask输出的处理结果数据,分发给reducetask,并在分发的过程中,对数据按key进行了分区和排序;
HBase可以被看作键值存储数据库、面向列族的数据库
HBase数据存储结构中主要包括:表、行、列族、列限定符、单元格和时间戳
3.简答题4个,共20分。
1.简述什么是大数据以及大数据的特征?
定义:是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。
特征:数据量巨大、数据具有高速性、数据类型多样性、数据具有潜在价值、数据准确性。
2.简述Hadoop以及Hadoop的特性?
Hadoop 是Apache 下的一个开源分布式计算平台。Hadoop以HDFS(Hadoop Distributed File System)和MapReduce(Google MapReduce 的开源实现)为核心。
Hadoop的特点:高可靠性、高扩展性、经济性、高容错性、高效性、基于Java语言开发的。
3.简述NoSQL数据库的特点以及类型?
(1)成本:nosql数据库简单容易部署,基本上都是开源软件,不像oracle数据库那样收费,和关系型数据库比起来价格便宜。
(2)查询速度:nosql数据库是将数据存储到缓存之中,关系型数据库将数据存储到硬盘中,所以nosql数据库查询速度快。
(3)存储数据的格式:nosql的存储格式是key,value形式、文档形式等等,所以可以存储基础类型以及对象或者集合等各种格式,关系型数据库只支持基础类型。
(4)拓展性:关系型数据库有join这个样的多表查询机制的限制导致拓展很艰难。
*一、 键值(Key-Value)数据库*
*二、 面向文档(Document-Oriented)数据库*
*三、 列存储(Wide Column Store/Column-Family)数据库*
*四、 图(Graph-Oriented)数据库*
4.简述Hive?
Hive是一个数据仓库基础工具在Hadoop中用来处理结构化数据。它架构在Hadoop之上,总归为大数据,并使得查询和分析方便。并提供简单的sql查询功能,可以将sql语句转换为MapReduce任务进行运行。
5.简述HBase?
HBase的数据的存储结构不同于传统的关系型数据库,HBase是一种结构松散,分布式,多维度有序映射的持久化存储系统,它索引的依据是行键、列键和时间戳。
6.简述hdfs存储数据过程
4.应用实操题。共10空,20分。
1.hdfs
有三种shell命令方式。
-
hadoop fs
-
hadoop dfs(已过期)
-
hdfs dfs(常用)
hadoop fs适用于任何不同的文件系统,比如本地文件系统和HDFS文件系统
hadoop dfs只能适用于HDFS文件系统
hdfs dfs跟hadoop dfs的命令作用一样,也只能适用于HDFS文件系统
1.在hdfs创建一个在user下的目录hadoop
hadoop fs -mkdir /user/hadoop
2.写“Hello world”到test.txt文件
echo “Hello world”->test.txt
3.将test.txt放入hdfs在user下的目录hadoop
hadoop fs -put test.txt /user/hadoop
4.在hdfs中查看test.txt
hadoop fs -cat /user/test.txt
5.从hdfs上下载test.txt到本地
hadoop fs -get /user/test.txt
6.从hdfs上删除test.txt
hadoop fs -rm /user/test.txt
2.mongodb
mongodb数据库相关:
-
show dbs:显示数据库列表
-
show collections:显示当前数据库中的集合(类似关系数据库中的表table)
-
show users:显示所有用户
-
use yourDB:切换当前数据库至yourDB
-
db.help() :显示数据库操作命令
-
db.yourCollection.help() :显示集合操作命令,yourCollection是集合名
MongoDB没有创建数据库的命令,如果你想创建一个“School”的数据库,先运行use School命令,之后做一些操作
1.创建一个“student”的数据库
use student
2.插入数据
db.student.insert({_id:1, sname: ‘zhangsan’, sage: 20})
或者
db.student.save({_id:1, sname: ‘zhangsan’, sage: 22})
这两种方式,其插入的数据中_id字段均可不写,会自动生成一个唯一的_id来标识本条数据。而insert和save不同之处在于:在手动插入_id字段时,如果_id已经存在,insert不做操作,save做更新操作;如果不加_id字段,两者作用相同都是插入数据。
3.查找数据
db.student.find(criteria, filterDisplay)
criteria :查询条件,可选
filterDisplay:筛选显示部分数据,如显示指定列数据,可选(当选择时,第一个参数不可省略,若查询条件为空,可用{}做占位符,如下例第三句)
db.student.find() #查询所有记录。相当于:select * from student
db.student.find({sname: ‘lisi’}) #查询sname='lisi’的记录。相当于: select * from student where sname=‘lisi’
db.student.find({},{sname:1, sage:1}) #查询指定列sname、sage数据。相当于:select sname,sage from student。sname:1表示返回sname列,默认_id字段也是返回的,可以添加_id:0(意为不返回_id)写成{sname: 1, sage: 1,_id:0},就不会返回默认的_id字段了
db.student.find({sname: ‘zhangsan’, sage: 22}) #and 与条件查询。相当于:select * from student where sname = ‘zhangsan’ and sage = 22
db.student.find({$or: [{sage: 22}, {sage: 25}]}) #or 条件查询。相当于:select * from student where sage = 22 or sage = 25
4.修改数据
db.student.update({sname: ‘lisi’}, {$set: {sage: 30}}, false, true) #相当于:update student set sage =30 where sname = ‘lisi’;
5.删除数据
db.student.remove({sname: ‘zhaoliu’}) #相当于:delete from student where sname=‘zhaoliu’
6.删除集合
db.student.drop()
3.hbase
1.创建一个student表,属性有:name,sex,age,dept,course。
create ‘student’,‘name’,‘sex’,‘age’,‘dept’,‘course’
2.为student表添加了学号为18001,名字为zhangsan的一行数据,其行键为18001。
put ‘student’,’18001’,’name’,’zhangsan’
3.查看数据
get ‘student’,‘18001’
或者
scan ‘student’
4.删除student表中95001行下的sex列的所有数据。
delete ‘student’,‘18001’,‘sex’
5.删除student表中的18001行的全部数据。
deleteall ‘student’,‘18001’
6.删除表
disable ‘student’
drop ‘student’
5.编程题(补充程序代码)。5空共10分。
创建目录
删除目录(如果目录非空则会提示not empty,不执行删除)
Java实现:
import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.*;import java.io.*;public class HdfsApi {
/**
* 判断路径是否存在
*/
public static boolean test(Configuration conf, String path) throws IOException {
FileSystem fs = FileSystem.get(conf);
return fs.exists(new Path(path));
}
/**
* 判断目录是否为空
* true: 空,false: 非空
*/
public static boolean isDirEmpty(Configuration conf, String remoteDir) throws IOException {
FileSystem fs = FileSystem.get(conf);
Path dirPath = new Path(remoteDir);
RemoteIterator<LocatedFileStatus> remoteIterator = fs.listFiles(dirPath, true);
return !remoteIterator.hasNext();
}
/**
* 创建目录
*/
public static boolean mkdir(Configuration conf, String remoteDir) throws IOException {
FileSystem fs = FileSystem.get(conf);
Path dirPath = new Path(remoteDir);
boolean result = fs.mkdirs(dirPath);
fs.close();
return result;
}
/**
* 删除目录
*/
public static boolean rmDir(Configuration conf, String remoteDir) throws IOException {
FileSystem fs = FileSystem.get(conf);
Path dirPath = new Path(remoteDir);
/* 第二个参数表示是否递归删除所有文件 */
boolean result = fs.delete(dirPath, true);
fs.close();
return result;
}
/**
* 主函数
*/
public static void main(String[] args) {
Configuration conf = new Configuration();
conf.set("fs.default.name","hdfs://localhost:9000");
String remoteDir = "/user/hadoop/input"; // HDFS目录
Boolean forceDelete = false; // 是否强制删除
try {
/* 判断目录是否存在,不存在则创建,存在则删除 */
if ( !HdfsApi.test(conf, remoteDir) ) {
HdfsApi.mkdir(conf, remoteDir); // 创建目录
System.out.println("创建目录: " + remoteDir);
} else {
if ( HdfsApi.isDirEmpty(conf, remoteDir) || forceDelete ) { // 目录为空或强制删除
HdfsApi.rmDir(conf, remoteDir);
System.out.println("删除目录: " + remoteDir);
} else { // 目录不为空
System.out.println("目录不为空,不删除: " + remoteDir);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
*向HDFS中指定的文件追加内容,由用户指定内容追加到原有文件的开头或结尾;*
Java实现:
import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.*;import java.io.*;public class HdfsApi {
/**
* 判断路径是否存在
*/
public static boolean test(Configuration conf, String path) throws IOException {
FileSystem fs = FileSystem.get(conf);
return fs.exists(new Path(path));
}
/**
* 追加文本内容
*/
public static void appendContentToFile(Configuration conf, String content, String remoteFilePath) throws IOException {
FileSystem fs = FileSystem.get(conf);
Path remotePath = new Path(remoteFilePath);
/* 创建一个文件输出流,输出的内容将追加到文件末尾 */
FSDataOutputStream out = fs.append(remotePath);
out.write(content.getBytes());
out.close();
fs.close();
}
/**
* 追加文件内容
*/
public static void appendToFile(Configuration conf, String localFilePath, String remoteFilePath) throws IOException {
FileSystem fs = FileSystem.get(conf);
Path remotePath = new Path(remoteFilePath);
/* 创建一个文件读入流 */
FileInputStream in = new FileInputStream(localFilePath);
/* 创建一个文件输出流,输出的内容将追加到文件末尾 */
FSDataOutputStream out = fs.append(remotePath);
/* 读写文件内容 */
byte[] data = new byte[1024];
int read = -1;
while ( (read = in.read(data)) > 0 ) {
out.write(data, 0, read);
}
out.close();
in.close();
fs.close();
}
/**
* 移动文件到本地
* 移动后,删除源文件
*/
public static void moveToLocalFile(Configuration conf, String remoteFilePath, String localFilePath) throws IOException {
FileSystem fs = FileSystem.get(conf);
Path remotePath = new Path(remoteFilePath);
Path localPath = new Path(localFilePath);
fs.moveToLocalFile(remotePath, localPath);
}
/**
* 创建文件
*/
public static void touchz(Configuration conf, String remoteFilePath) throws IOException {
FileSystem fs = FileSystem.get(conf);
Path remotePath = new Path(remoteFilePath);
FSDataOutputStream outputStream = fs.create(remotePath);
outputStream.close();
fs.close();
}
/**
* 主函数
*/
public static void main(String[] args) {
Configuration conf = new Configuration();
conf.set("fs.default.name","hdfs://localhost:9000");
String remoteFilePath = "/user/hadoop/text.txt"; // HDFS文件
String content = "新追加的内容\n";
String choice = "after"; //追加到文件末尾//
String choice = "before"; // 追加到文件开头
try {
/* 判断文件是否存在 */
if ( !HdfsApi.test(conf, remoteFilePath) ) {
System.out.println("文件不存在: " + remoteFilePath);
} else {
if ( choice.equals("after") ) { // 追加在文件末尾
HdfsApi.appendContentToFile(conf, content, remoteFilePath);
System.out.println("已追加内容到文件末尾" + remoteFilePath);
} else if ( choice.equals("before") ) { // 追加到文件开头
/* 没有相应的api可以直接操作,因此先把文件移动到本地,创建一个新的HDFS,再按顺序追加内容 */
String localTmpPath = "/user/hadoop/tmp.txt";
HdfsApi.moveToLocalFile(conf, remoteFilePath, localTmpPath); // 移动到本地
HdfsApi.touchz(conf, remoteFilePath); // 创建一个新文件
HdfsApi.appendContentToFile(conf, content, remoteFilePath); // 先写入新内容
HdfsApi.appendToFile(conf, localTmpPath, remoteFilePath); // 再写入原来内容
System.out.println("已追加内容到文件开头: " + remoteFilePath);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
*删除HDFS中指定的文件;*
Java实现:
import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.*;import java.io.*;public class HdfsApi {
/**
* 删除文件
*/
public static boolean rm(Configuration conf, String remoteFilePath) throws IOException {
FileSystem fs = FileSystem.get(conf);
Path remotePath = new Path(remoteFilePath);
boolean result = fs.delete(remotePath, false);
fs.close();
return result;
}
/**
* 主函数
*/
public static void main(String[] args) {
Configuration conf = new Configuration();
conf.set("fs.default.name","hdfs://localhost:9000");
String remoteFilePath = "/user/hadoop/text.txt"; // HDFS文件
try {
if ( HdfsApi.rm(conf, remoteFilePath) ) {
System.out.println("文件删除: " + remoteFilePath);
} else {
System.out.println("操作失败(文件不存在或删除失败)");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
*删除HDFS中指定的目录,由用户指定目录中如果存在文件时是否删除目录;*
Java实现:
import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.*;import java.io.*;public class HdfsApi {
/**
* 判断目录是否为空
* true: 空,false: 非空
*/
public static boolean isDirEmpty(Configuration conf, String remoteDir) throws IOException {FileSystem fs = FileSystem.get(conf);
Path dirPath = new Path(remoteDir);
RemoteIterator<LocatedFileStatus> remoteIterator = fs.listFiles(dirPath, true);
return !remoteIterator.hasNext();
}
/**
* 删除目录
*/
public static boolean rmDir(Configuration conf, String remoteDir, boolean recursive) throws IOException {
FileSystem fs = FileSystem.get(conf);
Path dirPath = new Path(remoteDir);
/* 第二个参数表示是否递归删除所有文件 */
boolean result = fs.delete(dirPath, recursive);
fs.close();
return result;
}
/**
* 主函数
*/
public static void main(String[] args) {
Configuration conf = new Configuration();
conf.set("fs.default.name","hdfs://localhost:9000");
String remoteDir = "/user/hadoop/dir1/dir2"; // HDFS目录
Boolean forceDelete = false; // 是否强制删除
try {
if ( !HdfsApi.isDirEmpty(conf, remoteDir) && !forceDelete ) {
System.out.println("目录不为空,不删除");
} else {
if ( HdfsApi.rmDir(conf, remoteDir, forceDelete) ) {
System.out.println("目录已删除: " + remoteDir);
} else {
System.out.println("操作失败");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
*在HDFS中,将文件从源路径移动到目的路径。*
Java实现:
import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.*;import java.io.*;public class HdfsApi {
/**
* 移动文件
*/
public static boolean mv(Configuration conf, String remoteFilePath, String remoteToFilePath) throws IOException {
FileSystem fs = FileSystem.get(conf);
Path srcPath = new Path(remoteFilePath);
Path dstPath = new Path(remoteToFilePath);
boolean result = fs.rename(srcPath, dstPath);
fs.close();
return result;
}
/**
* 主函数
*/
public static void main(String[] args) {
Configuration conf = new Configuration();
conf.set("fs.default.name","hdfs://localhost:9000");
String remoteFilePath = "hdfs:///user/hadoop/text.txt"; // 源文件HDFS路径
String remoteToFilePath = "hdfs:///user/hadoop/input"; // 目的HDFS路径
try {
if ( HdfsApi.mv(conf, remoteFilePath, remoteToFilePath) ) {
System.out.println("将文件 " + remoteFilePath + " 移动到 " + remoteToFilePath);
} else {
System.out.println("操作失败(源文件不存在或移动失败)");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
(1)倒排索引
一、Map阶段实现
二、Combine阶段实现
三、Reduce阶段实现
四、Runner程序主类实现
(1)数据去重
一、Map阶段实现
二、Reduce阶段实现
三、Runner程序主类实现
(1)TopN排序
一、Map阶段实现
二、Reduce阶段实现
三、Runner程序主类实现