0%
Block的副本放置策略
- 第一个副本: 放置在上传文件的DataNode; 如果是集群外提交, 随机挑选一台 磁盘不太满, CPU不太忙的节点
- 第二个副本: 放置在跟第一个副本不同机架的节点上(容灾备份)
- 第三个副本: 尽量跟第二个副本相同机架(节约网络资源)
- 更多副本: 随机节点
HDFS读流程

- 首先调用FileSystem对象的open方法, 获取的是一个DistributedFileSystem的实例
- DistributedFileSystem通过RPC获得文件的第一批block的locations, 同一block按照重复数会返回多个locations, 这些locations按照hadoop拓扑结构排序, 距离客户端近的排在前面
- 前两步会返回一个FSDataInputStream对象, 该对象会封装成 DFSInputStream对象,DFSInputStream可以方便的管理DataNode和NameNode数据流. 客户端调用read方法, DFSInputStream就会找出离客户端最近的datanode并连接datanode.
- 数据从datanode源源不断的流向客户端
- 如果第一个block块的数据读完了, 就会关闭指向第一个block块的datanode连接, 接着读取下一个block块. 这些操作对客户端透明, 从客户端角度来看只是读一个持续不断的流
- 如果第一批block读完了, DFSInputStream就会去NameNode拿下一批blocks的location,继续读, 当所有block读完, 关闭所有流.
HDFS写流程

- 客户端通过调用DistributedFileSystem的create方法, 创建一个新的文件
- DistributedFileSystem通过RPC调用NameNode,去创建一个没有blocks关联的新文件. 创建前, NameNode会做各种校验, 比如文件是否存在, 客户端有无权限去创建等. 如果通过, NameNode就会记录下新文件, 否则就会抛出IO异常.
- 前两步结束后返回FSDataOutputStream的对象, 和读文件等时候相似, FSDataOutputStream被封装成DFSOutputStream.客户端开始写数据到DFSOutputStream, DFSOutputStream会把数据切成一个个小packet, 然后排成队列data queue.
- DataStreamer会去处理接受data queue, DataStreamer把packet按队列输出到管道的第一个DataNode中, 第一个DataNode又把packet输出到第二个DataNode中, 以此类推.
- DFSOutputStream还有一个队列叫 ack queue, 也是由packet组成, 等待DataNode的收到响应, 当pipeline中的所有DataNode都表示已经收到的时候, 这时ack queue才会把对应的packet包移除
- 客户端完成写数据后, 调用close方法关闭写入流
- DataStreamer把剩余的包都刷到pipeline里,然后等待ack消息, 收到最后一个ack后, 通知DataNode把文件标记为已完成.
- 一个重要的参数: dfs.client.block.write.replace-datanode-on-failure.min-replication
HDFS文件权限
- 与Linux文件权限类似
- r
- w
- x 权限x对于文件忽略, 对于文件夹表示是否允许访问其内容
- 如果Linux用户lxm使用hadoop命令创建一个文件, 那么这个文件在HDFS中owner就是 lxm
- HDFS权限的目的: 阻止好人做错事, 而不是阻止坏人做坏事. HDFS相信, 你告诉我你是谁, 我就认为你是谁.
HDFS安全模式
- NameNode启动的时候, 首先将fsimage载入内存, 并执行edits中的各项操作
- 一旦在内存中成功建立文件系统元数据的映射, 则创建一个新的fsimage文件(无需SecondaryNameNode)和一个空的编辑日志(即improgress edits log)
- 此刻namenode运行在安全模式. 即 namenode的文件系统对于客户端是只读的
- 在此阶段,NameNode会收集各个DataNode的报告, 当数据块达到最小副本数(dfs.namenode.safemode.replication.min)以上时, 会被认为是“安全”的, 在一定比例(dfs.namenode.safemode.threshold-pct)的数据块被确定为“安全”后,安全模式结束
- 当检测到副本数不足的数据块时, 该块会被复制直到达到最小副本数, 系统中数据块的位置并不是NameNode维护的, 而是以块列表形式存储在DataNode中