一、写入
- 客户端创建Distributed File System对象,调用该对象的create()方法,创建FSDataOutputStream对象。
- Distributed File System对象通过RPC,在namenode中创建一个空的Entry。
- FSDataOutputStream对象读入数据,并将数据打包(默认64M),写入对象内部的缓冲区。
- FSDataOutputStream对象通过socket连接,将打好的包通过特定算法,一个一个传输到一组DataNode中的其中一个。默认三个为一组。
- 这个DataNode通过pipeline将包传输给其他DataNode,传输成功,则反向返回ack响应,由第一个DataNode发送ack响应给客户端。
- 客户端调用FSDataOutputStream对象close方法,关闭输出流。
- 客户端调用Distributed File System对象的complate方法,通知NameNode文件写入成功。
二、读出
- 初始化FileSystem,利用 open() 函数打开文件。
- FileSystem返回FSDataInputStream给客户端,客户端利用FSDataInputStream通过RPC连接NameNode获取数据存放路径。
- FSDataInputStream读取存放数据的第一个数据块的最近节点。
- 读取完一个数据块后,关闭与这个数据节点的连接,继续连接存放下一个数据块的最近的节点。
- 读取完数据后,调用close方法,关闭流。
- 如果读取数据时发生异常,就尝试连接存放该数据块的下一个节点。
- 读取数据失败的节点会被标记,下一次不会再次连接。
三、如何保证数据一致性
通过校验和,每一个chunk都有一个校验位,多个chunk构成一个package,多个package构成一个block,所以可以通过计算校验和来判断。
HDFS在存储数据的时候,对于每个分块的数据,都会对其计算一个校验和,作为隐藏文件保存在同名的HDFS命名空间下。当读取数据块之后,会对其重新计算校验和,并与之前存入时的校验和进行匹配,如果不同,就会从另一个存有该数据块的节点上读取数据。
参考文献:
HDFS读写流程(史上最精炼详细)