hdfs大规模数据存储底层原理详解(第31天)

avatar
作者
猴君
阅读量:1

系列文章目录

一、HDFS设计原理
二、HDFS系统架构
三、HDFS关键技术
四、HDFS应用实例
五、解决HDFS不能处理小文件详解问题


文章目录


前言

HDFS(Hadoop Distributed File System,Hadoop分布式文件系统)是专为大规模数据集设计的分布式文件存储解决方案,它通过一系列的技术和设计理念,实现了高效、可靠、可扩展的大数据存储。以下是对HDFS如何做到大规模数据存储的详细说明,包括其设计原理、架构、关键技术以及应用实例,


一、设计原理

HDFS的设计原理主要基于“分而治之”的策略,即将大文件分割成固定大小的数据块(Block),并将这些数据块分布存储在多个计算节点(DataNode)上,以实现数据的并行处理和冗余存储。这种设计使得HDFS能够处理PB级别的数据存储,并支持高吞吐量的数据访问。

二、系统架构

HDFS采用主从架构(Master-Slave Architecture),主要由以下几个组件组成:

  • NameNode:HDFS的主节点,负责维护文件系统的命名空间,管理文件系统树及整棵树内所有的文件和目录。NameNode还负责维护文件系统树中各个文件和目录的元数据信息,包括权限信息、文件属性等。这些信息被保存在NameNode的内存中,以便快速查询。
  • DataNode:HDFS的从节点,负责处理文件系统客户端的读写请求,在文件系统中实际存储数据。DataNode会定期向NameNode发送心跳信号和块报告,告知NameNode自己的状态以及存储的块信息。
  • Secondary NameNode:并非NameNode的热备,其主要作用是定期合并NameNode的编辑日志(Edit Log)和文件系统镜像(FSImage),以减少NameNode启动时间。此外,Secondary NameNode还可以在NameNode发生故障时,用于恢复NameNode。
  • Client:HDFS的客户端,是用户与HDFS交互的主要途径。客户端提供的API使得应用程序可以方便地读取、写入和管理分布式文件系统中的文件。

三、关键技术

  • 数据块(Block):HDFS将大文件分割成固定大小的数据块(默认大小为128MB,Hadoop 2.x版本以后可配置),每个数据块会存储在多个DataNode上,实现数据的分布式存储。这种设计有利于数据的并行处理和负载均衡。
  • 副本机制:为了保证数据的可靠性,HDFS采用副本机制,默认情况下,每个数据块会有三个副本。这些副本会被分布在不同的DataNode上,甚至可能位于不同的机架上,以避免单点故障导致的数据丢失。
  • 元数据管理:NameNode负责维护文件系统的元数据信息,包括文件名、路径、副本数量、数据块ID以及存储的DataNode节点等信息。这些信息被保存在NameNode的内存中,并通过编辑日志和文件系统镜像进行持久化存储。
  • 容错性设计:HDFS通过多种机制来保障系统的高可用性,包括数据块的冗余存储、DataNode的心跳检测、NameNode的故障恢复等。当DataNode出现故障时,HDFS会自动从其他DataNode上读取副本数据,以保证数据的可用性。
  • 扩展性:HDFS支持动态添加DataNode,以实现存储容量的扩展。这种设计使得HDFS能够轻松应对数据量的快速增长。

四、应用实例

以互联网公司使用HDFS存储用户行为数据为例,HDFS作为大数据离线分析的基础存储平台,可以支撑PB级别数据的存储和分析。具体流程如下:

数据收集:通过日志收集系统(如Flume)将用户行为数据实时收集并写入HDFS。
数据存储:HDFS将收集到的数据按照一定的规则进行分割和存储,每个数据块会被复制到多个DataNode上,以实现数据的冗余存储。
数据分析:数据挖掘工程师可以使用MapReduce、Spark等计算框架对存储在HDFS中的数据进行处理和分析,以发现有价值的信息。
结果展示:分析得到的结果可以通过数据可视化工具进行展示,为企业的决策提供有力支持。

五、解决HDFS不能处理小文件详解问题

HDFS通过其独特的设计原理和架构,实现了大规模数据的高效、可靠、可扩展存储。它采用数据块分割、副本机制、元数据管理等多种技术,保障了数据的可靠性和可用性。同时,HDFS还支持动态扩展,能够轻松应对数据量的快速增长。在实际应用中,HDFS已经成为大数据处理和分析的重要工具之一,为企业提供了强有力的数据支持。
然而,需要注意的是,HDFS并非完美无缺。由于其针对大规模数据集进行优化,因此在处理小文件时可能会存在性能瓶颈。此外,HDFS的写入操作相对较慢,且不支持并发写入和随机读写操作。因此,在选择存储解决方案时,需要根据具体的应用场景和需求进行综合考虑。在数据仓库中,小文件问题是一个常见的挑战,特别是在使用Hadoop HDFS(Hadoop Distributed File System)等分布式存储系统时。小文件会导致大量的元数据开销、NameNode性能下降以及HDFS读写效率的降低。为了有效地处理小文件问题,可以采取以下几种策略:

1. 合并小文件

  • 手动合并:通过编写脚本或程序,将多个小文件合并成一个大文件。这种方法适用于周期性或批处理场景。
  • Hadoop MapReduce作业:利用MapReduce框架编写作业来合并小文件。MapReduce作业可以并行处理大量数据,提高合并效率。
  • Hadoop Archive (HAR):HAR是一种用于存储和管理小文件的技术,它将多个小文件打包成一个单独的归档文件,类似于zip格式。这样可以减少存储空间的占用和元数据的开销。
  • Spark动态分区合并:Spark SQL支持通过动态分区写入和AQE(Adaptive Query Execution,自适应查询执行)特性来自动合并较小的分区,从而减少小文件的数量。

2. 优化Hive配置

  • 设置输入输出合并:在Hive中,可以通过设置hive.merge.mapredfiles、hive.merge.mapfiles等参数来在Map或Reduce任务结束时合并小文件。
    控制Map和Reduce的数量:减少Map和Reduce的数量可以减少小文件的生成。例如,通过set mapred.reduce.tasks来设置Reduce的数量,或者通过distribute by rand()来尽量使每个Reduce处理的数据量均衡。
  • 使用CombineHiveInputFormat:将hive.input.format设置为org.apache.hadoop.hive.ql.io.CombineHiveInputFormat,可以在执行Map前进行小文件合并。

3. 使用压缩和存储格式优化

  • 文件压缩:使用gzip、bzip2、snappy等压缩算法对小文件进行压缩,可以减少磁盘空间和网络带宽的使用,并减少小文件损坏的可能性。
  • 存储格式优化:Hive支持多种存储格式,如ORC、Parquet等。这些格式允许将多个小文件压缩并序列化成一个大文件,从而提高存储效率和查询性能。

4. 定时合并任务

  • 定时调度:设置定时任务(如每天或每周)来合并小文件。这可以通过编写脚本或利用大数据平台的调度工具(如Airflow、Apache Oozie等)来实现。
  • 数据清洗任务:在数据传输或处理任务后,增加一个清洗任务来合并小文件。这可以确保从数据源开始,小文件就不会向下游流去。

5. 重建表

  • 无分区表重建:对于无分区的表,可以考虑直接将表删掉然后重建,使用新的配置或处理逻辑来避免小文件的产生。
  • 分区表优化:对于分区表,可以优化分区策略以减少小文件的产生。同时,也可以利用Hive的ALTER TABLE CONCATENATE等命令来合并分区中的小文件。

6. 垃圾回收

  • 定期删除过期数据:使用HDFS的TTL(Time-To-Live)机制或定期执行删除命令来删除过期或不再需要的数据,以减少HDFS的存储压力和元数据开销。
    综上所述,处理数据仓库中的小文件问题需要从多个方面入手,包括合并小文件、优化Hive配置、使用压缩和存储格式优化、设置定时合并任务、重建表以及垃圾回收等。在实际应用中,可以根据具体情况选择最合适的策略或组合多种策略来解决问题。

补充面试题

1. hdfs写入数据原理[面试]

在这里插入图片描述
1.客户端发起写入数据的请求给namenode
2.namenode接收到客户端请求,开始校验(是否有权限,路径是否存在,文件是否存在等),如果校验没问题,就告知客户端可以写入
3.客户端收到消息,开始把文件数据分割成默认的128m大小的的block块,并且把block块数据拆分成64kb的packet数据包,放入传输序列

4.客户端携带block块信息再次向namenode发送请求,获取能够存储block块数据的datanode列表
5.namenode查看当前距离上传位置较近且不忙的datanode,放入列表中返回给客户端
6.客户端连接datanode,开始发送packet数据包,第一个datanode接收完后就给客户端ack应答(客户端就可以传入下一个packet数据包),同时第一个datanode开始复制刚才接收到的数据包给node2,node2接收到数据包也复制给node3(复制成功也需要返回ack应答),最终建立了pipeline传输通道以及ack应答通道
7.其他packet数据根据第一个packet数据包经过的传输通道和应答通道,循环传入packet,直到当前block块数据传输完成(存储了block信息的datanode需要把已经存储的块信息定期的同步给namenode)

8.其他block块数据存储,循环执行上述4-7步,直到所有block块传输完成,意味着文件数据被写入成功(namenode把该文件的元数据保存上)
9.最后客户端和namenode互相确认文件数据已经保存完成(也会汇报不能使用的datanode)

2. 读取数据原理[面试]

在这里插入图片描述
1.客户端发送读取文件请求给namenode

2.namdnode接收到请求,然后进行一系列校验(路径是否存在,文件是否存在,是否有权限等),如果没有问题,就告知可以读取
3.客户端需要再次和namenode确认当前文件在哪些datanode中存储
4.namenode查看当前距离下载位置较近且不忙的datanode,放入列表中返回给客户端

5.客户端找到最近的datanode开始读取文件对应的block块信息(每次传输是以64kb的packet数据包),放到内存缓冲区中
6.接着读取其他block块信息,循环上述3-5步,直到所有block块读取完毕(根据块编号拼接成完整数据)
7.最后从内存缓冲区把数据通过流写入到目标文件中

8.最后客户端和namenode互相确认文件数据已经读取完成(也会汇报不能使用的datanode)

3. 元数据存储的原理[面试]

在这里插入图片描述
1.namenode第一次启动的时候先把最新的fsimage文件中内容加载到内存中,同时把edits文件中内容也加载到内存中
2.客户端发起指令(增删改查等操作),namenode接收到客户端指令把每次产生的新的指令操作先放到内存中
3.然后把刚才内存中新的指令操作写入到edits_inprogress文件中
4.edits_inprogress文件中数据到了一定阈值的时候,把文件中历史操作记录写入到序列化的edits备份文件中
5.namenode就在上述2-4步中循环操作…

6.当secondarynamenode检测到自己距离上一次检查点(checkpoint)已经1小时或者事务数达到100w,就触发secondarynamenode询问namenode是否对edits文件和fsimage文件进行合并操作
7.namenode告知可以进行合并
8.secondarynamenode将namenode上积累的所有edits和一个最新的fsimage下载到本地,并加载到内存进行合并(这个过程称checkpoint)
9.secondarynamenode把刚才合并后的fsimage.checkpoint文件拷贝给namenode

10.namenode把拷贝过来的最新的fsimage.checkpoint文件,重命名为fsimage,覆盖原来的文件

注意: 不要死记硬背,要结合自己的理解,转换为自己的话术,用于面试

4. hdfs如何保证数据安全:三大机制

4.1 副本机制:

为了保证数据安全和效率,block块信息存储多个副本,第一副本保存在客户端所在服务器,第二副本保存在和第一副本不同机架服务器上,第三副本保存在和第二副本相同机架不同服务器

4.2 负载均衡机制:

namenode为了保证不同的datanode中block块信息大体一样,分配存储任务的时候会优先保存在距离近且余量比较大的datanaode上

4.3 心跳机制:

datanode每隔3秒钟向namenode汇报自己的状态信息,如果某个时刻,datanode连续10次不汇报了,namenode会认为datanode有可能宕机了,namenode就会每5分钟(300000毫秒)发送一次确认消息,连续2次没有收到回复,就认定datanode此时一定宕机了(确认datanode宕机总时间310+52*60=630秒)。观察地址http://node3:9864/datanode.html

在这里插入图片描述

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!