您现在的位置是:首页 >技术交流 >Hadoop HDFS 读写流程网站首页技术交流
Hadoop HDFS 读写流程
简介Hadoop HDFS 读写流程
HDFS 写流程
HDFS 的写数据流程 :
- 客户端通过 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 步)
代码分析 :
网络拓扑
HDFS 写数据时, NameNode 会选择距离 Clinet 最近 DataNode 接收数据
- 节点距离:两个节点到达最近的共同祖先的距离总和
节点距离计算 : 如 : 数据中心 d1 机架 r1 中的节点 n1 , 该节点表示为 /d1/r1/n1
情况 | 集群 | 机架 | 节点 | 距离 | 情况 |
---|---|---|---|---|---|
设备1 | d1 | r1 | n0 | 0 | 同一节点上的进程 |
设备2 | d1 | r1 | n0 | ||
设备1 | d1 | r1 | n0 | 2 | 同一机架上的不同节点 |
设备2 | d1 | r1 | n2 | ||
设备1 | d1 | r1 | n0 | 4 | 同一数据中心不同机架上的节点 |
设备2 | d1 | r2 | n0 | ||
设备1 | d1 | r1 | n0 | 6 | 不同数据中心的节点 |
设备2 | d2 | r1 | n0 |
机架感知
副本放置策略 (副本 : 3) :
- 副本1 : Client 的节点上。当客户端在集群外, 随机选 ( 快速写入 )
- 副本2 : 另个机架的随机一个节点 ( 应对交换机故障 )
- 副本3 : 副本2 的机架的随机节点 ( 减少跨 rack 的网络流量 )
此策略好处 :
- 减少了机架间写入流量,提高写入性能
- 不影响数据可靠性和可用性 , 因为机架故障的几率远小于节点故障
- 减少了读取数据时 , 使用的总网络带宽,因为一个块只放置在两个独特的机架中,而不是三个
- 文件的副本并非均匀分布在机架上。1 / 3 的副本在一个节点上,1 / 3 的副本在一个机架上,1/ 3 均匀分布在剩余的机架上
源码说明
Idea 中
org.apache.hadoop.hdfs.server.blockmanagement;
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>3.1.3</version>
</dependency>
Crtl + n 查找 BlockPlacementPolicyDefault
,在该类中查找 chooseTargetInOrder
方法
protected Node chooseTargetInOrder() {
int numOfResults = results.size();
if (numOfResults == 0) {
// 本地
DatanodeStorageInfo storageInfo = this.chooseLocalStorage();
}
if (numOfResults <= 1) {
// 远程
this.chooseRemoteRack();
}
if (numOfResults <= 2) {
if (this.clusterMap.isOnSameRack(dn0, dn1)) {
// 上一个本地, 这就远程
this.chooseRemoteRack();
} else if (newBlock) {
// 本地
this.chooseLocalRack();
} else {
// 本地
this.chooseLocalRack();
}
}
}
HDFS 读流程
读流程 :
- 客户端通过 DistributedFileSystem 向 NameNode 请求下载文件, NameNode 通过查询元数据,找到文件块所在的 DataNode 地址
- 选一台 DataNode (就近原则,数据量大就会随机),请求读取数据
- DataNode 开始传输数据给客户端(从磁盘读到输入流,以 Packet 为单位来做校验)
- 客户端接收数据 ( 单位: Packet),先在本地缓存,然后写入目标文件
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。