hdfs/MR常见问题总结
HDFS
架构
NameNode
负责存储数据的元数据信息
存储的元数据会放到内存里面,但是如果机器挂了,元数据就丢了,所以需要将元数据信息也写入到磁盘上,所以有了备份元数据信息的FsImage文件,但是不能每次写元数据信息都写入到磁盘里面,所以引入了edits文件,来记录所有对元数据的更新操作,顺序写。如果重启namenode就会对FsImage和Edits文件进行合并。
DataNode
存储实际数据的数据块
SecondaryNameNode
定期合并FSImage和Edits文件
因为如果一直向edits文件写入操作,这个文件就会很大,所以就会定期把备份的元数据和操作的edits文件进行合并
HDFS读写流程
HDFS写流程
首先客户端会向NameNode请求,然后namenode会检查这个文件存不存在,如果不存在就允许客户端上传文件
客户端再次向namenode请求第一个block上传到哪几个datanode节点,namenode返回了三个datanode
然后客户端会向datanode1请求上传数据,datanode会调用datanode2,datanode2继续调用datanode3,当链路打通了,dn3,dn2,dn1会向客户端返回数据
然后客户端会向datanode1上传第一个block,datanode1收到后就会传给datanode2,dn2再传给dn3
当第一个block传输完成了,客户端再请求上传第二个block
HDFS读流程
客户端会先向namenode发出请求,namenode会检查这个我呢见存不存在,如果存在就会返回一个文件的datanode的地址,这些返回的datanode的地址会按照集群拓扑的方式得出datanode与客户端之间的距离,然后进行排序,客户端会选择靠前的datanode来读取block,然后本地进行缓存,写入目标文件
小文件过多的危害
存储大量小文件就会占用namenode的内存来处理元数据
计算的时候每个小文件开启一个maptask浪费资源
解决办法:
上传hdfs之前对小文件进行合并后上传
使用har归档的方式,将多个小文件打包一个har文件
计算的时候使用combine切片,将多个小文件合并成一个切片
开启JVM重用,多个task共用一个jvm
NameNode HA中的脑裂问题
这个问题是因为假设namenode1是active的状态,namenode2是standBy的状态,某一时刻,namenode1对应的zkFailoverController假死了,zk服务端就任务这个namenode1死了,namenode2就会成为Active,但是这个时候namenode1其实活着,这时候就是脑裂了
解决办法
首先尝试调用这个旧的namenode尝试转换成standby
如果无法转换成standy,那么就执行hadoop配置文件中预定义的隔离措施
隔离措施有两种:
- 通过ssh到目标机器,杀死进程
- 执行一个用户自定义的shell脚本隔离进程
SecondaryNameNode的工作机制
定期合并FsImage和Edits文件
FsImage文件是记录了最新的元数据检查点
Edits文件记录了对namenode元数据的增删改的操作
在上传文件的时候忽然一个DataNode挂了怎么办
当DataNode忽然挂了的时候,客户端收不到DataNode上传结束文件的ack确认,客户端会通知NameNode,NameNode检查这个块的副本和规定的不相符,Name会通知DataNode复制副本,然后将挂掉的DataNode下线
在读取文件的时候忽然一个块挂了怎么办
在客户端读取完DataNode上的块后会进行checksum验证,也就是把客户端读到的本地的块和HDFS的原始块进行校验,校验结果不一样的话,客户端会通知NameNode,然后再从下一个拥有这个block副本的DataNode继续读
NameNode数据恢复的过程
当NameNode挂了的时候,secodarynamenode会保存所有的元数据信息
当NameNode重启的时候,secodarynamenode将元数据发送给NameNode
MapReduce
简述Mapreduce的整个流程
Map阶段
首先通过InputFormat把输入目录下面的文件进行切片,默认大小就是block大小,每一个切片都会由一个maptask处理。同时将切片的数据解析成为key和value的键值对
k代表偏移量,v代表内容。然后调用map方法,对每一行的内容进行处理,解析为kv的键值对。在wordCount案例中,k代表单词,v代表数字1
Shuffle阶段
Map Shuffle
将map后的kv写入到环形缓冲区,一半写元数据,(key的起始位置,value的起始位置,value的长度,partition号)。一半写kv数据,等达到百分之80的时候进行溢写
溢写之前需要根据key对key进行分区后进行快排,快排算法,分区号是按照key的hashcode对reduce task取模得到的,这里添加combiner合并,将有相同key的value合并起来,减少溢写到磁盘的数据量
溢写到文件中,进行merge归并排序,多个溢写文件归并
Reduce Shuffle
reduce会拉取同一分区的各个maptask的结果到内存中,如果放不下就会溢写到磁盘上,然后对内存和磁盘上的数据进行merge归并排序
reduce阶段
key相同的数据会调用一次reduce方法,每次调用都会产生一个键值对,最后将这些键值对写入到文件中
环形缓冲区工作原理
环形缓冲区有两个指针,一个写指针,一个读指针
写指针:指示当前写入数据的位置
读指针:指示当前读数据的位置
当写指针追赶上读指针时,缓冲区被认为是满的,此时需要进行溢写操作:
环形缓冲区图解:
初始状态:
可以支持连续读写,高效利用内存,避免频繁的内存分配和释放操作
join原理
“join” 操作是指将两个或多个数据集基于某个共同的键(key)进行合并
reduce中的join
适用于两个或多个大数据集的连接操作
- map阶段的主要任务就是对不同表的数据打上标签,然后用连接字段作为key,其他的部分和标签作为value
- shuffle阶段,根据key进行hash,然后就可以把key相同的送到一个reduce
- reduce的主要任务:同一个key的数据会调用一次reduce方法,就是对来自不同表的数据进行join
map中的join
小表复制:将小表加载到每个 Mapper 的内存中,这样每个 Mapper 都有一份小表的数据。
扫描大表:Mapper 逐行扫描大表的数据。
匹配并连接:对于大表中的每一条记录,Mapper 在内存中的小表查找是否存在相同的 key。
输出结果:如果找到匹配的记录,则进行 join 操作,并将结果输出。
增加了Map端业务,减少Reduce端业务的压力,尽可能减少数据倾斜
这种方法的关键在于小表足够小,可以被完全加载到内存中。如果小表太大而不能完全加载到内存中,这种方法就不适用了。
文件切片
数据切片
只是逻辑上对输入进行分片,并不会对磁盘进行切片存储
数据块:
默认为128M,hdfs在物理上把数据分成一块一块的
Maptask的并行度决定机制:
- 一个job的map阶段并行度由客户端在提交job时的切片数决定
- 每个切片对于一个maptask
- 切片大小等于blockSize
hadoop3.0的特性(转载)
最低要求的Java版本从Java 7增加到Java 8
现在,已针对Java 8的运行时版本编译了所有Hadoop JAR。仍在使用Java 7或更低版本的用户必须升级到Java 8。支持HDFS中的纠删码
纠删码是一种持久存储数据的方法,可节省大量空间。与标准HDFS副本机制的3倍开销相比,像Reed-Solomon(10,4) 这样的标准编码的空间开销是1.4倍。由于纠删码在重建期间会带来额外的开销,并且大多数情况下会执行远程读取,因此传统上已将其用于存储较冷,访问频率较低的数据。
在部署此功能时应考虑纠删码机制的网络和CPU开销。
Shell脚本重写
Hadoop Shell脚本已被重写,以修复许多长期存在的错误并包括一些新功能。Hadoop的开发人员尽管一直在寻求兼容性,但是某些更改可能会破坏现有的安装。MapReduce 任务本地优化
MapReduce 增加了对 map output 收集器的本地执行的支持,对于 shuffle 密集型工作,这可以使性能提高30%或更多。支持两个以上的 NameNode
在之前的版本中,HDFS的高可用最多支持两个NameNode。在HDFS 3.x 版本中,通过将编辑复制到法定数量的三个JournalNode,该体系结构能够容忍系统中任何一个节点的故障。
但是,某些部署需要更高的容错度。这个新特性启用了这一点,该功能允许用户运行多个备用NameNode。例如,通过配置三个NameNode和五个JournalNode,群集可以忍受两个节点的故障,而不仅仅是一个节点的故障。多个服务的默认端口已更改
以前,多个Hadoop服务的默认端口在Linux临时端口范围内(32768-61000)。这意味着在启动时,服务有时会由于与另一个应用程序的冲突而无法绑定到端口。
这些冲突的端口已移出临时范围,具体的端口更改如下:
NameNode 的端口: 50070 –> 9870, 8020 –> 9820, 50470 –> 9871;
Secondary NameNode 的端口: 50091 –> 9869, 50090 –> 9868;
DataNode 的端口: 50020 –> 9867, 50010 –> 9866, 50475 –> 9865, 50075 –> 9864;
Hadoop KMS 的端口: 16000 –> 9600(HBase的HMaster端口号与Hadoop KMS端口号冲突。两者都使用16000,因此 Hadoop KMS 更改为9600)。支持Microsoft Azure数据湖和阿里云对象存储系统文件系统连接器
Hadoop现在支持与Microsoft Azure数据湖和Aliyun对象存储系统集成,作为与Hadoop兼容的替代文件系统。数据内节点平衡器
单个DataNode可管理多个磁盘。在正常的写操作过程中,磁盘将被均匀填充。但是,添加或替换磁盘可能会导致DataNode内部出现严重偏差。原有的HDFS平衡器无法处理这种情况。新版本的HDFS中有平衡功能处理,该功能通过hdfs diskbalancer CLI调用。基于HDFS路由器的联合
基于HDFS路由器的联合添加了一个RPC路由层,该层提供了多个HDFS名称空间的联合视图。这简化了现有HDFS客户端对联合群集的访问。YARN资源类型
YARN资源模型已被通用化,以支持用户定义的CPU和内存以外的可计数资源类型。例如,集群管理员可以定义资源,例如GPU,软件许可证或本地连接的存储。然后可以根据这些资源的可用性来调度YARN任务。
hdfs租约机制
hdfs当客户端用户向某一个文件中写入数据的时候,为了保证数据的一致性,其他客户端程序是不许向这个文件中同时写入数据的
这里hdfs使用了租约文件。
租约也就是一个保存了租约持有者信息和这个租约对应的文件id列表,表示当前的租约持有者正在写这些文件id对应的文件其他人不许动
每个客户端用户都有一个租约
租约是hdfs给客户端的一个写文件操作的许可证,没有证件的不允许操作文件,客户端每次读写hdfs的时候会获取租约对文件进行一个读写,文件读取完了,会释放租约
hdfs的存储策略和异构存储
2.6.0版本之后支持异构存储,也就是冷热存储,把经常使用的数据放在内存或者SSD,其他的冷数据放在机械硬盘