5.9 安全模式和HDFS的权限
5.9.1安全模式
-
定义:
- 安全模式是集群启动时的一个状态
- 处于安全模式的状态下,只向客户端提供文件的只读视图,不接受对命名空间的修改;同时NameNode节点也不会进行数据块的复制或者删除,
-
安全模式的开启和关闭过程
- NameNode启动时
- 加载文件的元数据和文件与Block块之间的映射
- 首先将镜像文件(fsimage)载入内存,同时执行编辑日志(edits)中的各项操作
- 一旦在内存中成功建立文件系统元数据的映像(镜像文件和日志),则创建一个新的fsimage文件和一个空的编辑日志
- NameNode开始监听RPC和HTTP请求
- 安全模式开启
- DataNode上报与Block块之间的映射关系给NameNode,NameNode收集DN与BLK之间的映射关系
- NameNode发现数据节点过少会启动数据块复制过程
- 安全模式关闭
- 当NameNode有足够的数据块信息后,便在30秒后退出安全模式
- NameNode启动时
-
安全模式相关命令
hdfs dfsadmin -safemode leave 强制NameNode退出安全模式 hdfs dfsadmin -safemode enter 进入安全模式 hdfs dfsadmin -safemode get 查看安全模式状态 hdfs dfsadmin -safemode wait 等待一直到安全模式结束
5.9.2 HDFS的权限
- HDFS对权限的控制
- 只能防止好人做错事
- 不能防止坏人做坏事
- 你告诉他你是谁,他就认为你是谁!
5.10 机架感知策略
5.10.1 节点距离
5.10.2 机架感知
- 定义
- BLK选择DN的一种策略,就是通过机架感知策略来实现了BLK选择存储在哪一个DN上。
- 机架:可以理解为存放一组主机的柜子
- 作用:
- 为了保证副本在集群中的安全性,我们需要将副本放在不同的DN节点上,节点也需要一定的考量
- 节点需要考虑可靠性、可用性、带宽消耗
- HDFS系统的机架感知策略的优势是防止由于某个机架失效导致数据丢失,并且允许读取数据时充分利用多个机架的带宽
- 为了保证副本在集群中的安全性,我们需要将副本放在不同的DN节点上,节点也需要一定的考量
- 机架感知节点的选取
- 第一个节点
- 集群内部(优先考虑和客户端相同节点作为第一个节点)
- 集群外部(选择资源丰富且不繁忙的节点为第一个节点)
- 第二个节点
- 选择和第一个节点不同机架的其他节点
- 第三个节点
- 与第二个节点相同机架的其他节点
- 第N个节点
- 与前面节点不重复的其他节点
- 第一个节点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VDwiWzEG-1655564699048)(C:\Users\18446\AppData\Roaming\Typora\typora-user-images\image-20220618172347019.png)]
5.11 HDFS读写数据流程
5.11.1 HDFS的写数据流程(重难点)
写数据就是将客户端的数据上传到HDFS上
1. 宏观流程
写数据的宏观实现流程
- 客户端向HDFS发送写数据的请求
- hdfs dfs -put tomcat.tar.gz /yjx/
- filesystem通过RPC调用NameNode的create方法
- NN首先检查是否有足够的空间权限等条件创建这个文件,同时判断这个路径是否已存在
- 有权限
- NN会针对这个文件创建一个空的Entry对象用来存储文件与Block块之间的映射关系,Block块与DN之间的映射关系
- 无权限
- 直接抛出相应的异常,给予客户端错误的信息
- 有权限
- NN首先检查是否有足够的空间权限等条件创建这个文件,同时判断这个路径是否已存在
- DFS如果接收到成功状态,会创建一个对象FSDataOutputStream给客户端使用
- 客户端需要向NN询问第一个Block存放的位置
- NN是通过机架感知策略来确定Block的存放位置(node1 node 2 node8)
- 客户端和DN节点直接建立连接
- pipeline(管道)
- 客户端和node1建立连接socket
- node1和node2创建连接 socket
- node2和node8创建连接 socket
- pipeline(管道)
- 客户端将文件按照块Block切分数据,但是按照packet发送数据
- 默认一个packet的大小为64k,Block大小为128M,是2048个packet
- 客户端通过pipeline管道开始使用FSDataOutputStream对象将数据输出
- 客户端首先将一个packet发送给node1,同时给予node1一个ack状态
- node1接受数据后会将数据继续传递给node2,同时给予node2一个ack状态
- node2接受数据后会将数据继续传递给node8,同时给予node8一个ack状态
- node8将这个packet接受完成后,会响应这个ack给node2为true
- node2会响应给node1 ,同理node1响应给客户端
- 客户端接收到成功的状态,就认为某个packet发送成功了,直到当前Block块的所有packet都发送完成
- 如果客户端接收到最后一个packet的成功状态,说明当前Block传输完成,管道就会被撤销
- 客户端会将这个消息传递给NN,NN确认传输完成
- NN这时会将Block的信息记录到Entry,客户端会继续向NN询问第二个Block块的存储位置,以此类推
- block1 (node1 node2 node8)
- block2 (node1 node8 node9)
- …
- blockn(node1 node7 node9)
- 当所有额Block传输完成后,NN在Entry中存储所有的File和Block块的映射关系,以及Block块与DN的映射关系,同时关闭FSDataOutPutStream
2. 微观流程
写数据的微观流程
-
首先客户端从自己的硬盘以流的方式读取数据文件到自己的缓存中
-
然后将缓存中的数据以chunk(512B)和checksum(4B)的方式到packet(64)
- chunk:checksum=128:1
- checksum:在数据处理和数据通信领域中,用于校验目的的一组数据项的和
- acket中的数据分为两类,一类是实际数据包,另一类是header包。
- 一个Packet数据包的组成结构如下图
-
当packet满的时候就添加到dataqueue中
-
datastreamer开始从dataqueue队列上取出packet, 通过FSDataOPS发送到pipleline
- 在取出的时候,也会将packet加入到ackQueue,是一个典型的生产者消费者模式
5.11.2 HDFS读数据流程
- 首先客户端发送请求到DFS,申请读取某一个文件
- /yjx/tomcat.tar.gz
- DFS去NN查找这个文件的信息(权限,文件是否存在)
- 如果文件不存在,抛出指定的错误
- 如果文件存在,返回成功状态
- DFS创建FSDataInputStream对象,客户端通过这个对象读取数据
- 客户端获取文件第一个Block块信息,返回DN1,DN2,DN8
- 客户端直接就近原则选择DN1对应的数据即可
- 以此类推读取到其他块的信息,直到最后一个块,然后将所有的Block块合并成一个文件
- 关闭FSDataInputStream
5.12 Hadoop 1 的困境
- 单点故障问题
- 每个集群只有一个NameNode,NameNode存在着单点故障(SPOF)
- 如果该负责NameNode的计算机或者进程不可用,则整个集群在NameNode重启或者在另外一台计算机上启动之前将不可用
- 如果发生意外(例如机器崩溃),则在操作员重新启动NameNode之前,集群将不可用
- 计划内的维护事件,例如NN计算机上的软件或硬件升级,将导致集群停机时间的延长
- 水平扩展的问题
- 将来服务器启动的时候,启动速度慢
- NN随着业务的增多,占用内存也越来越多
- 如果NN内存占满,将无法继续提供服务
- 业务隔离性差
- 存储:有可能我们需要存储不同部门的数据
- 计算:有可能存在不同业务的计算流程
- 项目后期namenode的吞吐量将会是集群的瓶颈
- 客户端所有的请求都会先访问NameNode
- Hadoop2.x
- NameNode节点的高可用
- HA–high availability
- NameNode业余的水平扩展
- Federation
- NameNode节点的高可用
5.13 Hadoop-HA
HA(High Availablity),即高可用,7*21小时不中断服务,HA的出现是为了弥补Hadoop1.X存在的问题
5.13.1 设计思想
- 主备节点切换
- hadoop2.x启用了主备节点切换模式(1主1备)
- 当主节点出现异常的时候,集群直接将备用节点切换成主节点
- 要求备用节点马上就要工作
- 主备节点内存几乎同步
- 有独立的线程对主备节点进行监控健康状态
- 选举主节点的机制
- 需要有一定的选举机制,帮助我们确定主从关系
- 需要实时存储日志的中间件
5.13.2 Hadoop 2.X组件
1. ANN
- 定义:
- 主NN(Active NameNode )的功能和原理的NN的功能是一样的
- 接受客户端请求,查询数据块DN信息
- 存储数据的元数据信息
- 数据文件:Block:DN的映射关系
- 主NN(Active NameNode )的功能和原理的NN的功能是一样的
- 工作
- 启动时:接受DN的block汇报
- 运行时:和DN保持心跳(3s,10m30s)
- 存储介质
- 完全基于内存
- 优点:数据处理效率高
- 缺点:数据的持久化(日志edits+快照fsimage)
2. SNN
- 定义
- 备用NN(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合并
- 当达到阈值(64M/3600s)的时候,直接拍摄快照即可
- SNN将合并好的fsimage发送给ANN,ANN校验无误后,存放到自己的目录中
3. DN
- 定义
- 数据节点,用来存储文件的block数据
- 介质
- 硬盘
- 启动时:
- 同时向两个NN汇报Block信息
- 运行中
- 同时和两个NN节点保持心跳机制
4. QJM (JournalNode*3 )
-
定义
- QJM(Quorum JournalNode Manager)一致性日志管理系统,NameNod通过共享一致性日志管理系统实现日志数据的同步
- JournalNode是一个独立的小集群,它的实现原理和Zookeeper一致(Paxos)
-
组成
- JournalNode*3 =QJM
- JournalNode是日志节点
-
JurnalNode特点
- ANN产生日志文件的时候,就会同时发送到 JournalNode的集群中每个节点上
- JournalNode不要求所有的日志节点都接收到日志,只要有半数以上的(n/2+1)节点接受收到日志,那么本条日志就生效
- SNN每间隔一段时间就去QJM上面取回最新的日志
- SNN上的日志有可能不是最新的
- HA集群的状态正确至关重要,一次只能有一个NameNode处于活动状态
- JournalNode只允许单个NameNode成为作者。在故障转移期间,将变为活动状态的NameNode将承担写入JournalNodes的角色,这将有效地防止另一个NameNode继续处于活动状态,从而使新的Active节点可以安全地进行故障转移。
5. ZKFC
-
定义
- ZKFC(ZooKeeperFailoverController) Zookeeper的故障转移控制器
- 有一个NameNode就有一个ZKFC
-
作用
-
总的来说两个作用
- 健康监控
- 节点选举
-
对 NameNode 的主备切换进行总体控制,能及时检测到 NameNode 的健康状况
- 在主 NameNode 故障时借助 Zookeeper 实现自动的主备选举和切换
- 为了防止因为NN的GC失败导致心跳受影响,ZKFC作为一个deamon进程从NN分离出来
-
-
启动时ZKFC的作用
- 当集群启动时,主备节点的概念是很模糊的
- 当ZKFC只检查到一个节点是健康状态,直接将其设置为主节点
- 当zkfc检查到两个NN节点是的健康状态,发起投票机制
- 选出一个主节点,一个备用节点,并修改主备节点的状态
-
运行时ZKFC的作用
- 由 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 状态。
- NameNode 在选举成功后,ActiveStandbyElector会在 zk 上创建一个
- 由 ZKFailoverController、HealthMonitor 和 ActiveStandbyElector 这 3 个组件来协同实现主备切换
6. Zookeeper
- 为主备切换控制器提供主备选举支持。
- 启动的时候协助选举
- 和ZKFC保持心跳机制,确定ZKFC的存活
5.13.3 脑裂brain-split
- 定义
- 脑裂是Hadoop2.X版本后出现的全新问题,虽然我们解决了1.X版本的单点故障的问题,采用了主备NN的策略,但是实际运行过程中很可能有出现两个Name Node同时服务于整个集群的情况,这种情况称之为脑裂
- 原因
- 主从Name Node切换时,由于主NameNode(ActiveNameNode)的网络延迟、设备故障等问题,另一个活跃的NameNode会认为活跃的NameNode成为失效状态,此时备NameNode(StandbyNameNode)会转换成活跃状态,等主NameNode故障修复后,此时集群中就会出现两个活跃的NameNode,因此造成脑裂。
- 主NameNode出现网络延迟、心跳故障、设备故障等
- 脑裂场景
- NameNode 可能会出现这种情况,NameNode 在垃圾回收(GC)时,可能会在长时间内整个系统无响应,zkfc客户端也就无法向 zk 写入心跳信息,这样的话可能会导致临时节点掉线,备 NameNode会切换到 Active 状态,这种情况可能会导致整个集群会有同时有两个Active NameNode
- 脑裂的解决方案是隔离(Fencing)
- 第三方共享存储:任何时刻,只有一个NN可以写入
- DataNode:需要保证只有一个NN发出与管理数据副本有关的命令;
- 客户端:需要保证同一时刻只有一个NN能对客户端发出请求发出正确的相应
- 每个NN改变状态的时候,向DN发送自己的状态和本次选举的序列号
- DN在运行的过程中会维护自己的序列号,当failover(故障转移)的时候,在新的NN返回DN心跳的时候会返回自己的Active状态和一个更大的序列号,DN接收到这个返回认为该NN是最新的Active
- 如果这是原来的Active(比如GC)恢复,返回给DN的心跳信息包含Active状态和原来的序列号,这时DN就会拒绝这个NN的命令(相当于改朝换代,序列号更新)。
- 隔离的具体实现
- 每次ANN成功竞选后,会创建一个临时节点和一个正常节点
- 主动下线和被动下线
- 当ANN主动下线时,临时节点和正常节点都会被删除
- 当ANN被动下线时,临时节点会被删除,正常节点会被保留
- SNN对主动下线和被动下线的处理
- 如果SNN发现临时节点和正常节点都不存在,自己可以放心的切换成主
- 如果SNN发现临时节点被删除,正常节点存在,集群就有可能发生脑裂
- SNN对被动下线的处理(防止脑裂)
- 首先SNN会和原来的ANN进行联系,RPC调用ANN的ActiveBreadCrumb方法,尝试将主切换为备用
- 如果RPC切换失败,会执行预定义的隔离措施
- 预定义的隔离措施
- sshfence:通过SSH登录到目标机器上,执行命令fuser将对应的进程杀死
- shellfence:执行一个用户自定义的shell脚本 来将对应的进程隔离
- 当原来的ANN被处理后,现在的SNN开始调用 becomeActive 成为主节点,开始提供对外服务
- 新的ANN的ZKFC也会在ZK上面创建自己的临时节点和正常节点(以便检测新的ANN是否是被动下线)
5.14 Hadoop-Federation
Federation是指联邦机制,Hadoop-Federation的出现可以使得HDFS支持多个命名空间,并且允许HDFS中同时存在多个NameNode
5.14.1 单NN局限性
- Namespace(命名空间)的限制
- NameNode所能存储的对象(文件+块)数目受到NameNode所在JVM的heap size的限制。
- 50G的heap能够存储20亿(200million)个对象,这20亿个对象支持4000个DataNode,12PB的存储
- DataNode从4T增长到36T,集群的尺寸增长到8000个DataNode。存储的需求从12PB增长到大于100PB。
- 性能的瓶颈
- 整个HDFS文件系统的吞吐量受限于单个Namenode的吞吐量
- 隔离问题
- HDFS上的一个实验程序就很有可能影响整个HDFS上运行的程序
- 集群的可用性
- Namenode的宕机无疑会导致整个集群不可用。
- Namespace和Block Management的紧密耦合
- 纵向扩展目前的Namenode不可行
- 将Namenode的Heap空间扩大到512GB启动花费的时间太长
- Namenode在Full GC时,如果发生错误将会导致整个集群宕机
5.14.2 Federation
- 块池Block Pool
- Block pool(块池)就是属于单个命名空间的一组block(块)管理区域
- 每一个datanode为所有的block pool存储
- Datanode是一个物理概念,而block pool是一个重新将block划分的逻辑概念
- 一个Namenode失效不会影响其下的datanode为其他Namenode的服务
- datanode与Namenode建立联系并开始会话后自动建立Block pool
- Namespace Volume(命名空间卷)
- 一个Namespace和它的Block Pool合在一起称作Namespace Volume
- Namespace Volume是一个独立完整的管理单元。当一个Namenode/Namespace被删除,与之相对应的Block Pool也也被删除。
- 通过多个namenode/namespace把元数据的存储和管理分散到多个节点中
- 降低单个NN节点数据压力,计算压力
- namenode/namespace可以通过增加机器来进行水平扩展
- 可以让更多的节点参与到运算
- namespace命名空间,通过这种方式确定要处理数据的路径
- 我们可以通过namenode和namespace组合使用
- 所有的nn共享dn
- 但是每一个namespace会单独管理自己的块
- 会创建一个管理块的机制:blocks pool