一、定义:

狭义上来说, hadoop 就是单独指代 hadoop 这个软件,
广义上来说, hadoop 指代大数据的一个生态圈,包括很多其他的软件
二、分布式文件系统架构
分布式文件系统:将数据存放在多台电脑上存储。
分布式文件系统很多,HDFS是mapreduce计算的基础。
2.1 文件切分思想

源文件直接存放在一个磁盘上效率肯定很低(读取效率低,如果文件太大会超出单机存储的范围)

字节数组:文件在磁盘上真实存储文件的抽象概念

数组可以进行拆分合并,源文件不会收到影响。

切分数据:对数组进行拆分

拼接数据:按照数组偏移量将字节数组拼接到一起。

偏移量:当前数据在数组中的相对位置,可以理解为下标。

数组都有对应的下标,可以快速的定位数据。

不管文件的的大小,所有的文件都是由字节数组构成
如果我们要切分文件 , 就是将一个字节数组分成多份
我们将切分后的数据拼接到一起,数据可以继续使用
我们需要根据数据的偏移量将他们重新拼接到一起
2.2 Block拆分标准
拆分的数据快需要等大
数据计算的时候简化问题的复杂度
进行分布式算法设计的时候,数据不统一,算法很难设计
数据拉取的时候时间相对一致
通过偏移量就知道这个块的位置
相同文件,分成的数据块大小应该相等
数据块 Block
数据被切分后的一个整体称之为块
H1 默认大小为 64M, H2 及其以后默认大小为 128M
同一个文件中,每个数据块大小要一致除了最后一个节点外
不同文件中,块的大小可以不一致
文件大小不同可以设置不同的块的数量
真实情况下,会根据文件大小和集群节点的数量综合考虑块的大小
数据块的个数 =Ceil
文件大小 / 每个块的大小)
注意事项
HDFS 中一旦文件被存储,数据不允许被修改
修改会影响偏移量
修改会导致数据倾斜
修改数据会导致蝴蝶效益
但是可以被追加,但是不推荐
追加设置需要手动打开
一般 HDFS 存储的都是历史数据。所以 将来 Hadoop mr 都用来进行离线数据的处理
块的大小一旦文件上传之后就不允许被修改
128m -512M
如果数据文件的切割点 128M 整好是一个单词的中间部分,切分数据如何保证数据的完整性?

2.3 Block数据安全

肯定要对存储数据做备份
备份的数据肯定不能存放在一个节点上
使用数据的时候可以就近获取数据
所以备份的数量要小于等于节点的数量
每个数据块会有 3 个副本,相同副本是不会存放在同一个节点上
副本的数量可以变更
可能近期的数据被分析的可能性跟大,副本数可以多设置几个
后期数据很少被分析,可以减少副本数
2.4. Block 的管理效率
需要专门给节点进行分工
存储 DataNode
记录 NameNode
日志 secondaryNameNode
2.5. HDFS 的特点
优点
a) 高容错性
i. 保存多个副本,且提供容错机制。
ii. 副本丢失或宕机自动恢复。默认存 3 份。
b) 运行在廉价的机器上(商用机)
i. 通过副本提高可靠性
ii. 提供了容错和恢复机制
c) 适合批处理
i. 移动计算而非数据
ii. 数据位置暴露给计算框架。 NameNode 上有位置
d) 适合大数据的处理
i.TB ,甚至 PB 级数据
ii. 百万规模以上的文件数量
iii.10K+ 节点规模
e) 流式数据访问
i. 一次写入,多次读取,高吞吐量,所以可以同时处理大量数据
缺点
a) 不擅长低延迟数据访问
比如毫秒级
b) 不擅长小文件的分区
i. 占用 NameNode 大量内存
ii. 磁盘寻道时间超过读取时间
c) 不擅长并发写入,文件随机修改
i. 一个文件只能有一个写入者
ii. 仅支持 append, 也就是添加(有组件实现删等)
三、NameNode
3.1 功能
接受客户端的读写服务
NameNode 存放文件与 Block 的映射关系
NameNode 会记录 Block DataNode 的映射关系,但是不会持久化
保存文件的元数据信息
文件的归属
文件的权限
文件的大小时间
Block 信息,但是 block 的位置信息不会持久化 , 需要每次开启集群的时候 DN 上报
收集 Block 的信息
系统启动时
NN 关机的时候是不会存储任意的 Block DN 的映射信息
DN 启动的时候,会将自己节点上存储的 Block 信息汇报给 NN
NN 接受请求之后重新生成映射关系
Block--DN3
如果某个数据块的副本数小于设置数,那么 NN 会将这个副本拷贝到其他节点
集群运行中
NN DN 保持心跳机制 , 三秒钟发送一次
如果客户端需要读取或者上传数据的时候, NN 可以知道 DN 的健康情况
可以让客户端读取存活的 DN 节点
如果 DN 超过三秒没有心跳,就认为 DN 出现异常
不会让新的数据读写到 DataNode
- 客户访问的时候不提供异常结点的地址
如果 DN 超过 10 分钟 +30 秒没有心跳,那么 NN 会将当前 DN 存储的数据转存到其他节点
超时时长的计算公式为: timeout = 2 * heartbeat.recheck.interval + 10 *
dfs.heartbeat.interval 。 而默认的 heartbeat.recheck.interval 大小为 5 分钟,
dfs.heartbeat.interval 默认为 3 秒。
3.2 性能
NameNode 为了效率,将所有的操作都在内存中完成
NameNode 不会和磁盘进行任何的数据交换
问题 :
数据的持久化
数据保存在内存中,掉电易失

 四、DataNode

4.1 功能

存放的是文件的数据信息和验证文件完整性的校验信息
数据会存放在硬盘上
1m=1 条元数据 1G=1 条元数据
NameNode 非常排斥存储小文件,一般小文件在存储之前需要进行压缩
汇报
启动时
汇报之前先验证 Block 文件是否被损坏
NN 汇报当前 DN block 的信息
运行中
NN 保持心跳机制
客户可以向 DN 读写数据,
当客户端读写数据的时候,首先去 NN 查询 file block dn 的映射
然后客户端直接与 dn 建立连接,然后读写数据
五、 SecondaryNameNode
5.1 传统解决方案
日志机制
做任何操作之前先记录日志
NN 下次启动的时候,只需要重新按照以前的日志 重做 一遍即可
缺点
edits 文件大小不可控,随着时间的发展,集群启动的时间会越来越长
有可能日志中存在大量的无效日志
优点
绝对不会丢失数据
拍摄快照
我们可以将内存中的数据写出到硬盘上
序列化
启动时还可以将硬盘上的数据写回到内存中
反序列化
缺点
关机时间过长
如果是异常关机,数据还在内存中,没法写入到硬盘
如果写出频率过高,导致内存使用效率低( stop the world JVM
优点
启动时间较短
5.2 SNN解决方案
解决思路(日志edit+快照fsimage)
        让日志大小可控
        快照定时保存
NameNode文件目录
        查看目录

/var/yjx/hadoop/full/dfs/name/current
edits_0000000000000000001-0000000000000000019
edits_inprogress_0000000000000000020
        当前正在执行操作的日志信息
        这些日志信息还没有被合并到镜像中
fsimage_0000000000000000000
fsimage_0000000000000000000.md5
fsimage_0000000000000000019
fsimage_0000000000000000019.md5
        完整性校验规则
seen_txid -->19
VERSION
解决方案
        当我们启动一个集群的时候,会产生四个文件
edits_0000000000000000001
fsimage_ edits_000000000000000000
seen_txid
VERSION
我们每次操作都会记录日志-->edits-inprogress- edits_00000001
随着时间的推移,日志文件会越来越大-当达到阈值的时候(64M或3600秒)
会生成新的日志文件
edits_inprogress-000000001 -->edits_0000001
创建新的日志文件 edits_inprogress-0000000016

 

 

六、安全模式
集群启动时的一个状态
安全模式是 HDFS 的一种工作状态,处于安全模式的状态下,只向客户端提供文件的只读视
图,不接受对命名空间的修改;同时 NameNode 节点也不会进行数据块的复制或者删除,
NameNode 启动时,
首先将镜像文件( fsimage )载入内存,并执行编辑日志( edits )中的各项操作。
一旦在内存中成功建立文件系统元数据的映像,则创建一个新的 fsimage 文件和一个空的编辑
日志。
NameNode 开始监听 RPC Http 请求。
此时 NameNode 处于安全模式,只接受客户端的读请求。
系统中的数据块的位置并不是由 NameNode 维护的,而是以块列表的形式存储在 DataNode 中。
[root@node01 ~]# rm -rf /var/yjx/hadoop/full/dfs/name/current/*
[root@node01 ~]# scp -r
root@node02:/var/yjx/hadoop/full/dfs/namesecondary/current/*
/var/yjx/hadoop/full/dfs/name/current 安全模式下
安全模式下,各个 DataNode 会向 NameNode 发送自身的数据块列表
NameNode 有足够的数据块信息后,便在 30 秒后退出安全模式
NameNode 发现数据节点过少会启动数据块复制过程
如果 NN 收集的 Block 信息没有达到最少副本数,就会将缺失的副本 , 从有的 DN 上拷贝到其他 DN
dfs.replication.min=2
但是默认最低副本数为 1
在拷贝的过程中系统还是处于安全模式
安全模式相关命令
hadoop dfsadmin -safemode leave 强制 NameNode 退出安全模式
hadoop dfsadmin -safemode enter 进入安全模式
hadoop dfsadmin -safemode get 查看安全模式状态
hadoop dfsadmin -safemode wait 等待一直到安全模式结束

七、HDFS权限

HDFS 对权限的控制
        只能防止好人做错事
        不能防止坏人做坏事
你告诉他你是谁,他就认为你是谁!

八、机架感知策略

8.1 节点距离

distance(/D1/R1/H1,/D1/R1/H1)=0 相同的 datanode
distance(/D1/R1/H1,/D1/R1/H3)=2 同一 rack 下的不同 datanode
distance(/D1/R1/H1,/D1/R2/H4)=4 同一 IDC 下的不同 datanode
distance(/D1/R1/H1,/D2/R3/H7)=6 不同 IDC 下的 datanode
8.2 机架感知
机架感知是为了保证副本在集群中的安全性
我们需要将节点放在不同的DN节点上,节点也需要一定的考量
        可靠性,可用性,带宽消耗
第一个节点:
        集群内部(优先考虑和客户端相同的节点作为第一个节点)
        集群外部(选择资源丰富且不繁忙的节点作为第一个节点)
第二个节点:
        第二个节点选择与第一个节点不同机架的其他节点
第三个节点:
        与第二个相同机架相同的其他节点
第N个节点:
        与前面节点不重复的其他节点

九、HDFS写数据流程

 写数据就是将客户端上的数据上传到HDFS

9.1 宏观过程

 1.客户端向HDFS发送写数据请求

        hdfs dfs -put tomcat.tar.gz /yjx/

  2.  filesystem通过rpc调用namenode的create方法

        nn首先检查是否有足够的空间权限等条件创建这个文件,或者这个路径是否已经存在,权限

        有:NN会针对这个文件创建一个空的Entry对象,并返回成功状态给DFS        

        没有:直接抛出对应的异常,给予客户端错误提示信息

3.如果DFS接收到成功的状态,会创建一个FSDataOutputStream的对象给客户端使用

4.客户端要向nn询问第一个Block存放的位置

        NN通过机架感知策略 (node1 node 2 node8)

5.需要将客户端和DN节点创建连接

        pipeline(管道)

        客户端和node1 创建连接 socket
        node1和 node2 创建连接 socket
        node2 和 Node8 创建连接 socket
6.客户端按照文件块切分数据,但是按照packet发送数据

        默认一个packet大小为64K,Block128M2048packet

7.客户端通过pipeline管道开始使用FDSOutputStream对象将数据输出

        1. 客户端首先将一个 packet 发送给 node1, 同时给予 node1 一个 ack 状态
        2. node1接受数据后会将数据继续传递给 node2, 同时给予 node2 一个 ack 状态
        3. node2接受数据后会将数据继续传递给 node8, 同时给予 node8 一个 ack 状态
        4. node8将这个 packet 接受完成后,会响应这个 ack node2 true
        5. node2会响应给 node1 , 同理 node1 响应给客户端
8. 客户端接收到成功的状态 , 就认为某个 packet 发送成功了,直到当前块所有的 packet 都发送完成
9. 如果客户端接收到最后一个 pakcet 的成功状态 , 说明当前 block 传输完成,管道就会被撤销
10. 客户端会将这个消息传递给 NN NN 确认传输完成
        1. NN会将 block 的信息记录到 Entry, 客户端会继续向 NN 询问第二个块的存储位置 , 依次类推
        2. block1 (node1 node2 node8)
        3. block2 (node1 node8 node9)
        4. ....
        5. blockn(node1 node7 node9)
11. 当所有的 block 传输完成后, NN Entry 中存储所有的 File Block DN 的映射关系关闭
        FsDataOutPutStream
9.2 微观过程
1.客户端首先从自己的硬盘中以流的形式将自己的数据读取到缓存中
2.然后将缓存中的数据以chunk(512B)和checksum(4B)的方式放入到packet(64k)
        
        1. chunk:checksum=128:1
        2. checksum:在数据处理和数据通信领域中,用于校验目的的一组数据项的和
        3. Packet中的数据分为两类,一类是实际数据包,另一类是 header 包。
        4. 一个 Packet 数据包的组成结构
3.当packet满的时候添加到dataqueue
4.datastreamer开始从dataqueue队列上读取一个packet,通过FDSDataOPS发送到Poepleline
         在取出的时候,也会将 packet 加入到 ackQueue, 典型的生产者消费者模式
5. 客户端发送一个 Packet 数据包以后开始接收 ack ,会有一个用来接收 ack ResponseProcessor
程,如果收到成功的 ack
        
        1. 如果某一个 packet ack true, 那么就从 ackqueue 删除掉这个 packet
        2. 如果某一个 packet ack false, ackqueue 中所有的 packet 重新挂载到 发送队列 , 重新发送

 十、HDFS读数据流程

首先客户端发送请求到 DFS ,申请读取某一个文件
/yjx/tomcat.tar.gz
DFS NN 查找这个文件的信息 ( 权限 , 文件是否存在 )
如果文件不存在,抛出指定的错误
如果文件存在,返回成功状态
DFS 创建 FSDataInputStream 对象,客户端通过这个对象读取数据
客户端获取文件第一个 Block 信息 , 返回 DN1 DN2 DN8
客户端直接就近原则选择 DN1 对应的数据即可
依次类推读取其他块的信息,直到最后一个块 , Block 合并成一个文件
关闭 FSDataInputStream
十一、Hadoop1 的困境
单点故障
每个群集只有一个 NameNode NameNode 存在单点故障( SPOF )。
如果该计算机或进程不可用,则整个群集在整个 NameNode 重新启动或在另一台计算机上启
动之前将不可用
如果发生意外事件(例如机器崩溃),则在操作员重新启动 NameNode 之前,群集将不可
用。
计划内的维护事件,例如 NameNode 计算机上的软件或硬件升级,将导致群集停机时间的延
长。
水平扩展
将来服务器启动的时候,启动速度慢
namenode 随着业务的增多,内存占用也会越来越多
如果 namenode 内存占满,将无法继续提供服务
业务隔离性差
存储:有可能我们需要存储不同部门的数据
计算:有可能存在不同业务的计算流程
项目后期 namenode 的吞吐量将会是集群的瓶颈
客户端所有的请求都会先访问 NameNode
Hadoop2.x
NameNode 节点的高可用
HA--high availability
NameNode 业余的水平扩展
Federation
十二、Hadoop-HA
12.1 设计思想
hadoop2.x 启用了主备节点切换模式(1主 1 备)
当主节点出现异常的时候,集群直接将备用节点切换成主节点
要求备用节点马上就要工作
主备节点内存几乎同步
有独立的线程对主备节点进行监控健康状态
需要有一定的选举机制,帮助我们确定主从关系
我们需要实时存储日志的中间件
12.2 ANN
Active NameNode 的功能和原理的 NN 的功能是一样的
接受客户端请求,查询数据块 DN 信息
存储数据的元数据信息
数据文件: Block DN 的映射关系
工作
启动时:接受 DN block 汇报
运行时:和 DN 保持心跳 (3s,10m30s)
存储介质
完全基于内存
优点:数据处理效率高
缺点:数据的持久化 ( 日志 edits+ 快照 fsimage)
12.3 SNN
Standby NameNode NN 的备用节点
他和主节点做同样的工作,但是它不会发出任何指令
存储:数据的元数据信息
数据文件: Block DN 的映射关系
它的内存数据和主节点内存数据几乎是一致的
工作:
启动时:
接受 DN block 汇报
运行时:
DN 保持心跳 (3s,10m30s)
存储介质
完全基于内存
优点:数据处理效率高
缺点:数据的持久化
合并日志文件和镜像
当搭建好集群的时候,格式化主备节点的时候, ANN SNN 都会会默认创建
fsimage_000000000000000
当我们操作 HDFS 的时候 ANN 会产生日志信息
edits_inprogress_0000000000001
主节点会将日志文件中新增的数据同步到 JournalNode 集群上 所以只需要 snn 有操作的日志信息,就可以合并 fsImage edits 信息 , 理论上是一直在合并数据
fsimage --> 初始化创建
edits--> JournalNode 集群上定时同步
只要同步到 edits 文件,就开始于 fsimage 合并
当达到阈值的时候,直接拍摄快照即可
SNN 将合并好的 Fsimage 发送给 ANN,ANN 验证无误后,存放到自己的目录中
12.4 DataNode(DN)
存储
文件的 Block 数据
介质
硬盘
启动时:
同时向两个 NN 汇报 Block 信息
运行中
同时和两个 NN 节点保持心跳机制
12.5 QJM
Quorum JournalNode Manager 共享存储系统, NameNode 通过共享存储系统实现日志数据同
步。
JournalNode 是一个独立的小集群,它的实现原理和 Zookeeper 的一致 ( Paxos)
ANN 产生日志文件的时候,就会同时发送到 JournalNode 的集群中每个节点上
JournalNode 不要求所有的 jn 节点都接收到日志,只要有半数以上的( n/2+1 )节点接受收到日
志,那么本条日志就生效
SNN 每间隔一段时间就去 QJM 上面取回最新的日志
SNN 上的日志有可能不是最新的
HA 集群的状态正确至关重要,一次只能有一个 NameNode 处于活动状态。
JournalNode 只允许单个 NameNode 成为作者。在故障转移期间,将变为活动状态的 NameNode
将承担写入 JournalNodes 的角色,这将有效地防止另一个 NameNode 继续处于活动状态,从而使
新的 Active 节点可以安全地进行故障转移。
12.6 ZKFC
Failover Controller( 故障转移控制器 )
NameNode 的主备切换进行总体控制,能及时检测到 NameNode 的健康状况
在主 NameNode 故障时借助 Zookeeper 实现自动的主备选举和切换
为了防止因为 NN GC 失败导致心跳受影响, ZKFC 作为一个 deamon 进程从 NN 分离出来
启动时:
当集群启动时,主备节点的概念是很模糊的
ZKFC 只检查到一个节点是健康状态,直接将其设置为主节点
zkfc 检查到两个 NN 节点是的健康状态,发起投票机制
选出一个主节点,一个备用节点,并修改主备节点的状态
运行时:
ZKFailoverController HealthMonitor ActiveStandbyElector 3 个组件来协同实现
主备切换
ZKFailoverController 启动的时候会创建 HealthMonitor ActiveStandbyElector 这两
个主要的内部组件
HealthMonitor 主要负责检测 NameNode 的健康状态
ActiveStandbyElector 主要负责完成自动的主备选举,内部封装了 Zookeeper 的处理逻
主备节点正常切换
NameNode 在选举成功后, ActiveStandbyElector 会在 zk 上创建一个
ActiveStandbyElectorLock 临时节点,而没有选举成功的备 NameNode 中的
ActiveStandbyElector 会监控这个节点
如果 Active NameNode 对应的 HealthMonitor 检测到 NameNode 的状态异常时,
ZKFailoverController 会主动删除当前在 Zookeeper 上建立的临时节点
ActiveStandbyElectorLock
如果是 Active NameNode 的机器整个宕掉的话,那么跟 zookeeper 连接的客户端线程也挂
, 会话结束 , 那么根据 Zookeepe 的临时节点特性, ActiveStandbyElectorLock 节点会自动被
删除,从而也会自动进行一次主备切换
处于 Standby 状态的 NameNode ActiveStandbyElector 注册的监听器就会收到这个节点
NodeDeleted 事件,并创建 ActiveStandbyElectorLock 临时节点,本来处于 Standby
态的 NameNode 就选举为 Active NameNode 并随后开始切换为 Active 状态。
12.7  Zookeeper
为主备切换控制器提供主备选举支持。
辅助投票
ZKFC 保持心跳机制,确定 ZKFC 的存活
12.8  脑裂 brain-split
定义
脑裂是 Hadoop2.X 版本后出现的全新问题,实际运行过程中很有可能出现两个 namenode
时服务于整个集群的情况,这种情况称之为脑裂。
原因
脑裂通常发生在主从 namenode 切换时,由于 ActiveNameNode 的网络延迟、设备故障等问
题,另一个 NameNode 会认为活跃的 NameNode 成为失效状态,此时 StandbyNameNode
转换成活跃状态,此时集群中将会出现两个活跃的 namenode 。因此,可能出现的因素有网
络延迟、心跳故障、设备故障等。
脑裂场景
NameNode 可能会出现这种情况, NameNode 在垃圾回收( GC )时,可能会在长时间内整
个系统无响应
zkfc 客户端也就无法向 zk 写入心跳信息,这样的话可能会导致临时节点掉线,备 NameNode
会切换到 Active 状态
这种情况可能会导致整个集群会有同时有两个 Active NameNode
脑裂问题的解决方案是隔离( Fencing
1. 第三方共享存储:任一时刻,只有一个 NN 可以写入; 2.DataNode :需要保证只有一个 NN 发出与管理数据副本有关的命令;
3.Client 需要保证同一时刻只有一个 NN 能够对 Client 的请求发出正确的响应。
(a) 每个 NN 改变状态的时候,向 DN 发送自己的状态和一个本次选举对应的序列号。
(b) DN 在运行过程中维护此序列号,当 failover 时,新的 NN 在返回 DN 心跳时会返回自己
active 状态和一个更大的序列号。
DN 接收到这个返回是认为该 NN 为新的 active
(c) 如果这时原来的 active (比如 GC )恢复,返回给 DN 的心跳信息包含 active 状态和原来
的序列号,这时 DN 就会拒绝这个 NN 的命令。
解决方案
ActiveStandbyElector 为了实现 fencing ,当 NN 成为 ANN 之后创建 Zookeeper 临时节点
ActiveStandbyElectorLock ,创建 ActiveBreadCrumb 的持久节点,这个节点里面保存了这个
Active NameNode 的地址信息 (node-01)
Active NameNode ActiveStandbyElector 在正常的状态下关闭 Zookeeper Session 的时
候,会一起删除这个持久节点
但如果 ActiveStandbyElector 在异常的状态下关闭,那么由于 /hadoop
ha/${dfs.nameservices}/ActiveBreadCrumb 是持久节点,会一直保留下来,后面当另一个
NameNode 选主成功之后,会注意到上一个 Active NameNode 遗留下来的这个节点,从而
会回调 ZKFailoverController 的方法对旧的 Active NameNode 进行 fencing
首先尝试调用这个旧 Active NameNode HAServiceProtocol RPC 接口的
transitionToStandby 方法,看能不能把它转换为 Standby 状态;
如果 transitionToStandby 方法调用失败,那么就执行 Hadoop 配置文件之中预定义的
隔离措施。
1. sshfence :通过 SSH 登录到目标机器上,执行命令 fuser 将对应的进程杀死
2. shellfence :执行一个用户自定义的 shell 脚本来将对应的进程隔离
在成功地执行完成 fencing 之后,选主成功的 ActiveStandbyElector 才会回调
ZKFailoverController becomeActive 方法将对应的 NameNode 转换为 Active 状态,开始
对外提供服务。
新的主创建临时节点 ActiveStandbyElectorLock ,创建持久化节点 ActiveBreadCrumb ,并将
自己的主机地址 Node02 赋值给初始化节点

 

Logo

开源、云原生的融合云平台

更多推荐