写在前面: 不考虑HA和Federation架构,如果本文有错误的地方还望大佬指出,小弟不胜感激.
1.客户端通过shell命令的方式传输文件到HDFS上(申请上传)

hdfs dfs -put a.txt /tmp
#如果添加了-f就会覆盖掉hdfs上/tmp/a.txt文件

2.namenode检查文件夹是否存在,检查文件是否存在,如果文件夹不存在是肯定不能上传的,如果文件存在就要看有没有覆盖写入了

3.返回允许上传通知

1-3步图片

formatZK流程 hadoop hadoop写流程图_hadoop

4.判断文件的大小,然后切割文件,默认按照128m去切割(hadoop2.x)按照64m去切割(hadoop1.x)


最小化寻址开销,如果太小,namenode的压力就会比较大,如果太大,datanode在计算的时候压力就会比较大,一般我们都会手动设置这个大小.

5.通知namenode上传第一个block块

6.namenode通过副本机制得到block块应该放在哪些datanode节点上的地址列表


假设3个副本,如果文件在datanode的节点上,第一个副本应该在客户端所在的datanode节点上,也就是本地,这样可以避免网络传输,如果文件不是在datanode的节点上,应该是随机发送到一个datanode上的.

第二个副本应该是放在第一个副本的不同机架上,设计思想:容灾


第三个副本应该是放在和第二个相同的机架上,设计思想:避免网络传输造成不要开销


7.返回这些地址给client端

4-7步图片

formatZK流程 hadoop hadoop写流程图_上传_02

8.client端和一个datanode建立连接,我们设为A,然后A又和另外一个datanode建立连接,我们设为B,然后B又和另外一个datanode建立连接,我们设为C,这里其实是建立的一个远程RPC调用


  1. 简单:RPC 概念的语义十分清晰和简单,这样建立分布式计算就更容易。
  2. 高效:过程调用看起来十分简单而且高效。
  3. 通用:在单机计算中过程往往是不同算法部分间最重要的通信机制。

9.将块再次分成packet(64kb)发送给A节点,每个节点会将packet重组成block块


如果是在A上传完后组成block再去拷贝到B这样显然效率就很低了,应该是当ABC都上传完后再组成block块.

10.A节点会发送给B节点,B节点会发送给C节点

11.C节点会返回给B节点一个ack确认码,B节点会返回A节点一个ack确认码,A节点会返回client端一个确认码


如果B节点宕机了,C节点应该也接收不到packet了,这时会将已经写入的数据放置queue的顶部,并将挂掉的datanode移除pipeline,在写入结束后namenode会收集datanode副本的数量,发现没有达到要求,寻找一个新的datanode保存副本。 持续思考: 按道理C讲节点应该能收到消息啊?那副本复制应该成功才对,那具体是怎么做的呢?是通过client去管理这三个节点的元数据吗?这个问题不大清楚

12.通知上传第二个block块后续步骤同5-11步骤

总的流程图:

formatZK流程 hadoop hadoop写流程图_formatZK流程 hadoop_03