Hadoop 中的大数据技术:HDFS(2)
续上一篇Hadoop 中的大数据技术:HDFS(1)
大家好!在为您带来精彩的技术干货之前,先给您推荐一个我精心运营的公众号[大数据深度洞察]。在这里,您将获取更多独家的技术分享、实用案例以及行业前沿资讯。
亲爱的读者们,当您准备开启这篇充满价值的技术文章之旅时,不妨先关注我的公众号[大数据深度洞察]。它是您在技术领域不断成长的好伙伴。
第 4 章 HDFS 的读写流程(面试关键要点)
4.1 HDFS 写数据流程
4.1.1 深入剖析文件写入过程
- 客户端借助
Distributed FileSystem
模块向NameNode
发起上传文件的请求,NameNode
会对目标文件是否存在以及父目录是否存在进行核查。 NameNode
给出能否上传的回应。- 客户端请求确定第一个
Block
应上传至哪些DataNode
服务器。 NameNode
回传 3 个DataNode
节点,例如dn1
、dn2
、dn3
。- 客户端通过
FSDataOutputStream
模块向dn1
发出上传数据的请求,dn1
接收请求后会接着联络dn2
,然后dn2
再联系dn3
,以此完成通信管道的构建。 dn1
、dn2
、dn3
依次对客户端做出应答。- 客户端开始向
dn1
上传第一个Block
(首先从磁盘读取数据并放置于本地内存缓存中),以Packet
为单位,dn1
每收到一个Packet
就会传递给dn2
,dn2
再传递给dn3
;dn1
每传输一个packet
都会将其放入一个应答队列以等待回应。 - 当一个
Block
传输结束后,客户端再次向NameNode
请求上传第二个Block
的服务器。(重复执行 3 - 7 步)。
4.1.2 网络拓扑 - 节点距离计算
在 HDFS 进行写数据操作时,
NameNode
会选取距离待上传数据最近的
DataNode
来接收数据。那么,这个最近距离是如何计算得出的呢?
节点距离:指两个节点抵达最近的共同祖先的距离总和。
例如,假设有位于数据中心
d1
、机架
r1
中的节点
n1
。该节点可表示为
/d1/r1/n1
。基于这种标记方式,这里给出四种距离的描述。
请大家计算每两个节点之间的距离。
4.1.3 机架感知(副本存储节点选择)
- 机架感知说明- 官方说明
http://hadoop.apache.org/docs/r3.1.3/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html#Data_Replication``````For the common case, when the replication factor is three, HDFS’s placement policy is to put one replica on the local machine if the writer is on a datanode, otherwise on a random datanode, another replica on a node in a different (remote) rack, and the last on a different node in the same remote rack. This policy cuts the inter-rack write traffic which generally improves write performance. The chance of rack failure is far less than that of node failure; this policy does not impact data reliability and availability guarantees. However, it does reduce the aggregate network bandwidth used when reading data since a block is placed in only two unique racks rather than three. With this policy, the replicas of a file do not evenly distribute across the racks. One third of replicas are on one node, two thirds of replicas are on one rack, and the other third are evenly distributed across the remaining racks. This policy improves write performance without compromising data reliability or read performance.
如下为翻译:对于常见情况,当副本因子为 3 时,HDFS 的放置策略是:如果写入者在数据节点上,则将一个副本放在本地机器上,否则放在随机的数据节点上;另一个副本放在不同(远程)机架的节点上,最后一个副本放在同一远程机架的不同节点上。此策略减少了机架间的写入流量,通常能提高写入性能。机架故障的概率远低于节点故障;此策略不会影响数据的可靠性和可用性保证。然而,由于一个数据块仅放置在两个独特的机架而不是三个,这确实减少了读取数据时使用的聚合网络带宽。通过此策略,文件的副本不会在机架之间均匀分布。三分之一的副本在一个节点上,三分之二的副本在一个机架上,其余三分之一均匀分布在其余机架上。此策略在不影响数据可靠性或读取性能的情况下提高了写入性能。- 源码说明 按下Ctrl + n
查找BlockPlacementPolicyDefault
,在该类中查找chooseTargetInOrder
方法。 Hadoop 3.1.3
副本节点选择
4.2 HDFS 读数据流程
- 客户端通过
DistributedFileSystem
向NameNode
请求下载文件,NameNode
通过查询元数据,找出文件块所在的DataNode
地址。 - 选取一台
DataNode
(遵循就近原则,然后随机选择)服务器,并向其请求读取数据。 DataNode
开始向客户端传输数据(从磁盘中读取数据输入流,并以Packet
为单位进行校验)。- 客户端以
Packet
为单位接收数据,先在本地进行缓存,而后写入目标文件。
第 5 章 NameNode 与 SecondaryNameNode
5.1 NN 和 2NN 的工作机制
思考:NameNode 中的元数据究竟存于何处?
首先,假设一下,如果将其存储在 NameNode 节点的磁盘中,由于需要频繁进行随机访问,还要响应客户请求,必然效率低下。所以,元数据需要存放在内存中。然而,若只存于内存,一旦断电,元数据丢失,整个集群便无法正常工作。于是,就有了在磁盘中备份元数据的 FsImage。
这又带来新的问题,当内存中的元数据更新时,如果同步更新 FsImage,会导致效率不高;但如果不更新,就会出现一致性问题,一旦 NameNode 节点断电,就会造成数据丢失。因此,引入了 Edits 文件(仅进行追加操作,效率较高)。每当元数据有更新或者新增时,先修改内存中的元数据,再追加到 Edits 中。如此,一旦 NameNode 节点断电,可以通过 FsImage 和 Edits 的合并,重新合成元数据。
不过,如果长时间向 Edits 中添加数据,会致使该文件过大,效率降低,而且一旦断电,恢复元数据所需时间过长。所以,需要定期进行 FsImage 和 Edits 的合并,若此操作由 NameNode 节点完成,效率又会很低。故而,引入一个新的节点 SecondaryNameNode,专门负责 FsImage 和 Edits 的合并。
- 第一阶段:NameNode 启动 - 首次启动 NameNode 并格式化后,会创建 Fsimage 和 Edits 文件。若并非首次启动,则直接将编辑日志和镜像文件加载至内存。- 客户端发出对元数据进行增删改的请求。- NameNode 记录操作日志,更新滚动日志。- NameNode 在内存中对元数据进行增删改操作。
- 第二阶段:Secondary NameNode 工作 - Secondary NameNode 询问 NameNode 是否需要进行 CheckPoint,并直接带回 NameNode 的检查结果。- Secondary NameNode 请求执行 CheckPoint。- NameNode 滚动正在编写的 Edits 日志。- 将滚动前的编辑日志和镜像文件拷贝至 Secondary NameNode。- Secondary NameNode 加载编辑日志和镜像文件至内存,然后进行合并。- 生成新的镜像文件 fsimage.chkpoint。- 把 fsimage.chkpoint 拷贝至 NameNode。- NameNode 将 fsimage.chkpoint 重新命名为 fsimage。
5.2 Fsimage 和 Edits 解析
- 利用 oiv 查看 Fsimage 文件- 查看 oiv 和 oev 命令
[lzl@hadoop12 current]$ hdfs
oiv 对 fsimage 应用离线 fsimage 查看器 oev 对 edits 文件应用离线 edits 查看器- 基本语法 hdfs oiv -p 文件类型 -i 镜像文件 -o 转换后的文件输出路径- 案例实操[lzl@hadoop12 current]$ pwd/opt/module/hadoop-3.1.3/data/dfs/name/current[lzl@hadoop12 current]$ hdfs oiv -p XML -i fsimage_0000000000000000025 -o /opt/module/hadoop-3.1.3/fsimage.xml[lzl@hadoop12 current]$ cat /opt/module/hadoop-3.1.3/fsimage.xml
将显示的 xml 文件内容拷贝至 Idea 中创建的 xml 文件,并进行格式化。部分显示结果如下。<inode><id>16386</id><type>DIRECTORY</type><name>user</name><mtime>1512722284477</mtime><permission>lzl:supergroup:rwxr-xr-x</permission><nsquota>-1</nsquota><dsquota>-1</dsquota></inode><inode><id>16387</id><type>DIRECTORY</type><name>lzl</name><mtime>1512790549080</mtime><permission>lzl:supergroup:rwxr-xr-x</permission><nsquota>-1</nsquota><dsquota>-1</dsquota></inode><inode><id>16389</id><type>FILE</type><name>wc.input</name><replication>3</replication><mtime>1512722322219</mtime><atime>1512722321610</atime><perferredBlockSize>134217728</perferredBlockSize><permission>lzl:supergroup:rw-r--r--</permission><blocks><block><id>1073741825</id><genstamp>1001</genstamp><numBytes>59</numBytes></block></blocks>
思考:可以看出,Fsimage 中并未记录块所对应的 DataNode,这是为何?****在集群启动后,要求 DataNode 上报数据块信息,并间隔一段时间后再次上报。解释:Fsimage 文件的作用- Fsimage 文件:Fsimage 是HDFS NameNode中的一个重要组成部分,它保存了整个文件系统的元数据(如文件目录结构、权限信息等)的一个持久化快照。- Fsimage 不记录块位置的原因:Fsimage 中不记录块所对应的DataNode信息,主要是因为这样的设计使得NameNode能够更加灵活地管理数据块的位置和副本。如果Fsimage中记录了每个块的具体位置,那么每次DataNode的增减或者块的复制都会引起Fsimage的更新,这会导致Fsimage变得庞大且难以管理。DataNode 向 NameNode 上报数据块信息的原因- 初始上报:当集群启动时,每个DataNode会向NameNode上报其所持有的所有数据块信息。这是因为NameNode需要构建一个完整的块位置映射表,即了解哪些块存储在哪些DataNode上。- 周期性上报:DataNode还会定期(默认每6小时)向NameNode报告它们当前所拥有的数据块信息。这种机制有助于NameNode保持最新的块位置信息,并及时发现任何数据丢失或节点故障的情况。总结- 灵活性:Fsimage不记录块位置信息的设计增强了NameNode的灵活性,使得它能够在不影响整体系统的情况下调整块的位置和副本数量。- 效率:通过DataNode定期向NameNode上报块信息的方式,NameNode可以高效地管理数据块的位置信息,并且可以随时根据需要调整数据分布。 - 利用 oev 查看 Edits 文件- 基本语法 hdfs oev -p 文件类型 -i 编辑日志 -o 转换后的文件输出路径- 案例实操
[lzl@hadoop12 current]$ hdfs oev -p XML -i edits_0000000000000000012 - 0000000000000000013 - o /opt/module/hadoop - 3.1.3/edits.xml[lzl@hadoop12 current]$ cat /opt/module/hadoop - 3.1.3/edits.xml
将显示的 xml 文件内容拷贝至 Idea 中创建的 xml 文件,并进行格式化。显示结果如下。<EDITS><EDITS_VERSION>-63</EDITS_VERSION><RECORD><OPCODE>OP_START_LOG_SEGMENT</OPCODE><DATA><TXID>129</TXID></DATA></RECORD><RECORD><OPCODE>OP_ADD</OPCODE><DATA><TXID>130</TXID><LENGTH>0</LENGTH><INODEID>16407</INODEID><PATH>/hello7.txt</PATH><REPLICATION>2</REPLICATION><MTIME>1512943607866</MTIME><ATIME>1512943607866</ATIME><BLOCKSIZE>134217728</BLOCKSIZE><CLIENT_NAME>DFSClient_NONMAPREDUCE_-1544295051_1</CLIENT_NAME><CLIENT_MACHINE>192.168.10.102</CLIENT_MACHINE><OVERWRITE>true</OVERWRITE><PERMISSION_STATUS><USERNAME>lzl</USERNAME><GROUPNAME>supergroup</GROUPNAME><MODE>420</MODE></PERMISSION_STATUS><RPC_CLIENTID>908eafd4-9aec-4288-96f1-e8011d181561</RPC_CLIENTID><RPC_CALLID>0</RPC_CALLID></DATA></RECORD><RECORD><OPCODE>OP_ALLOCATE_BLOCK_ID</OPCODE><DATA><TXID>131</TXID><BLOCK_ID>1073741839</BLOCK_ID></DATA></RECORD><RECORD><OPCODE>OP_SET_GENSTAMP_V2</OPCODE><DATA><TXID>132</TXID><GENSTAMPV2>1016</GENSTAMPV2></DATA></RECORD><RECORD><OPCODE>OP_ADD_BLOCK</OPCODE><DATA><TXID>133</TXID><PATH>/hello7.txt</PATH><BLOCK><BLOCK_ID>1073741839</BLOCK_ID><NUM_BYTES>0</NUM_BYTES><GENSTAMP>1016</GENSTAMP></BLOCK><RPC_CLIENTID></RPC_CLIENTID><RPC_CALLID>-2</RPC_CALLID></DATA></RECORD><RECORD><OPCODE>OP_CLOSE</OPCODE><DATA><TXID>134</TXID><LENGTH>0</LENGTH><INODEID>0</INODEID><PATH>/hello7.txt</PATH><REPLICATION>2</REPLICATION><MTIME>1512943608761</MTIME><ATIME>1512943607866</ATIME><BLOCKSIZE>134217728</BLOCKSIZE><CLIENT_NAME></CLIENT_NAME><CLIENT_MACHINE></CLIENT_MACHINE><OVERWRITE>false</OVERWRITE><BLOCK><BLOCK_ID>1073741839</BLOCK_ID><NUM_BYTES>25</NUM_BYTES><GENSTAMP>1016</GENSTAMP></BLOCK><PERMISSION_STATUS><USERNAME>lzl</USERNAME><GROUPNAME>supergroup</GROUPNAME><MODE>420</MODE></PERMISSION_STATUS></DATA></RECORD></EDITS >
思考:NameNode 如何确定下次开机启动时要合并哪些 Edits?答:NameNode 在Hadoop HDFS中负责管理文件系统的元数据,包括文件和目录的属性、文件到数据块的映射、以及数据块到DataNode的映射等信息。为了确保元数据的一致性和持久性,NameNode使用Fsimage和Edit log(Edits)两种文件来存储这些信息。- Fsimage:Fsimage是一个持久化的文件,它存储了文件系统元数据的一个快照。- Edits:Edits是一系列的日志文件,记录了自上次Fsimage创建以来发生的所有更改操作。当NameNode重启时,它需要将Fsimage与最新的Edits合并,以重建最新的元数据状态。以下是NameNode确定要合并哪些Edits的步骤:1. 确定最新的Fsimage: - NameNode首先找到最新的Fsimage文件,这是它重启时的基础元数据状态。2. 查找最新的Edits: - NameNode会查找自上一个Fsimage创建以来的所有Edits文件。Edits文件按照时间顺序命名,通常以创建时间戳命名,因此NameNode可以很容易地确定最新的Edits文件。3. 合并Edits: - NameNode会从最早的Edits文件开始,依次读取并应用每个Edits文件中的更改操作。这个过程称为checkpoint或checkpointing,它会将Edits中的所有更改应用到Fsimage上,从而重建最新的文件系统元数据状态。4. 生成新的Fsimage: - 一旦所有的Edits都被合并,NameNode就会创建一个新的Fsimage文件,这反映了合并后的最新元数据状态。这个新的Fsimage文件将作为下一次重启的基础。5. 清理旧的Edits: - 为了节省磁盘空间,NameNode可能会删除那些已经被合并到Fsimage中的旧Edits文件。小结- 目的:通过这种方式,NameNode可以在重启后快速恢复到最新的文件系统状态,同时保持元数据的一致性和完整性。- 机制:NameNode通过将Fsimage与最新的Edits合并来实现这一点,确保每次重启时都能正确地恢复文件系统的元数据。这种机制保证了即使在NameNode突然崩溃的情况下,也可以通过上述步骤恢复文件系统的元数据,从而保证HDFS的可靠性和一致性。
5.3 CheckPoint 时间设置
- 通常情况下,SecondaryNameNode 每隔一小时执行一次。 [hdfs-default.xml]
<property><name>dfs.namenode.checkpoint.period</name><value>3600s</value></property>
- 每分钟检查一次操作次数,当操作次数达到 100 万时,SecondaryNameNode 执行一次。
<property><name>dfs.namenode.checkpoint.txns</name><value>1000000</value><description>操作动作次数</description></property><property><name>dfs.namenode.checkpoint.check.period</name><value>60s</value><description> 1 分钟检查一次操作次数</description></property>
第6章 DataNode
6.1 DataNode的工作机制
- 数据块存储 每个数据块在DataNode上以文件形式存储在磁盘上,包含两个文件:数据本身及元数据。元数据包含了数据块的长度、校验和以及时间戳等信息。
- 注册与报告 DataNode启动后会向NameNode注册,并定期(默认每6小时)上报其所有块的信息。相关的配置参数如下:
<property> <name>dfs.blockreport.intervalMsec</name> <value>21600000</value> <description>Block reporting interval in milliseconds.</description></property><property> <name>dfs.datanode.directoryscan.interval</name> <value>21600s</value> <description>Interval in seconds for Datanode to scan data directories and reconcile differences between in-memory and on-disk blocks.</description></property>
- 心跳机制 DataNode会每3秒向NameNode发送一次心跳,其中可能包含NameNode分配的任务,例如复制块数据到另一台机器或删除某个数据块。若超过10分钟未接收到某个DataNode的心跳,则认为该节点已离线。
- 动态扩展 在集群运行期间,可以安全地加入或移除节点。
6.2 数据完整性保障
- 场景思考 如果存储控制高铁信号灯指令的数据磁盘出现故障,导致始终显示绿灯,这将是极其危险的情况。同样地,如果DataNode上的数据损坏而未被检测到,也会带来风险。以下是如何确保数据完整性的措施:
- 校验机制 当DataNode读取Block时,会计算校验和(CheckSum)。如果计算出的校验和与Block创建时的值不符,表明Block已损坏。
- 冗余读取 客户端可以通过读取其他DataNode上的Block来获取所需数据。
- 校验算法 常见的校验算法包括CRC32、MD5和SHA1等。
- 周期性验证 DataNode会在文件创建后定期验证校验和。
6.3 掉线时限参数配置
- 配置说明在hdfs-site.xml配置文件中,需要关注heartbeat.recheck.interval(单位为毫秒)和dfs.heartbeat.interval(单位为秒)这两个参数。示例配置如下:
<property> <name>dfs.namenode.heartbeat.recheck-interval</name> <value>300000</value></property><property> <name>dfs.heartbeat.interval</name> <value>3</value></property>
感谢您阅读完这篇文章,如果您觉得有所收获,别忘了关注我的公众号[大数据深度洞察],更多精彩内容等您来探索!”
“希望本文能对您有所帮助,如果您还想获取更多类似的优质内容,欢迎关注我的公众号[大数据深度洞察],让我们一起在技术的海洋中遨游!”
“如果您喜欢这篇文章的内容,期待在公众号[大数据深度洞察]中与您有更多的交流,那里有更多深度的技术文章和实用的技巧等着您!
版权归原作者 大数据深度洞察 所有, 如有侵权,请联系我们删除。