master ===> nameNode
slave ===> dataNode
文件是按照 blocksize 分 block(块)后存在不同的 dataNode 上的
nameNode 的工作:
1. 维护目录树
2. 管理元数据(metadata,文件对应所有 block 的 id,dataNode,副本数)
3. 响应客户端请求
dataNode 的工作:
1. 存储和管理 block 数据
2. 定时(3600s)向 nameNode 汇报自身保存的 block 信息
客户端上传文件:
1. 客户端向 nameNode 发消息要上传文件
2. nameNode 查询目录树后决定是否允许上传,并把结果告诉给客户端
3. 如果允许上传,客户端在本地文件按照 blocksize 进行切片
4. 客户端向 nameNode 请求上传第 1 个 block
5. nameNode 返回副本数量个可用的 dataNode 给客户端(dn1,dn2,dn3)
6. 客户端依次连接 dataNode 确定通信畅通
7. 确定通信畅通后客户端开始发送 block1 的数据,以 package(64k) 为单位进行发送
8. 客户端先把 package 发送给 dn1
9. dn1 收到第一份 package 后,先保存一下,然后开启一个管道连接到 dn2,然后把 package 发送给 dn2
10. dn2 收到第一份 package 后,先保存一下,然后开启一个管道连接到 dn3,然后把 package 发送给 dn3,这个管道通常 称为 pipline
11. 后续的每一个 package 都从 dn1 顺着管道到达 dn2 和 dn3
12. 客户端发送完第 block1 后向 nameNode 进行汇报
13. dn1,dn2 和 dn3 在接收完毕 block1 后也会向 nameNode 进行汇报
14. nameNode 收到所有的汇报后通知客户端 block1 上传成功
15. 如果客户端还有 block 需要上传就重复 4-15 步,直到所有 block 全部上传
副本规则:默认是 3 个
dn1:
1. 如果客户端是在某个 dataNode 上,那么就选取这个 dataNode
可以避免一次网络传输数据,提高上传速度
2. 否则通过负载均衡的策略,选取一个可用的
dn2:通过机架感知,选取不和 dn1 在同一个机架上的 dataNode
dn3:和 dn2 同一个机架的不同 dataNode
更多的:随机分配
副本数是由客户端上传文件的时候决定的
咱们在 hdfs-site.xml 中配置了副本数为 2,所有使用 hadoop fs -put 上传的文件副本数是 2
通过 eclipse 上文件的时候,没有配置副本数,就采用默认值 3,所以上传的文件副本数是 3
eclipse 通过 conf.set("dfs.replication", "5"); 设置副本数
客户端下载文件:
1. 客户端向 nameNode 发送下载文件的请求
2. nameNode 先查目录树,然后查元数据池为文件的每一个 block 找出 1 个 dataNode
3. nameNode 把找到的 dateNode 按照 block 顺序发送给客户端
4. 客户端连接第 1 个 dataNode 读取 block 数据
5. 客户端继续读取第 2 个 dataNode 的 block 数据
6. 依次类推,直到全部读取完毕,客户端拼接 block 生成文件
客户端和服务器的通信是通过 rpc 完成的
rpc:远程过程调用协议,可以在一个程序内调用另外一个程序的方法
SecondaryNameNode 是 nameNode 的冷备份
在 nameNode 挂了以后,可以从 SecondaryNameNode 中进行几乎全部数据的恢复
nameNode 管理的元数据需要频繁的读取或者修改,放在内存比较合适
为了防止数据丢失还需要再硬盘上保存一份,分为两部分:
fsimage:hdfs 启动的时候的元数据信息
edits:操作记录
每次对元数据的修改,只会增加 edits 不会修改 fsimage
一旦 nameNode 挂了,下次重启的时候可以对 fsimage 执行 edits 的操作进行还原
假设 hdfs 运行了一年后,关了,下次启动就把一年的 edits 都执行一边,耗时很长,为了避免这种情况,hdfs 会定期合并 fsimage 和 edits。
合并条件:
1. 3600s
2. edits 达到 100w
只要达到任何一个条件就进行合并,合并后重置所有条件
合并操作:checkpoint
SecondaryNameNode 负责合并操作
1. SecondaryNameNode 以 60s 的间隔询问 nameNode 是否要合并
2. nameNode 上运行着一个 http 服务器
3. 当 nameNode 告诉 SecondaryNameNode 需要合并文件的时候,SecondaryNameNode 会从 http 服务器上下载 fsimage 和 edits
3. 开始下载的时候 nameNode 会生成一个新的 edits 文件叫做 edits.new 用来记录在合并的这段时间内对元数据进行的操作
4. SecondaryNameNode 对 fsimage 进行 edits 的操作生成新的 fsimage 叫做 fsimage.ckpt
5. SecondaryNameNode 通过 POST 请求把 fsimage.ckpt 上传到 nameNode
6. nameNode 把 fsimage.ckpt 重命名为 fsimage,edits.new 重命为 edits
7. SecondaryNameNode 在下次合并前不会删除下载的 fsimage 和 edits
8. 如果 nameNode 中的 fsimage 和 edits 丢失了,可以尝试从 SecondaryNameNode 中复制 fsimage.ckpt 进行恢复
9. nameNode 重启后会合并 fsimage 和 edits 生成最新的 fsimage
nameNode 的数据保存在 hdfs/name/current
SecondaryNameNode 的数据保存在 tmp/dfs/namesecondary/current
从 SecondaryNameNode 恢复 nameNode 的时候需要把 name 文件夹删除,然后重新创建,再把
namesecondary 下的所有内容拷贝到 name 文件夹,然后重启集群即可