hadoop包含hdfs和MapReduce,hdfs负责数据文件存储,是hadoop的基础,MapReduce是对数据的处理和计算。
HDFS(Hadoop Distributed File System)即分布式文件系统,包含四大部分:client、NameNode、DataNode、Secondary NameNode。

- DataNode:实际的数据存放节点,通过心跳与NameNode保持连接;执行数据的读写操作。
- NameNode:维护DataNode元数据,维护数据块与DataNode的路由信息,以供client查询。
- client:访问NameNode获取数据块路由信息,执行读写操作;通过命令更新文件系统等。
- Secondary NameNode:不是NameNode的副本;为NameNode提供辅助功能。
- 其架构和多数分布式系统架构相似,譬如kafka,同一的集群元数管理NameNode对比zookeeper,数据文件实际存放的DataNode对应broker,client对应consumer、producer。
特点:
- 适合大数据存储、处理
- 分布式部署,高可用性
- 适合流程读取
- 适合大批量低端机器部署
不足:
- 不适合线上业务,访问延迟较高
- 不能修改,不适合小文件储存
文件读取:
- 客户端首先通过rpc调用,从NameNode获取第一批block文件的的DataNode信息,block对应的DataNode有多个,按照由近到远的顺序排序。
- 读取时,优先读取距离近的DataNode。
- 读完一个block后,关闭其连接;重复以上动作,读取后续block,直到读取完成,关注读取流。
文件写入:
- 客户端首先通过接口发起创建文件请求,hdfs会校验文件是否存在,用户是否有权限等,文件创建成功后,返回给客户端一个输出流DFSOutputStream。
- DFSOutputStream将写入数据分成小的packet,写入队列发送,交给DataStreamer发送。
- DataStreamer发送请求给NameNode,查询距离最近的DataNode写入。
- 最近NameNode接受数据后又将数据写入第二个NameNode,直到全部写入完成,最后关闭写入流。
读写实例:
- 文件读取
public class HadoopMain {
public static void main(String[] args) throws Exception {
readText();
}
private static void readText() throws Exception {
// 指定hadoop HOME目录
System.setProperty("hadoop.home.dir", "/");
Configuration conf = new Configuration();
// 访问的hadoop地址
conf.set("fs.defaultFS", "hdfs://localhost:9000/");
// 读取的文件路径
Path path = new Path("/flume/test/test1.log");
FileSystem fs = path.getFileSystem(conf);
FSDataInputStream input = fs.open(path);
int i = 0;
try {
// 按行读取文件内容
String line = input.readLine();
while (line != null) {
i++;
System.out.println(line);
line = input.readLine();
}
System.out.println("line: " + i);
} finally {
IOUtils.closeStream(input);
}
}
}
- 文件写入
public class HadoopMain {
public static void main(String[] args) throws Exception {
write();
}
private static write() {
// 待写文件
String inPath = "./test.txt";//本地路径
// 写入hdfs位置
String outPath = "hdfs://localhost:9000/test/test2.txt";//hdfs的路径
InputStream in = new BufferedInputStream(new FileInputStream(inPath));
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create(outPath), conf);
// 创建文件
FSDataOutputStream out = fs.create(new Path(outPath), new Progressable() {
@Override
public void progress() {
System.out.print("ok");
}
});
IOUtils.copyBytes(in, out, 1024, true);
}
}
参考:
https://blog.csdn.net/wypersist/article/details/79757242
https://www.jianshu.com/p/f1e785fffd4d
网友评论