HDFS的写流程 - FSDataOutputStream
- 上传一个文件到hdfs / 目录
[hadoop@hadoop614 hadoop-2.6.0-cdh5.7.0]$ hdfs dfs -put ./LICENSE.txt /
19/03/03 16:31:38 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
[hadoop@hadoop614 hadoop-2.6.0-cdh5.7.0]$ hdfs dfs -ls /
19/03/03 16:31:42 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Found 4 items
-rw-r--r-- 1 hadoop supergroup 17087 2019-03-03 16:31 /LICENSE.txt
drwx------ - hadoop supergroup 0 2019-03-02 13:13 /tmp
drwxr-xr-x - hadoop supergroup 0 2019-03-02 13:13 /user
drwxr-xr-x - hadoop supergroup 0 2019-03-02 20:31 /wordcount
但是我们只看到了文件已经上传的结果,但是中间到底经过了那些流程呢?
- Client端调用Distributed FileSystem.create(filePath)方法,与NN进行【RPC通讯】,check该路径是否存在,如果目录存在则检查是否有创建文件的权限;
如果有权限,则创建一个新的文件,但是不关联任何的block块,NN根据上传的文件大小且块大小和副本数,计算需要多少个块,以及块存放的额DN,最终将信息返回给客户端则为【FSDataOutputStream】。
如果有权限,则创建一个新的文件,但是不关联任何的block块,NN根据上传的文件大小且块大小和副本数,计算需要多少个块,以及块存放的DN;
最终将信息返回给客户端则为【FSDataOutputStream】。- Client调用FSDataOutputStream.write方法,将第一个块的
第一个副本写到第一个DN,写完写第二个副本,写完写第三个副本;
当第三个副本写完,返回给ack packet给第二个副本的DN,然后第二个DN返回ack packet给第一个DN;
第一个DN返回ack packet给FSDataOutputStream对象,标识第一个块,3副本写完!
然后依次写剩余的块!
(对操作者来说是透明的)- 当向文件写入数据完成后,Client调用FSDataOutputStream.close()方法。关闭输出流,flush换成区的数据包。
- 再调用Distributed FileSystem.complete(),通知NN节点写入成功。
HDFS的读流程 - FSDataInputStream
- 从hdfs下载一个文件到用户家目录
[hadoop@hadoop614 hadoop-2.6.0-cdh5.7.0]$ hdfs dfs -get /LICENSE.txt ~
19/03/03 16:49:51 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
[hadoop@hadoop614 hadoop-2.6.0-cdh5.7.0]$ ll ~
total 28
drwxrwxr-x 3 hadoop hadoop 4096 Feb 27 20:44 app
drwxrwxr-x 3 hadoop hadoop 4096 Mar 2 12:37 data
-rw-r--r-- 1 hadoop hadoop 17087 Mar 3 16:49 LICENSE.txt
[hadoop@hadoop614 hadoop-2.6.0-cdh5.7.0]$
同上传时一样,我们只看到了下载的结果,但是中间到底又经过了那些流程呢?
- Client通过FileSystem.open(filePath),
去与NN进行【RPC】通信,返回该文件的部分
或全部的block列表,也就是返回FSDataInputStream对象。- Client调用【FSDataInputStream】对象的read()方法,
a. 去与第一个块的最近的DN进行read,读取完后,会check,
假如success,会关闭与当前DN通信。假如fail 会记录失败的DN+block信息,下次就不会读取。
那么会去该块的第二个DN的地址读取。
b.然后去第二个块的最近的DN上读取,会check,success,会关闭与当前DN通信。
c.假如当前block列表全部读取完成,文件还没结束,那么FileSystem会从NN获取下一批的block列表。
(对于操作者,是透明的,感觉就是连续的数据流)- Client调用FSDataInputStream.close() 关闭输入流