hadoop 基本概念
广义:以hadoop软件为主的生态圈(sqoop flume spark flink hbase kafka、 cdh环境 )
狭义: hadoop软件 本身 开源
Hadoop 版本:
实际上,当前Hadoop只有两个版本:Hadoop1.0和Hadoop 2.0。
Hadoop 1.0 :其中有三次版本0.20.x,0.21.x和0.22.x,0.20.x最后演化成1.0.x,变成了稳定版。
Hadoop1.0由一个分布式文件系统HDFS和一个离线计算框架MapReduce组成。
Hadoop 2.0(Hadoop):完全不同于Hadoop1.0,是一套全新的架构,包含一个支持NameNode横向扩展的HDFS,一个资源管理系统YARN和一个运行在YARN上的离线计算框架MapReduce。
Hadoop2.0主要由Yahoo独立出来的hortonworks公司主持开发。相比于Hadoop1.0,Hadoop 2.0功能更加强大,且具有更好的扩展性、性能,并支持多种计算框架。
Hadoop遵从Apache开源协议,基于开源Hadoop有各家发行版,如华为发行版、Intel发行版、Cloudera发行版(CDH)、Hortonworks发行版(HDP)、MapR等,所有这些发行版均是基于Apache Hadoop衍生出来的
CDH(ClouderaDistributionHadoop)。
截至目前为止,CDH共有4个版本,前两个不再更新。最近的两个CDH3和CDH4,分别对应Apache的Hadoop 1.0和Hadoop2.0。
-
官网:hadoop.apache.org 【apache顶级项目】
-
bug上报:https://issues.apache.org/jira
如 https://issues.apache.org/jira/browse/SPARK-2908 【SPARK-2908】组件名称大写-数字 ,表明该组件存在bug,确认是否修复
-
部署过程: Hadoop环境搭建过程记录
部署模式
Local (Standalone) Mode 本地模式 , 不使用
Pseudo-Distributed Mode 伪分布式 , 单个集群(一个NN,一个SNN,一个DN)
Fully-Distributed Mode 集群模式 , 生产环境用 (2个NN,多个DN)
hadoop存储组件
hdfs 存储数据 [分布式文件系统]
mapreduce 计算(作业) spark 、flink 的基础
yarn 资源(cpu memory)作业调度
HDFS架构设计
HDFS是一个主从架构,HDFS集群由一个NameNode和多个DataNode组成,NameNode保存了文件的元数据,DataNode保存了文件数据。
在伪分布式模式下,还有Secondary NameNode,对NameNode进行定时备份,在一定程度上保证集群的可靠性。
但是在生产环境中,一般会基于zookeeper,以两个NN做集群。一个NN Active,另一个NN Standby 实时等待。即部署两台NameNode,多台DataNode。
NameNode
别名:NN 、名称节点。维护数据的元数据
a. 文件的名称
b. 文件的目录结构、权限、大小、所属用户用户组 时间
c. 文件被切割哪些块----》块(和副本)分布在哪些DN节点上 blockmap 块映射
NameNode主要存储了文件的名称、目录结构、权限、大小、所属用户、用户组、时间等元数据信息。同时也根据DataNode的块报告(block report)在内存中存储了每个文件块到DataNode的映射关系,就是块映射(blockmap)。
NameNode不会持久化存储blockmap,而是通过集群启动和运行的时候,DN定时给NN汇报,然后NN在内存中动态维护这种映射关系。finalized和rbw都是实际存储数据的目录。
作用: 管理文件系统的命名空间。它维护着文件系统树及整棵树内所有的文件和目录。这些信息
以两个文件形式永久保存在本地磁盘上:命名空间镜像文件fsimage和编辑日志文件editlog
SNN
- 大数据早期,只有一个NN维护元数据,如果宕机,整个hdfs宕机,不可靠。
- 伪分布式模式,由SNN 定期来合并、 备份 、推送给NN,但间隔1小时备份一次,如果NN在中途宕机,只能从上一个检查点(checkpoint)恢复数据,有部分数据丢失。通过如下参数修改:
dfs.namenode.checkpoint.period 3600s [时间间隔1小时备份一次]
dfs.namenode.checkpoint.txns 1000000 [文件大小达到1000000也会触发备份]
官网提供所有hdfs-default的参数:https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml
// hadoop.tmp.dir 是因为在core-site.xml配置为了/home/liqiang/tmp/hadoop-${user.name}
[liqiang@gargantua current]$ cd /home/liqiang/tmp/hadoop-liqiang/dfs/name
edits 编辑日志文件、fsimage 镜像文件
-rw-rw-r-- 1 liqiang liqiang 42 Nov 28 09:07 edits_0000000000000000258-0000000000000000259
-rw-rw-r-- 1 liqiang liqiang 10576 Nov 28 09:07 edits_inprogress_0000000000000000260
-rw-rw-r-- 1 liqiang liqiang 2874 Nov 28 08:07 fsimage_0000000000000000257
过程:
1. SNN 将 NN的 fsimage_0000***257 和 edits_0000***258-0000***259 合并
2. 生成fsimage_0000***259文件
3. 再推送给NN
- 再后来取消SNN,而用两个NN做集群。一个NN Active,另一个NN Standby 实时等待。
DataNode
别名: DN 、 数据节点
作用:
-
存储数据块 和 块的校验
dfs/data/current/目录下,存储的是文件数据。该目录由dfs.datanode.data.dir参数指定
-
与Namenode通信:
a.每隔3秒发送一个心跳包
b.每十次心跳发送一次blockReport. 作用(主要):读写文件的数据块 -
定期给NN发送块报告。默认情况下每6个小时提交一个块报告。可以通过dfs.blockreport.intervalMsec(默认值:21600000)参数进行修改。
dfs.blockreport.intervalMsec 21600000ms=6h dfs.datanode.directoryscan.interval 21600s=6h
块 【dfs.blocksize】
- hadoop1.x 默认一个 blocksize 为 64M
- hadoop2.x 起 默认一个 blocksize 为 128M
数据在DN上是分块存储,大于128M的文件将会被切分成各块<=128M 的文件,小于128M的文件占据一个单独块。
如一个文件260M,将分成128M+128M+4M,一个DN中占据3个块。若集群3个DN[副本数(dfs.replication) 3],共占据3*3=9个块。
对于大量小文件,每个小文件单独占用一个块。浪费空间又增加NN维护元数据负担。
所以生产上:,要尽量规避小文件在HDFS的存储:
a. 数据在传输到hdfs之前,提前合并
b. 数据已经到了hdfs,就定时在业务低谷时期,去合并(冷)文件
hive [手动] 和 hbase [自带] 都有合并小文件的方法
HDFS文件读写流程
写流程
- hdfs client 调用 FileSystem.create(filePath)方法和NN进行rpc通信。
- NN会校验这个client的用户信息、权限、判断文件是否存在等;然后根据文件大小、块信息和DN节点的副本系数、集群情况,计算出当前文件可上传的DN节点信息,返回给client 的FsDataOutputStream 对象。
- client 调用FsDataOutputStream对象的write方法,根据副本放置策略,将第一个块放到DN1,DN1写完后再镜像写入到DN2(而不是从client写),再到DN3,当DN3写完后返回一个ack确认包给DN2,DN2拿到DN3的ack加上自己写完的ack一并返回给DN1,DN1最终返回给client。
- 当client收到ack,即所有的块都写完。client 调用FsDataOutputStream对象的 close方法关闭输出流。
- 再调用 FileSystem.complete方法,告诉NN文件写成功。
源码中有体现:调用 create方法,返回 FSDataOutputStream
FSDataOutputStream out = null;
try {
out = dstFS.create(dst, overwrite);
// ...
IOUtils.closeStream(out);
}
client:FileSystem.create()
NN:校验、计算DN,告诉 client的 FsDataOutputStream
client: FsDataOutputStream.write()
DN: 依次写完,依次返回ackq确认包给 client
client: FsDataOutputStream.close()
client:FileSystem.complete()
读流程
- hdfs client 调用 FileSystem.open(filePath)方法和NN进行rpc通信。
- NN 根据元数据信息,获得这个文件数据块的位置,返回给 client 的FSDataInputStream 对象.
- client 调用FSDataInputStream对象的read方法,从最近一台DN读取数据。
- DN 以packet为单位来校验被读取的数据,如果读取失败,则从下一个节点读取,且以后都不会在本节点读取。
- client 关闭输入流。
client:FileSystem.open()
NN:获取文件数据块的位置,告诉 client的 FsDataOutputStream
client: FsDataOutputStream.read()
DN: 校验读取的数据,如果失败则换下一节点
client: FsDataOutputStream.close()
client:FileSystem.complete()
副本放置策略
最简单的放置策略:直接将3个副本放置在三个不同机架的服务器上。
尽可能保证了高可用,但是文件写入网络IO成本高。
理论上最优的放置策略:
- 第一副本:放置在写入程序所在的节点有DataNode。如果是集群外提交,则随机挑选一台磁盘不太慢、CPU不太忙的节点上;
- 第二副本:放置在于第一个副本不同的机架的节点上;
- 第三副本:与第二个副本相同机架的不同节点上;
- 如果还有更多的副本:随机放在节点中;
生产环境放置策略:
在生产上,一般有一台单独的类似于堡垒机的机器作为写入程序的单点客户端,该节点机器上既没有NameNode,也没有DataNode。
这样的好处是,可以限制客户端的权限,从而放置集群的节点被误操作。
另外,在万兆带宽的局域网环境中,网络IO其实还好,该副本放置策略带来的网络消耗可以忽略不计。