上传

  1. 客户端向namenode发送文件上传的请求,即通过RPC与NameNode建立通讯。
  2. namenode进行一系列的检查(权限|父目录|文件是否已经存在)
  3. namenode检查通过,会向客户端响应
  4. 客户端会向namenode发送文件上传的真正的请求,这个请求中包含文件的长度。
  5. namenode会根据客户端发送的请求中的文件的长度,计算数据块的个数,并获取集群中的副本的配置信息,给客户端返回当前数据每一个数据块需要存放的节点.(NameNode与各DataNode使用心跳机制来获取DataNode信息。NameNode收到Client请求后,获取DataNode信息,并将可存储文件的节点信息返回给Client。)
    1
    2
    3
    hadoop.wmv  204m ,3个副本
    blk01:[hadoop01,hadoop03,hadoop04]
    blk02:[hadoop01,hadoop02,hadoop04]
  6. client收到NameNode返回的信息,与对应的DataNode节点取得联系,并向该节点写文件.
    1. 客户端开始准备文件上传.
    2. 客户端进行逻辑切块,仅仅是一个偏移量的范围划分
    3. 客户端开始准备上传第一个数据块,开启一个后台的阻塞进程,这个进程作用:等待数据块上传完成一个报告
    4. 构建第一个数据块的pipline
    5. 开始进行数据块上传
    6. 第一个数据块上传成功 关闭当前的pipline
    7. 开始上传第二个数据块 重复4,5,6
    8. 文件写入到DataNode后,以流水线的方式复制到其他DataNode(这里面也有DataNode向NameNode申请block)
  7. 所有的数据块上传成功 客户端给namenode反馈,namenode开始修改元数据信息

下载

文件下载相对来说就简单一些,Client要从DataNode上,读取 hadoop.wmv 文件。而hadoop.wmv 由block1和block2组成。

  1. 客户端向namenode发送文件下载的请求
  2. namenode会进行一系列的检查 如果检查通过 给客户端返回当前请求数据的块副本的存储位置
  3. 客户端开始下载第一个数据块 就近原则下载
  4. 下载会进行数据校验
  5. 第一个数据块下载及校验完成 开始下载第二个数据块
  6. 所有的数据块下载完成 给namenode反馈

元数据合并

有“写请求”到来时

  1. namenode会首先写editlog到磁盘,即向edits文件中写日志,成功返回后,才会修改内存,
  2. 向客户端返回hadoop会维护一个fsimage文件,也就是namenode中metedata的镜像.
  3. 但是fsimage不会随时与namenode内存中的metedata保持一致,而是每隔一段时间通过合并edits文件来更新内容
  4. 此时Secondary namenode就派上用场了,合并fsimage和edits文件并更新NameNode的metedata

元数据位置:

  • 内存:1.抽象目录树 2.数据和块的对应关系 3.数据块的存储位置

  • 硬盘:1 2 /02hadoop.wmv blk01:[] blk02:[]

    • 硬盘上元数据加载到内存中的时候 接受datanode的心跳的时候会将块的存储位置填上
      /02hadoop.wmv blk01:[hadoop01,hadoop03] blk02:[hadoop02,hadoop01]

元数据的目录结构:

  1. edits * 历史日志文件 一个小时滚动一次

    1
    2
    3
    4
    5
    6
    <property>
    <name>dfs.namenode.checkpoint.period</name>
    <value>3600</value>
    <description>The number of seconds between twoperiodic checkpoints.
    </description>
    </property>
  2. edits_inprogress 正在编辑的日志文件

  3. fsimage 元数据的镜像文件,存储某一时段NameNode内存元数据信息。

  4. seen_txid 合并点

    • fsimage_0000000000000000000 9:04
    • fsimage_0000000000000000017 10:04 最新合并的元数据文件
    • fsimage_0000000000000000078====fsimage_0000000000000000000+edits文件合并
  5. 合并完成之后 fsimage文件的命名:fsimage_0000000000000000078 以最后一个edits文件的id进行命名的命名完成之后 存在namenode的元数据中

  6. 为了避免元数据丢失,原来的镜像文件fsimage_0000000000000000000不会立即删除,下一个镜像文件合并完成的时候 前前一个镜像文件才会被删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@hadoop01 name]# pwd
/home/hadoop/hdfs/name
[root@hadoop01 name]# tree
.
├── current
│ ├── edits_0000000000000000001-0000000000000000017
│ ├── edits_inprogress_0000000000000000018
│ ├── fsimage_0000000000000000000
│ ├── fsimage_0000000000000000000.md5
│ ├── fsimage_0000000000000000017
│ ├── fsimage_0000000000000000017.md5
│ ├── seen_txid
│ └── VERSION
└── in_use.lock

1 directory, 9 files
[root@hadoop01 name]# cat current/seen_txid
18

NameNode中的元数据信息:

1
2
Namenode:	FileName,			replicas,		block-ids,	id2host ....
02hadoop.wmv, 2, {blk_1,blk-2},[{blk_1:[hadoop02,hadoop03]},{blk_2:[hadoop02,hadoop03]}]

02hadoop.wmv文件上传后,Namenode始终在内存中保存metedata,用于处理“读请求”。metedata主要存储了

  • 文件名称(FileName),
  • 副本数量(replicas),
  • 分多少block存储(block-ids),
  • 分别存储在哪个节点上(id2host)等。

元数据合并的过程

  1. secondarynamenode会向namenode发送元数据是否合并的检查 1min检查一次
  2. namenode需要元数据合并 会向sn进行响应
  3. secondarynamenode向namenode发送元数据合并的请求,通知namenode切换edits文件
  4. namenode将正在编辑的元数据的日志文件进行回滚 变成一个历史日志文件,同时会
    生成一个新的正在编辑的日志文件
  5. secondarynamenode通过http请求从将fsimage文件和edits文件拉取到secondarynamenode的本地
  6. secondarynamenode将上面的fsimage加载到内存中进行合并 根据edits的操作日志修改fsimage文件
  7. 合并完成,将合并完成的新的fsimage文件发送给namenode,重命名,生成最新的fsimage文件,secondarynamenode本地也会保存一个(下一次合并就不需要拉取 fsimage文件,只有第一次才会拉取 fsimage文件)
  8. namenode用新的fsimage替换旧的fsimage

画图说明

找了二张图片

上传

下载