1 写数据流程
1.1 写数据流程图解
- 在客户端上通过创建
DistributedFileSystem
对象进行操作数据
uri = URI.create("hdfs://192.168.153.131:8020");
conf = new Configuration();
user = "cxj";
// fs为DistributedFileSystem对象
fs = FileSystem.get(uri, conf, user);
- 在数据上传前,向
NameNode
请求上传文件/user/atguigu/ss.avi
(假定上传200M
的该内容)
FileInputStream fis = new FileInputStream(new File("C:\\Users\\cxj\\Desktop\\ss.avi"));
FSDataOutputStream fos = fs.create(new Path("/user/atguigu/ss.avi"));
// 数据拷贝到HDFS存储
IOUtils.copyBytes(fis, fos ,conf);
IOUtils.closeStream(fis);
IOUtils.closeStream(fos);
-
NameNode
响应可以上传文件 -
请求上传第一个
Block (0-128M)
,请返回DataNode
-
返回
dn1
,dn2
,dn3
节点(假设只有三个DataNode
的节点), 表示采用这三个节点存储数据 -
客户端可以通过
FSDataOutputStream
将输入的FileInputStream
流转换成对应的HDFS
相关的输出流,然后再进行资源的拷贝 -
客户端会查找传输距离最短的服务器。并请求建立数据传输通道,并且客户端只负责请求离他距离最近的节点(数据传输的距离),后续的就由节点负责,例如上述中d
ns1
负责dns2
,dns2
负责dns3
-
假设这里是
dns1
离客户端的传输距离最短,那么客户端只负责将数据传输到dns1
,然后dns1
负责后续的数据传递,如上图dns1
将数据传递给dns2
,再然后是dns2
传递到dns3
,从客户端到dns3
三个节点的信息传递的逻辑组成一个通道 -
信息的传递不是将整一个
128M
的信息完全传递(这里假设第一个数据块是128M
),而是分数据包进行传递,数据包大小一般是64kb
(数据包包括实际传输的数据以及数据的检验和),数据包传输到节点之前是存在DataQuene中,也就是数据队列中,当进行数据传输时,由DataStream从DataQuene进行取出数据包,然后传递给第一个节点,当数据包传递到具体的节点的时候,就会被存储到缓冲区之中,然后等待缓冲区满了再写进磁盘中 -
数据包被
DataStream
从DataQuene
拿出数据包后就放到ACKQuene
,当数据传输完成,节点会通过数据通道进行数据的应答,应答后的数据包经验证从ACKQuene
中删除 -
没有应答的数据包会重新从
ACKQuene
回到DataQuene
,并且建立新的通信通道,从而防止数据包传递过程中的丢包以及节点连接断开的情况 -
数据传输完成进行应答。重复上述过程,一直到整个数据块传输完成
数据传输过程中,如果存在某个节点不可用,那么最终数据的存储的副本数,就会比设置的要少,这个少的副本将会在后续由
NameNode
进行补全,所以至少有一个节点完成传输,那么就可以产生同样数量的副本
- 下一个数据块继续从
4
开始
2 节点距离计算
之类就是解决上文中,例如由客户端寻找最近距离的节点的问题。也就是如何衡量机器与机器之间的距离
2.1 实例图
2.2 原理与实例
说明:图上每一个颜色块可以看做一个节点,上方的颜色块可以看做是下方的父节点,那么层次关系就是:橙色块→集群d1蓝色快、集群d2绿色快→黄色快机架、蓝色块机架该结构就是一个局部的小型网络的拓扑结构图
计算规则:距离计算规则是表示两个机器到共同汇合点一个量的和,例子如下
-
Distance(/d1/r1/n0, /d1/r1/n0)=0
(同一节点上的进程)
表示从d1
集群上r1
机架的n0
机器到d1
集群上r1
机架的n0
机器,因为同一个机器,那么距离就是0
-
Distance(/d1/r1/n1, /d1/r1/n2)=2
(同一机架上的不同节点)
表示从d1
集群上r1
机架的n1
机器到d1
集群上r1
机架的n2
机器的距离是2
同一个机架,但是不同的机器,那么汇合点就是相当于父节点的d1
,二者都找到d1
,就能回去对方的信息,从n0
到d1
距离是1
,n2
也同样,那么和就是2
,所以距离就是2
-
Distance(/d1/r2/n0, /d1/r3/n2)=4
(同一数据中心不同机架上的节点)
表示从d1
集群上r2
机架的n0
机器到d1
集群上r3
机架的n2
机器
的距离是4
因为不同机架也不同机器节点,二者汇合在集群d1
上,那么机架r2
上机器n0
首先是找到r2
距离是1
,然后再由r2
找到d1
,距离也是1
,总距离就是2
,对于d3
上的n2
也是同样的,总距离是2
,那么二者距离之和就是4
4.Distance(/d1/r2/n1, /d2/r4/n1)
=6 (不同数据中心的节点)
表示从d1
集群上r2
机架的n0
机器到d2
集群上r4
机架的n1
机器的距离是6
二者不同集群,那么汇合点就是最顶层的橙色节点,那么集群d1
的机架r2
的n1
节点找到橙色节点距离就是3
,对于r4
的n1
也是3
,那么总距离就是6
3 副本存储节点策略
3.1 集群示例图
3.2 实例概述
假设设置的副本数是3
,例如咋hdfs-site.xml
中设置dfs.replication为3
或者不设置默认就是3
,那么三个副本存储的策略如下
- 如果当前进行客户端操作的节点同时也是一个
DataNode
那么第一个副本在Client
所处的节点上。如果客户端在集群外,随机选择一个DataNode
进行存储 - 第二个副本随机选择一个远程的机架,然后随机选择一个节点。例如第一个副本存储在机架
r1
上的n0
,那么第二个副本就可以选择r2
或者r3
- 第三个副本在第二个副本所在机架的随机节点
以上是
hadoop3.1.3
的副本选择策略,对于hadoop2.7.6
,第一个节点选择策略是一样的,第二个副本是在第一个节点同一机架的上随机的一个节点,第三个副本就是不同于前两个副本的一个机架上的一个随机节点
这么选择是兼容距离以及容错率的,要是都放一个机架,虽然距离近了,但是容错率低,一个机架坏了,就会所有副本都失效,所以需要分机架存放,然后兼容距离产生上述的同一支架放置以及客户端相关性的防止策略
4 读数据流程图解
- 在客户端上通过创建
DistributedFileSystem
对象进行操作数据
uri = URI.create("hdfs://192.168.153.131:8020");
conf = new Configuration();
user = "cxj";
// fs为DistributedFileSystem对象
fs = FileSystem.get(uri, conf, user);
HDFS
客户端在读取前进行询问NameNode
相关的元信息,NameNode
存储的相关的HDFS
目录信息以及相关的文件的元数据,在客户端询问后就进行返回相关的信息
FileInputStream fis = new FileInputStream(new File("C:\\Users\\cxj\\Desktop\\ss.avi"));
FSDataOutputStream fos = fs.create(new Path("/user/atguigu/ss.avi"));
// 拷贝下载
IOUtils.copyBytes(fis, fos ,conf);
IOUtils.closeStream(fis);
IOUtils.closeStream(fos);
- 客户端根据返回的相关块信息去寻找需要的块,他会寻找存储了该块的最近的节点,进行请求数据块,然后节点进行应答并返回块信息
对于设置的副本数小于总的
DataNode
的节点数,会按上文的副本分配策略进行分配,客户端的所有数据块可能存储在不同的节点上