9.1 从HDFS
读取数据的流程
9.1.1 剖析文件的读取
说明:
客户端通过调用
FileSystem
对象的open()
方法来打开希望读取的文件. 这个FileSystem
对象是DistributedFileSystem
的一个对象.DistributedFileSystem
通过RPC(远程过程调用)
来调用namenode
, 然后namenode
就会返回这个文件的每一个快的位置信息(datanode
的地址).返回的这些
datanode
会根据他们与客户端的距离进行排序.open()
方法返回的是一个FSDataInputStream
对象. 通过这个对象就可以读取数据了. 这个对象管理着datanode
和datanode
的IO
调用
FSDataInputStream
对象的read()
方法, 则FSDataInputStream
会从距离客户端最近的datanode
读取第一个块的数据.随着反复的调用
read()
, 第一个块的数据被读完, 则关闭连接, 然后寻找下一个块的最佳datanode
所有的这些操作都是透明的, 对客户端来说,仿佛他一直在读取一个连续的流一样.
如果从
datanode
读取数据的时候遇到错误, 则会尝试从这个快的另一个最邻近的datanode
读取数据.它也会记住那个故障
datanode
, 保证以后不会反复读取存储在该节点上的后续的块.FSDataInputStream
也会通过校验和确认从datanode
发来的数据是否完整, 如果有损坏的块, 也会试图从其他datanode
读取副本, 也会将损坏的块通知namenode
9.1.2 网络拓扑的概念
客户端读取数据的时候, 我们经常说从最近的datanode
读取数据, 那么Hadoop
是如何衡量客户端与datanode
之间的远近的呢?
在海量数据处理中, 其主要限制因素是节点之间数据的传输速率(带宽的稀缺性). 所以, Hadoop
将两个节点之间的带宽作为距离的衡量标准.
那么Hadoop
又是如何衡量两个节点之间的带宽的呢?
Hadoop
采用了最简单的办法: 把网络看作一棵树, 则, 两个节点之间的距离是他们到共同的祖先(一般是网络交换机)的距离和.
节点表示法
假设有:
- 数据中心:data1
- 机架: rack1
- 节点: node1
则节点node1可以表示为:data1/rack1/node1
四种距离分别为:
同一节点上的进程间的距离:
dis(data1/rack1/node1,data1/rack1/node1) = 0
同一机架不同节点:
dis(data1/rack1/node1,data1/rack1/node2) = 2
同一数据中心, 不同机架:
dis(data1/rack1/node1,data1/rack2/node1) = 4
不同数据中心:
dis(data1/rack1/node1,data2/rack1/node1) = 6
另外Hadoop
并不能自动发现每个节点的网络拓扑结构, 我们需要进行相应的配置. 此处暂且不讲如何配置.
9.1.3 机架感知
如果Hadoop
知道了网络拓扑结构, 那么, HDFS
在存储数据的副本的时候, 是如何选择节点呢? 这就是所谓的机架感知(Rack Awareness
).
Hadoop
主要从数据可靠性和读写性能来选择副本的放置.
参考文章: http://hadoop.apache.org/docs/r2.7.2/hadoop-project-dist/hadoop-common/RackAwareness.html
现总结如下:
默认情况下, 每个数据块有三个副本.
第一个副本放在客户端(
client
)所在的datanode
上. 如果client
没有在datanode
上, 则随机选一个datanode
.第二个副本放在与第一个副本同一个机架内的不同节点上.
第三个副本放在与第一第二副本不同的机架内的随机节点上.