<1> Hadoop的核心优势
- 高可靠性:Hadoop支持同一数据多个副本保存机制,能有效避免数据丢失情况
- 高扩展性:Hadoop能够很方便地扩展大量节点,用于分布式存储与计算
- 高效率性:Hadoop结合MapReduce的思想,支持分布式并行工作,处理工作
- 高容错性:在Hadoop集群中,能够自动将失败节点的任务重新分配
<2> Yarn的架构
- ResourceManager:负责集群任务调度与资源分配的核心,启动监控NM与AM
- ApplicationMaster:负责监控和调度每个任务的进行,Client提交任务RM就会创建AM
- NodeManager:每个节点上负责调度该节点任务的单元,管理该节点的资源
- Container:Yarn集群每个节点的资源抽象而成的概念,包括多个维度:CPU、磁盘等
<3> Hadoop的核心配置
- hadoop-env.sh:Hadoop的环境配置,如配置JAVA_HOME
- core-site.xml:配置集群文件系统类型(NameNode的URL)、集群文件存储目录等
- hdfs-site.xml:与HDFS有关的配置,比如指定HDFS副本数量、Block大小等;指定SecondaryNameNode
- yarn-env.sh:配置Yarn的工作环境,比如添加JAVA_HOME
- yarn-site.xml:指定Yarn的ResourceManager,指定Reducer获取数据的方式(mapreduce_shuffle) 、配置每个节点Container最多可申请的内存等
- mapred-env.sh:配置Mapreduce的环境
- mapred-site.xml:指定Mapreduce运行在Yarn上 -- 关联、指定JobTracker的地址
<4> 为什么不能频繁格式化NameNode?
- Reason1:格式化NameNode就需要删除节点内保存的所有数据,开销较大,且有数据丢失风险
- Reason2:NameNode第一次启动会生成集群id,而NameNode格式化后会生成新的集群id,如果某些节点的数据未清理干净,可能导致这些DataNode持有的还是旧集群ID,导致节点失效
<5> Hadoop集群搭建的要点
- 部署 JDK & Hadoop
- 设置静态IP (关闭防火墙)
- 设置SSH免密登录(NameNode --- ALL Node ; ResourceManager --- ALL Node)
- 配置群启配置文件slavers
- 设置集群内时间同步(如每10mins同步一次)
<6> HDFS
是什么:HDFS是分布式文件管理系统的一种
干什么:海量数据(单台PC设备无法容纳)的存储与管理
【优点】
- 高容错性:支持一文件多副本存储机制,文件丢失风险较小
- 高扩展性:很方便进行集群的扩建,增加节点;而且节点对于设备的要求不高
- 高容纳性:扩展性的前提让HDFS天然就拥有高容纳性,能存储管理TB甚至PB级别的数据
【缺点】
- 响应时间较长,不适合实时数据访问
- 不支持并发写操作,同一时间同一文件只能由一个线程进行写
- 不支持随机修改,写入数据只能append
- 无法高效存储小文件(NameNode机制导致)
<7> HDFS架构
- NameNode:HDFS集群的核心管理者,存储所有块文件的元数据,管理DataNode,处理Client端请求
- DataNode:实际文件的存储者;负责文件的读写操作
- Client:客户端,管理操作HDFS,与NameNode交互获取元数据 -- 与DataNode交互获取实际数据
- SecondaryNameNode:NameNode的协助角色,帮助NameNode进行fsimage与Edits的合并,必要时辅助NamaNode的恢复重启
<8> HDFS的文件块大小
Hadoop1.X -- 64M Hadoop2.X -- 128M 可通过参数进行调整(hdfs-site.xml)
决定文件块大小的原因:磁盘的传输速率 -- 访问数据时寻址时间为传输时间的1%时为最佳
- 文件块太大:传输时间明显远大于寻址时间,表现为程序在处理文件块时操作时间比较久
- 文件块太小:寻址时间占耗时比例太大,增加寻址时间,不符合分布式的目的
<9> HDFS的写流程
- Client端加载FileSystem类,连接到NameNode,并发送上传文件请求
- NameNode检查文件是否已存在以及检查文件将要存放的父目录是否存在,然后回复是否可以进行上传
- Client端请求上传第一个Block(128M) -- 文件在Client端就会切分为块,逻辑切分,即通过seek维护偏移量
- NameNode根据副本数分配对应数量的DataNode节点返还给Client
- 根据设置的副本数分配对应数量的DataNode节点并返还给Client端
- Client加载FSDataOutputStream类,选择一个距离自己最近的DataNode - D1请求建立通信,D1收到请求后会调用D2,D2再调用D3,随后D123分别应答Client,至此成功建立数据通道
- Client,向D1传输Block1 -- 以Packet为单位
- D1接受数据Packet到内存,然后拷贝写到本地磁盘,写完后内存中的Packet将会传递给D2
- D2同样进行拷贝刷写,然后将内存中数据传递给D3
- D3为最后一站,直接将接收到的Packet写入到磁盘
- 第一个Block上传完后,Client将会再次发送请求到NameNode请求上传第二个Block
- ......
<10> HDFS的读流程
- Client端加载FileSystem类,建立与NameNode的通信,上传读取(下载)数据的请求
- NameNode根据文件块的元数据,判断文件是否存在以及在哪个DataNode上
- NameNode答复Client端,不存在文件 OR 文件所在的DataNode - D1 D2 D3 (一个文件可被分为几个Block)
- Client实现FSDataInputStream类,建立与D0 (存放Block1) 的通信,并请求下载数据
- D0接收到请求,将数据文件从磁盘读取到内存,以Packet为单位,然后发送给Client
- Client接受到Packet数据,先写到内存缓存,然后写入到磁盘
- Block1读取下载完毕后,Client再和D2建立通信,下载Block2
- ......
<11> NameNode && SecondaryNameNode
关键点:不管文件大小,只要是一个Block,就会分配150byte用作存储该Block的元数据,因此小文件过多很容易导致NameNode的实际利用率很低
- 内存:存储当前集群所有块文件的元数据
- FSImage:元数据在磁盘中的实际存储文件
- Edits:以日志形式记录写入操作
当NameNode关闭或异常断电时,内存中的数据丢失,既可以通过加载磁盘上的FSImage文件到内存,同时执行Edits中记录的操作,就可以恢复所有的元数据
关键点:随着集群运转,Edits日志越来越大怎么办?
SecondaryNameNode的主要工作便是定期帮助NameNode进行FsImage和Edits文件的合并。默认每小时或者Edits文件中记录超过100万条(每分钟检查一次)时,SecondaryNameNode会将NameNode中的两个文件拷贝到自己的节点,并加载到内存中进行合并后生成一个新的FSimage文件,将该新的文件拷贝给NameNode,替换原来的FSImage文件。注意:在SecondaryNameNode开始工作时,NameNode会生成一个新的Edits文件,记录合并过程中发生的写操作,这样新的Fsimage和新的Edits文件就是当前最新的元数据了
SecondaryNameNode并不是实时进行NameNode数据的同步,因此并不能在NameNode挂掉时完全替代后者,而是通过将上一次的FsImage文件拷贝给NameNode进行大概的数据恢复,因为上一次合并到NameNode挂掉之间的数据仍然只在NameNode中,因此该恢复方法并不能完全保证数据的完整性,当nameNode丢失Edits文件便会有数据的丢失
PLUS: NameNode启动过程,是将磁盘中的FsImage和Edits加载到内存进行合并,最后形成完整的元数据,在此过程集群为安全模式,面向Client只读,即无法进行写操作
<12> DataNode
HDFS文件块的实际存储节点,DataNode数据包括两部分:
- 数据块本身,128M / per Block
- 数据块元数据:数据块长度(可能为一个小文件,不足128M,但也是一个Block)、校验和、时间戳等
DataNode运行机制:
- DataNode启动后,会首先向NameNode注册自己
- 每个一个小时,周期性地向NameNode上报节点下所有数据块的元数据信息
- 心跳机制:让NameNode知道DataNode是否还活着,默认每3s一次,如果超过10min + 30s没有心跳,则NameNode就会判断DataNode挂掉,将其标记为不可用
- 在集群运行的时候,可以进行DataNode的加入【白名单】和退役【黑名单】
【扩充知识点:黑白名单】
- 如果设置了白名单(dfs.hosts),那么只有白名单上的节点才能够接入集群,不在名单上的节点如果当前不在集群,那么无法进入集群;已在集群的节点,会被强制退役,且这些退役节点中的数据不会转移到其他节点
- 如果设置了黑名单(dfs.hosts.exclude),那么黑名单上的节点都不能接入集群,在名单上的节点如果当前不在集群,那么无法进入集群;已在集群的节点,会被强制退役,不过退役前会将数据转移到其他节点
<13> HDFS处理小文件的方法
HDFS文件归档:将一个目录下的众多小文件归档成为一个HAR文件,对内访问时仍然是一个个独立的文件,即读取时仍是彼此独立的,但对NameNode而言则是一个整体,于是这些小文件将会共用一个块的元数据
<14> HA -- HDFS高可用
总结:为了消除单点故障,维护两个乃至多个NameNode,同一时间只有一个在役,其他的为替补,当当前在役的NameNode挂掉后,替补的NameNode升级服役,解决单点故障的痛点
手动实现高可用 -- 可能出现故障转移失败:
即若当前NameNode不可用了,Client端通过命令启用另一台NameNode。但由于NameNode在集群的唯一性,为了避免Split Brain(两个或多个NameNode在线),候补NameNode会给原来的NameNode发送验证消息,只有收到了恢复候补NameNode的状态才能够能够升级为Active。这样当NameNode节点设备只是NameNode进程中断的话是能够实现NameNode切换的,但如果是因为设备损毁(如爆炸、断电、网络中断等)而导致NameNode的不可用,候补NameNode节点无法与旧NameNode建立通信,也就无法完成切换
通过ZooKeeper实现自动故障转移 -- 故障转移稳定:
- 除却Zookeeper外,自动故障转移还在每个NameNode节点启用了ZKFC,ZKFC会定期ping同机上的NameNode进程,得到其健康状态,此外,ZKFC在Zookeeper上还维护了一个排他锁ZNode。此外,每个NameNode都在Zookeeper上维护了一个持久会话,如果会话消失,则锁被释放,且其他NameNode会收到消息。这样即便原NameNode机子完全炸了,也能实现自动的故障转移
- 如果ZKFC发现当前NameNode健康,且此时ZNode锁没有被任何人持有,那么ZKFC将会抢占该锁,所在节点NameNode也将成为Active【启动时谁抢到了谁Active】。
- 如果当前NameNode不健康了,则NameNode所在会话将会关闭,其他候补NameNode收到消息,且ZNode锁被释放,则候补NameNode中谁抢到了锁谁就变为Active
- 假死补刀:如果当前NameNode只是网络波动等造成的假死,那么ZKFC会检测出来,并通过Zookeeper通知成为新NameNode的节点下的ZKFC进程,新NameNode节点下的ZKFC将会发送kill指令,将旧NameNode彻底结束(补刀),如此防止Split Brain现象
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。