目录
网络拓扑-节点距离
节点距离:两个节点到达最近的共同祖先的距离总和。
如果将数据中心d1里的机架r1上的节点n1定义为/d1/r1/n1的话,那么将会有以下结果:
- distance(/d1/r1/n1, /d1/r1/n1) = 0 (同一节点上的两个应用程序)
- distance(/d1/r1/n1, /d1/r1/n2) = 2 (同一机架上的两个节点)
- distance(/d1/r1/n1, /d1/r2/n3) = 4 (同一数据中心里不同机架上的两个节点)
- distance(/d1/r1/n1, /d2/r3/n4) = 6 (不同数据中心的两个节点)
读过程
如下图所示,假设HDFS客户端需要读取文件one.txt,文件one.txt被分为两个数据块,分别为BlockA和BlockB。副本数为3。BlockA存放在D2,D5,D7;BlockB存放在D3,D9,D11。
HDFS客户端与NameNode通信
- 因为NameNode存放了one.txt的数据块的元数据,所以客户端需要向NameNode发出请求,请求获取存放了one.txt的数据块的DataNode列表。
- NameNode收到客户端发来的请求,首先检查客户端用户的权限。如果客户端用户有足够的权限,NameNode接着检查请求的文件是否存在。如果存在,NameNode会发送存放了one.txt的数据块的DataNode列表(该列表的DataNode按照客户端到DataNode的距离由小到大排列)。同时,NameNode会给予客户端一个安全令牌,当客户端访问DataNode时,需要使用令牌进行认证。
HDFS客户端与DataNode通信
- 当客户端收到NameNode发过来的DataNode列表,客户端直接与DataNode通信。通过FSDataInputStream对象给距离客户端最近的DataNode(在D2的BlockA和在D3的BlockB)发送请求。其中,DFSInputStream管理客户端和DataNode之间的通信。
- 客户端用户向DataNode展示NameNode给的安全令牌,然后开始从DataNode读取数据,数据将以流的形式从DataNode流向客户端。
- 读取完所有数据块时,客户端调用close()方法关闭FSDataInputStream。
HDFS读数据的详细过程
- 客户端调用FileSystem的 open() 方法(在HDFS文件系统中DistributedFileSystem具体实现了FileSystem)。
- DistributedFileSystem通过RPC远程调用NameNode,请求获取存放了one.txt的开始几个数据块的DataNode的位置。然后NameNode返回存放该数据块的所有DataNode的地址(NameNode根据距离客户端的远近对DataNode进行排序)
- open()之后,DistributedFileSystem返回一个FSDataInputStream输入流给客户端。对于HDFS而言,具体的输入流是DFSInputStream,DistributedFileSystem会利用DFSInputStream实例化FSDataInputStream。
- 客户端调用 read() 方法读取数据。输入流DFSInputStream根据得到的排序结果,选择距离客户端最近的DataNode建立连接并读取数据。接着数据以流的形式从DataNode流向客户端。
- 当该数据块读取完毕时,DFSInputStream关闭与该DataNode的连接。然后向NameNode发出请求,获取下一个数据块的位置(如果客户端缓存中已经包含该数据块的信息,就不需要请求NameNode)
- 找到下一个数据块最佳的DataNode,读取数据。
- 如果DFSInputStream在读取的过程中,与正在通信的DataNode发生错误,客户端将选择其它距离它最近的DataNode。DFSInputStream也会标记那些发生故障的DataNode,避免下一个块再读取这些DataNode。同时,DFSInputStream会校验数据的检验和,如果发现有错误,会向NameNode汇报,然后读取其它的DataNode。
- 当客户端读取完全部数据,调用FSDataInputS