Hadoop 是一个开源的分布式系统基础架构,用于存储和处理大规模数据集。它主要包含 HDFS(Hadoop Distributed File System)分布式文件系统、MapReduce 分布式计算框架以及 YARN(Yet Another Resource Negotiator)资源管理器。HDFS 负责数据的分布式存储,将大文件分割成多个数据块存储在不同节点上;MapReduce 用于分布式并行处理数据;YARN 则负责集群资源的管理和调度,为不同的应用程序分配计算资源。
MapReduce 是一种分布式计算编程模型,用于大规模数据集的并行处理。它主要由 Map 和 Reduce 两个阶段组成,并且中间会有 Shuffle 过程来进行数据的重组和分发。
spilit 是在mr 处理的map端之前产生的概念,split切片大小,默认等于block*1.1,在FileInputFormat中计算切片大小的逻辑:
blocksize:默认是 128M,可通过 dfs.blocksize 修改
minSize:默认是 1,可通过 mapreduce.input.fileinputformat.split.minsize 修改
maxsize:默认是 Long.MaxValue,可通过 mapreduce.input.fileinputformat.split.maxsize 修改
Hadoop FileInputFormat 源码:
public static final String SPLIT_MAXSIZE = "mapreduce.input.fileinputformat.split.maxsize";
public static final String SPLIT_MINSIZE = "mapreduce.input.fileinputformat.split.minsize";
protected long computeSplitSize(long blockSize, long minSize, long maxSize) {
return Math.max(minSize, Math.min(maxSize, blockSize));
}
为什么split不是与block 一一对应的?
大量小文件场景,map进程造成资源严重浪费。
针对大小文件场景可以手动配置。
namenode,在基于主从架构的hdfs文件系统中是主节点,其主要职责就是对hdfs中的文件的元信息,副本数,文件目录树,block 数据节点信息;
datanode,它是从节点也是数据节点,基于本地磁盘存储 block(文件的形式),有相关数据块的长度、效验和、时间戳,与namnode保持心跳,汇报 block 状态。
secondaryNameNode,检查点节点,namenode 日志高可用的关键,其主要作用就是将namenode的元数据日志信息合并后备份,防止元数据丢失。
元信息:是数据文件的block大小,文件副本存储位置,副本数量,block 数量,主要体现在edits文件和fsimage文件。
副本数:hdfs 中同一个文件在多个节点中所存储的总数量,也是实现持久化和保证安全性的关键。
文件目录树:hdfs提供了一个可以维护的文件目录,该文件目录下存储着有关所有hdfs的文件。
block 数据节点信息:如a文件在01和02节点中存储,该信息称为数据节点信息。
HDFS 采用主从架构,主要由 NameNode 和 DataNode 组成。
工作原理方面,当客户端进行写操作时,首先向 NameNode 请求上传文件,NameNode 检查目标文件是否已存在以及父目录是否存在,确认可以上传后,返回可用的 DataNode 节点列表。客户端将文件数据按块写入第一个 DataNode,第一个 DataNode 会将数据块同步复制到列表中的其他 DataNode,形成数据的冗余备份。在读取数据时,客户端向 NameNode 请求下载文件,NameNode 根据元数据找到文件对应的数据块所在的 DataNode 地址,客户端从这些 DataNode 读取数据块并组装成完整的文件。
客户端通过 DistributedFileSystem 向 NameNode 发起读取文件的请求。
NameNode 根据元数据信息,查找文件对应的所有数据块的存储位置,返回数据块所在的 DataNode 列表。
客户端从返回的 DataNode 列表中选择一个 DataNode(通常采用就近原则,优先选择网络距离近的节点),向其发送读取数据块的请求。
被选中的 DataNode 开始从本地磁盘读取数据块,将数据以 Packet(数据包)为单位传输给客户端。客户端接收 Packet 并进行校验,在校验无误后,将数据组装成完整的数据块。
客户端按照文件的数据块顺序,依次从各个 DataNode 读取所有数据块,最终组装成完整的文件。
客户端通过 DistributedFileSystem 向 NameNode 发起上传文件的请求。
NameNode 检查目标文件是否已存在,以及父目录是否存在。若目标文件不存在且父目录存在,则允许上传,否则返回错误信息。
NameNode 根据数据块副本策略,返回一组 DataNode 节点列表,用于存储文件的数据块副本。
客户端与第一个 DataNode 建立连接,开始上传数据。客户端将数据按 Packet 写入第一个 DataNode,第一个 DataNode 在接收到 Packet 后,会将其转发给第二个 DataNode,第二个 DataNode 再转发给第三个 DataNode(假设副本数为 3),形成数据的流水线复制。
每个 DataNode 在接收到 Packet 后,会进行校验和存储操作,并向客户端发送确认消息。当客户端接收到所有副本 DataNode 的确认消息后,认为该数据块上传成功。
客户端继续上传下一个数据块,重复上述步骤,直到整个文件上传完成。
Secondary NameNode 并非 NameNode 的热备节点,它的主要作用是协助 NameNode 进行元数据的管理和恢复。它会定期与 NameNode 进行通信,从 NameNode 获取命名空间镜像文件(fsimage)和编辑日志文件(edits)。然后,Secondary NameNode 将 fsimage 加载到内存中,并将 edits 中的操作应用到 fsimage 上,生成一个新的合并后的 fsimage 文件。这个新的 fsimage 文件会被传输回 NameNode,NameNode 用它替换旧的 fsimage 文件,并将编辑日志文件清空。通过这种方式,Secondary NameNode 可以减少 NameNode 在进行元数据检查点操作时的负担,加快 NameNode 在故障恢复时的速度,因为恢复时可以直接使用合并后的 fsimage 文件,而不需要重新应用大量的编辑日志操作。
为了解决 NameNode 的单点故障问题,主要采用以下几种方案:
Hadoop 的块是 HDFS 中数据存储的基本单位。一个文件在 HDFS 中会被分割成多个块进行存储,每个块的大小可以通过配置参数设置,默认大小在 Hadoop 2.x 版本中通常为 128MB。
使用块的主要原因如下:
HDFS 中的数据块大小是可以配置的。在 Hadoop 的配置文件hdfs-site.xml中,可以通过设置dfs.blocksize属性来指定数据块的大小。例如,要将数据块大小设置为 256MB,可以在hdfs-site.xml中添加如下配置:
dfs.blocksize
268435456
修改完配置文件后,需要重启 Hadoop 集群的 NameNode 和 DataNode 服务,使配置生效。需要注意的是,合理设置数据块大小非常重要,过大或过小的块大小都可能影响系统的性能。块设置过大,从磁盘传输数据的时间会明显大于寻址时间,导致程序在处理这块数据时变得非常慢;块设置过小,存放大量小文件会占用 NameNode 中大量内存来存储元数据,而且文件块过小,寻址时间增大,导致程序一直在找 block 的开始位置。