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.第二个副本放在与第一个副本同一个机架内的不同节点上.
第三个副本放在与第一第二副本不同的机架内的随机节点上.
