初学大数据之—Apache Hadoop
-
背景
随着信息化互联网|物联网发展要求,万物互联趋势势在必 行。随之引发架构的演变由单一架构向高并发分布式架构演 变。数据的存储也开始由原始的单机存储演变为分布式存储。
1)JavaWeb:为了应对高并发和分布式提出的是LNMP(Linux、 Nginx、MySQL、PHP)思想。
2)海量数据存储|数据分析 :存储方案(HDFS)、计算方案 (Map Reduce、Storm 、 Spark 、 Flink)
大数据背景
分布式:服务间出现跨机器、跨进程通信同一称为分布式
存储——>
- 单机存储:容量限制、扩展性差、数据灾备问题
- 分布式存储:使用存储的集群实现对海量数据的并行化 的读写,提升系统写的吞吐能力。目前针对传统业务领 域的分布式文件存储方案有
文件存储、块存储。
计算(分析)——>- 单机分析/计算:慢,受限于单机存储的内存、CPU、网络限制
- 分布式计算:将计算任务交给专门的计算集群负责任务 的计算。打破单机计算的瓶颈,实现并行计算,模拟多核CPU的计算能力。可以实现在一定的时间内达到对数 据的有效分析。
Hadoop 出现
为了解决海量数据引发的一系列问题,人们通过借鉴Googl发 布Google File System和simple Data processing on large cluster 的论文在早期的Nutch项目中实现了Hadoop的雏形,早期在 Nutch中有两个板块:NDFS(Nutch Distribute File System)、MapReduce分别解决该工程的存储和计算两个问题,而后将该板块冲Nutch中剥离形成独立的模块,最后更名为Hadoop。
- HDFS :Hadoop Distribute File System 分布式文件存储。
- MapReduce :分发–>汇总 ,MapReduce是hadoop中通用的 分布式并行计算框架。
下载地 址:https://www.apache.org/dyn/closer.cgi/hadoop/common/h adoop-2.9.2/hadoop-2.9.2.tar.gz
环境搭建
在下面链接中可以有完整的Hadoop的安装教程以及网盘资料
https://blog.csdn.net/qq_41885073/article/details/108814846
HDFS架构
简介
-
Hadoop分布式文件系统(HDFS)是指被设计成适合运行在通用 硬件(commodity hardware)上的分布式文件系统(Distributed File System)。它和现有的分布式文件系统有很多共同点。但同时,它和其他的分布式文件系统的区别也是很明显的。HDFS是一个高度容错性的系统,适合部署在廉价的机器上。HDFS能提供高吞吐量的数据访问,非常适合大规模数据集上的应用。HDFS放宽了一部分POSIX约束,来实现流式读取文件系统数据的目的。HDFS在最开始是作为Apache Nutch搜索引擎项目的基础架构而开发。HDFS是Apache Hadoop Core项目的 一部分。
-
HDFS有着高容错性(fault-tolerant)的特点,并且设计用来部署在低廉的(low-cost)硬件上。而且它提供高吞吐量(high throughput)来访问应用程序的数据,适合那些有着超大数据集(large data set)的应用程序。
架构
NameNode & DataNodes
HDFS是一个master/slave架构,一个HDFS的集群包含一个NameNode,该服务是主服务负责管管文件系统的Namespace和 响应客户端的常规访问。另外,有很多个DataNode节点,每个DataNode负责管理存储在DataNode运行所在主机上得文件。 HDFS暴露了一个文件系统Namespace以及允许将用户数据存储到文件里。HDFS底层会将文件切分成1~N个块,这些块被存储在一系列的DataNode上,NameNode负责修改Namespace的 DDL操作例如:打开、关闭、修改文件或者文件夹。 NameNode决定了数据块到DataNode的映射。DataNode负责响 应客户端的读写请求,同时在接收到来自于NameNode的指令 DataNode还要进行块的创建、删除、复制等操作。
- NameNode :使用内存存储集群中的元数据(文件命名空间-文 件目录结构、数据块到DataNode映射)
- DataNode :负责响应客户端对数据块的读写请求,向 NameNode汇报自身状态信息。 Block :是HDFS切分文件的尺度,默认是128MB,一个文件最 多只有 一个不足128MB块
- 副本因子 :HDFS为了防止DataNode宕机导致块的丢失,允许 一个块又多个备份,默认备份是3
为什么HDFS不擅长存储小文件?
因为Namenode使用单机的内存存储,因此由于小文件会占用 更多的内存空间,导致了Namenode内存浪费。
什么是机架感知?
分布式的集群通常包含非常多的机器,由于受到机架槽位 和交换机网口的限制,通常大型的分布式集群都会跨好几 个机架,由多个机架上的机器共同组成一个分布式集群。 机架内的机器之间的网络速度通常都会高于跨机架机器之 间的网络速度,并且机架之间机器的网络通信通常受到上 层交换机间网络带宽的限制。 Hadoop在设计时考虑到数据的安全与高效,数据文件默认 在HDFS上存放三份,存储策略为:
(1)第一个block副本放在客户端所在的数据节点里(如果客户 端不在集群范围内,则从整个集群中随机选择一个合适的 数据节点来存放)。
(2)第二个副本放置在与第一个副本所在节点相同机架内的其 它数据节点上
(3)第三个副本放置在不同机架的节点上样如果本地数据损坏,节点可以从同一机架内的相邻节点拿 到数据,速度肯定比从跨机架节点上拿数据要快;同时,如果 整个机架的网络出现异常,也能保证在其它机架的节点上找到 数据。为了降低整体的带宽消耗和读取延时,HDFS会尽量让 读取程序读取离它最近的副本。如果在读取程序的同一个机架 上有一个副本,那么就读取该副本。如果一个HDFS集群跨越 多个数据中心,那么客户端也将首先读本地数据中心的副本。
参考:https://www.cnblogs.com/zwgblog/p/7096875.html
SecondaryNameNode & NameNode
- fsimage :存储在Namenode服务所在物理主机磁盘上的一个二 进制文本文件。记录了元数据信息
- edits :存储在Namenode服务所在物理主机磁盘上的一个二进 制文本文件,记录了对元数据修改操作。
当第一次启动Namenode服务的时候,系统会加载fsimage和 edits文件进行合并得到最新元数据信息,并且更新fsimage和edits,一旦服务启动成功后,在服务运行期间不再更新 fsimage,只是将操作记录在edits中。导致menode在长期运行之后重启导致namenode启动时间过长,还可能导致edits文 件过大。因此Hadoop HDFS引入Secondary Namenode 辅助 Namenode在运行期间完成对元数据的整理。
NameNode启动过程
NameNode的SafeMode
在启动过程中,NameNode会进入一个特殊的状态称为 Safemode.HDFS在处于安全模式下不会进行数据块的复制。 NameNode在安全模式下接收来自DataNode的心跳和 Blockreport信息,每个DataNode的块的汇报信息中包含了该物 理主机上所持有的所有的数据块的信息。Name会在启动时候 检查所有汇报的块是否满足设置的最小副本数(默认值1), 只要块达到了最小副本数,才认得当前块是安全的。 NameNode等待30秒然后尝试检查汇报的所谓的安全的块的比 例有没有达到99.9%,如果达到该阈值,NameNode自动退出 安全模式。然后开始检查块的副本数有没有低于配置的副本 数,然后发送复制指令,进行块的复制。
注意:HDFS在启动的时候会自动进入和退出安全模式,一般 在生产一般有时候也会让HDFS强制进入安全模式,进而对服 务器进行维护。
下面是几个简单的命令大家可以参考一下
#启动HDFS服务
start-dfs.sh
#关闭HDFS服务
stop-dfs.sh
#查看Namenode是否是安全模式
hdfs dfsadmin -safemode get
#开启Namenode安全模式
hdfs dfsadmin -safemode enter
#关闭Namenode安全模式
hdfs dfsadmin -safemode leave
#文件存储
hdfs dfs -put 文件名
SSH免密码认证
SSH 为建立在应用层基础上的安全协议。SSH 是较可靠,专为 远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。提供的登 录方式有两种:
- 基于口令的安全验证 - 有可能远程主机冒充目标主机,截获 用户信息。
- 密匙的安全验证 -需要认证的是机器的身份。
(1)生公私钥对,可选RSA或者DSA算法
ssh-keygen -t rsa
#后面的一直按回车
(2)将本机的公钥添加到目标主机的授信列表文件
ssh-copy-id root@CentOS
#第一次后面的一直按回车 如果出现选择 就选yes 输入本机密码
Trash回收站
HDFS为了规避由于用户的误操作,导致的数据删除丢失,用 户可以在构建HDFS的时候,配置HDFS的垃圾回收功能。所谓 的垃圾回收,本质上是在用户删除文件的时候,系统并不会立 即删除文件,仅仅是将文件移动到垃圾回收的目录。然后更具 配置的时间,一旦超过该时间,系统会删除该文件,用户需要 在到期之前,将回收站的文件移除垃圾站,即可避免删除。
- 开启垃圾回收,需要在core-site.xml中添加如下配置,然后重 启hdfs即可
<!--垃圾回收,5 minites-->
<property>
<name>fs.trash.interval</name>
<value>5</value>
</property>
```powershell
#到这个目录下 才能找到core-sit文件
[root@CentOS ~]# cd /usr/hadoop-2.9.2
[root@CentOS hadoop-2.9.2]# vi etc/hadoop/core-site.xml
#将上面的代码粘贴到<configuration>标签中
目录结构
[root@CentOS ~]# tree -L 1 /usr/hadoop-2.9.2/
/usr/hadoop-2.9.2/
├── bin # 系统脚本,hdfs、hadoop、yarn
├── etc # 配置目录xml、文本文件
├── include # 一些C的头文件,无需关注
├── lib # 第三方native实现C实现
├── libexec # hadoop运行时候,加载配置的脚本
├── LICENSE.txt
├── logs # 系统运行日志目录,排查故障!
├── NOTICE.txt
├── README.txt
├── sbin # 用户脚本,通常用于启动服务例如:start|top- dfs.sh、
└── share # hadoop运行的依赖jars、内嵌webapp
HDFS实践
HDFS Shell 命令(经常用)
- √打印hadoop类路径 [root@CentOS ~]# hdfs classpath
- √格式化NameNode [root@CentOS ~]# hdfs namenode -format
- dfsadmin命令
(1)可以使用-report -live或者-dead查看集群中dataNode节点状态
[root@CentOS ~]# hdfs dfsadmin -report -live
(2)使用-safemode enter|leave|get等操作安全模式
[root@CentOS ~]# hdfs dfsadmin -safemode get
Safe mode is OFF
(3)查看集群网络拓扑
[root@CentOS ~]# hdfs dfsadmin -printTopology Rack: /default-rack 192.168.73.130:50010 (CentOS)
检查某个目录状态
[root@CentOS ~]# hdfs fsck /
更多请参考:https://hadoop.apache.org/docs/stable/hadoop- project-dist/hadoop-hdfs/HDFSCommands.html#dfsadmin
- √DFS命令
[root@CentOS ~]# hdfs dfs -命令 选项
或者老版本写法
[root@CentOS ~]# hadoop fs -命令 选项
"-appendToFile"
将anaconda-ks.cfg 追加到aa.log中
[root@CentOS ~]# hdfs dfs -appendToFile /root/anaconda-ks.cfg /aa.log
[root@CentOS ~]# hdfs dfs -appendToFile /root/anaconda-ks.cfg /aa.log
"-cat"
查看文件内容
[root@CentOS ~]# hdfs dfs -cat /aa.log
等价
[root@CentOS ~]# hdfs dfs -cat hdfs://CentOS:9000/aa.log
"-chmod"
修改文件权限
[root@CentOS ~]# hdfs dfs -chmod -R u+x /aa.log
[root@CentOS ~]# hdfs dfs -chmod -R o+x /aa.log
[root@CentOS ~]# hdfs dfs -chmod -R a+x /aa.log
[root@CentOS ~]# hdfs dfs -chmod -R a-x /aa.log
"-copyFromLocal/-copyToLocal"
copyFromLocal本地上传到HDFS;copyToLocal从HDFS上下载文件
[root@CentOS ~]# hdfs dfs -copyFromLocal jdk-8u191- linux-x64.rpm
[root@CentOS ~]# rm -rf jdk-8u191-linux-x64.rpm
[root@CentOS ~]# hdfs dfs -copyToLocal /jdk-8u191- linux-x64.rpm /root/
[root@CentOS ~]# ls anaconda-ks.cfg hadoop-2.9.2.tar.gz jdk-8u191- linux-x64.rpm
"-moveToLocal/moveFromLocal "
moveToLocal先下载文件,然后删除远程数据;moveFromLocal :先上传,再删除本地
[root@CentOS ~]# hdfs dfs -moveFromLocal jdk-8u191- linux-x64.rpm /dir1
[root@CentOS ~]# ls anaconda-ks.cfg hadoop-2.9.2.tar.gz
[root@CentOS ~]# hdfs dfs -moveToLocal /dir1/jdk- 8u191-linux-x64.rpm /root moveToLocal: Option '-moveToLocal' is not implemented yet.
"-put/get"
文件上传/下载
[root@CentOS ~]# hdfs dfs -get /dir1/jdk-8u191- linux-x64.rpm /root
[root@CentOS ~]# ls anaconda-ks.cfg hadoop-2.9.2.tar.gz jdk-8u191- linux-x64.rpm
[root@CentOS ~]# hdfs dfs -put hadoop-2.9.2.tar.gz /dir1
更多命令请使用
[root@CentOS ~]# hdfs dfs -help 命令
例如,想知道touchz该如何使用
[root@CentOS ~]# hdfs dfs -touchz /dir1/Helloworld.java
[root@CentOS ~]# hdfs dfs -ls /dir1/
Found 5 items -rw-r--r-- 1 root supergroup 0 2020-09- 25 23:47 /dir1/Helloworld.java
drwxr-xr-x - root supergroup 0 2020-09- 25 23:07 /dir1/d1
drwxr-xr-x - root supergroup 0 2020-09- 25 23:09 /dir1/d2
-rw-r--r-- 1 root supergroup 366447449 2020-09- 25 23:43 /dir1/hadoop-2.9.2.tar.gz
-rw-r--r-- 1 root supergroup 176154027 2020-09- 25 23:41 /dir1/jdk-8u191-linux-x64.rpm
Java API操作HDFS(了解)
- 搭建开发步骤,创建一个Maven的项目(不用选择任何模 板),在pom.xml文件中添加如下依赖
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.9.2</version>
</dependency>
</dependencies>
2.配置windows开发环境(很重要)
- 需要将hadoop-2.9.2解压在window的指定目录下,比如这里 我们解压在C:/目录下 在Windows系统的环境变量中添加HADOOP_HOME环境变量
- 将hadoop-window-master.zip中的bin目录下的文件全部拷贝到HADOOP_HOME%/bin目录下进行覆盖
- 重启IDEA否则集成开发环境不识别配置HADOOP_HOME环境变量
3.建议将core-site.xml和hdfs-site.xml文件拷贝到项目的 resources目录下
4.在Windows上配置主机名和IP的映射关系
5.创建FileSystem和Configuration对象
public static FileSystem fs=null;
public static Configuration conf=null;
static {
try { conf= new Configuration();
conf.addResource("core-site.xml");
conf.addResource("hdfs-site.xml");
fs=FileSystem.get(conf);
} catch (IOException e) {
e.printStackTrace();
}
}
- 文件上传
Path src = new Path("file://xx路径");
Path dst = new Path("/");
fs.copyFromLocalFile(src,dst);
-------------------------------
//流的方式
InputStream in=new FileInputStream("file://xx路 径");
Path dst = new Path("/xx路径");
OutputStream os=fs.create(dst);
IOUtils.copyBytes(in,os,1024,true);
- 文件下载
Path dst = new Path("file://xx路径");
Path src = new Path("/xx路径");
fs.copyToLocalFile(src,dst);
-------------------------------
//流的方式
Path dst = new Path("/xx路径");
InputStream in= fs.open(dst);
OutputStream os=new FileOutputStream("file://xx路 径");
IOUtils.copyBytes(in,os,1024,true);
- 删除文件
Path dst = new Path("/system");
fs.delete(dst,true);
- 回收站
Path dst = new Path("/aa.log");
Trash trash=new Trash(fs,conf);
trash.moveToTrash(dst);
- 所有文件
Path dst = new Path("/");
RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(dst, true);
while (listFiles.hasNext()){
LocatedFileStatus fileStatus = listFiles.next();
System.out.println(fileStatus.getPath()+" "+fileStatus.isDirectory()+" "+fileStatus.getLen());
}
- 所有文件或文件夹
Path dst = new Path("/");
FileStatus[] fileStatuses = fs.listStatus(dst);
for (FileStatus fileStatus : fileStatuses) {
System.out.println(fileStatus.getPath()+" "+fileStatus.isDirectory());
}