hdfs有两种角色 NameNode,DataNode
1. HDFS架构
NameNode
- 主要负责管理元数据
- 维护hdfs的目录树
- 响应客户端的请求
DataNode 主要存数据块
- Secondary NameNode
2. 文件存储
1. client 向 NameNode 申请上传文件
2. NameNode根据文件大小向 client 分配的 DataNode 1,2
3. client 根据文件的大小和DataNode的块大小 切分为block1,block2, 并且分别写入 DataNode1,2
4. client 向 DataNode 写完数据之后 通知 NameNode, NameNode更新元数据
5. NameNode 根据配置的副本数量控制DataNode进行拷贝
其中 NameNode 记录Block存储在各个DataNode的位置信息 我们称之为元数据
其中block不要设置的太小,会极大消耗NameNode有限的空间
3. NameNode元数据管理
为了快速读取元数据,获取各个block的位置。NameNode是放在内存中,并且磁盘上有备份。
edits:本地文件,不能修改,只能追加 几十兆
fsimage: 磁盘文件
1. 客户端上传文件时,NameNode首先向edits log文件中记录元数据操作日志
2. 客户端上传文件之后, 返回信息返回成功信息给 NameNode, NameNode就在内存中写入这次上传操作新产生的元数据信息
3. 当edits log写满时,需要将一段时间的新的元数据刷新到fsimage中去
4. NameNode 通知 Secondary NameNode 进行checkpoint操作 合并操作
5. 停止往edits文件中写数据, 新的数据写入 edits.new 中
6. Secondary NameNode 下载 NameNode 的fsiamge和edits到本地,合并生成fsimage.checkpoint文件
7. Secondary NameNode把 fsimage.checkpoint 上传到NameNode
8. 把fsimage删掉,重命名fsiamge.checkpoint,把edits 删掉,重命名edits.new
元数据格式
NameNode(FileName, replicas, block-ids,id2host...)
/test/a.log,3,{blk_1,blk_2},[{blk_1:[h0,h1,h3]},{blk_2:[h0,h2,h4]}]
含义
文件路径 /test/a.log 副本数量 3
分割后的block blk_1, blk_2
blk_1的3个副本分别在 h0,h1,h3 这三个DataNode上
blk_2的3个副本分别在 h0,h2,h4 这三个DataNode上
checkpoint 相关配置参数
文件:hdfs-site.xml
fs.checkpoint.period 指定两次checkpoint的最大时间间隔,默认3600秒
fs.checkpoint.size 规定edits文件的最大值,一旦超过这个值则强制checkpoint,不管是否到达最大时间间隔。默认64M
4. DataNode 工作原理
- 提供真实文件数据的存储服务
- 文件块(block): 最基本的存储单位。 dfs.block.size
对于文件内容而言,一个文件的长度是size,从文件的0偏移开始,按照固定的大小,顺序对文件进行划分并编号,划分好的每一个块成为一个Block。
HDFS默认Block大小是128M。以一个256M文件,共有256/128=2个Block - 不同于普通文件系统的是,HDFS中,如果一个文件小于一个数据块的大小,并不占用整个数据块的存储空间
- Replication。 多副本。默认三个 dfs.replication
5. HDFS JAVA 客户端编写
首先导入hadoop的 hdfs 和common这两个包
然后把 core-site.xml 和 hdfs-site.xml 两个配置文件 拷贝到当前目前目录
下面代码是从hdfs下载一个文件
package cn.itcast.hadoop.hdfs;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
public class HdfsUtil {
public static void main(String[]args) throws IOException {
Configuration conf = new Configuration(); //创建一个配置,从当前文件读配置 代码里设置的优先级高
FileSystem fs = FileSystem.get(conf);
Path src = new Path("hdfs://hadoop1:9000/jdk-8u161-linux-x64.tar.gz"); //hadoop的文件地址
FSDataInputStream in = fs.open(src);
FileOutputStream os = new FileOutputStream("/home/hadoop/jdk-8u161-linux-x64.tar.gz"); // 本地文件位置
IOUtils.copy(in, os); 拷贝下来
}
}
- 如果是在远程登录 hadoop的话 需要设置一下 jvm中的hadoop用户