5.大数据学习之旅——hadoop-HDFS

版权声明:版权归零零天所有 https://blog.csdn.net/qq_39188039/article/details/86223419

NameNode

查看edits文件:
hdfs oev -i edits_0000000000000000022-0000000000000000023 -o edits.xml
查看fsimage文件:
hdfs oiv -i fsimage_0000000000000000024 -o fsimage.xml -p XML
fsimage_0000000000000000023.md5 — 用于校验的
VERSION
Namenode:clusterID=CID-e7c4b16d-dc36-4cca-ac67-3d28aac9dfeb
Datanode:clusterID=CID-e7c4b16d-dc36-4cca-ac67-3d28aac9dfeb — 用于进
行标记的。

SecondaryNameNode

在这里插入图片描述

合并过程

  1. 将edits和fsimage文件通过网络拷贝到Secondarynamenode上
  2. 在namenode产生一个edits.new记录合并期间的操作
  3. 拷贝完成之后,fsimage就会将其中的数据存到secondarynamenode的内
    存中
  4. 将edits的操作更新到secondarynamenode的内存中
  5. 更新完成之后,将内存中的数据写到fsimage.ckpt文件中
  6. 通过网络将fsimage.ckpt拷贝到namenode中
  7. 将fsimage.ckpt重命名为fsimage,并且将edits.new也重命名为edits
    合并过程
    SecondaryNameNode只负责进行数据的合并,不是Namenode的热备,但是
    也能起到一定的备份作用,会产生数据的丢失

Datanode

存储数据,并且是以数据块的形式来存储。
datanode存储namenode对应的clusterID以确定当前的datanode归哪一个
namenode管理
datanode每隔一段时间(3s)会主动向namenode发送心跳信息(节点状态,节
点数据)
如果namenode超过了10min没有收到datanode的心跳,则认为这个datanode
产生lost,那么namenode就会将这个datanode上的数据copy到其他节点上

HDFS的操作流程

读取数据

  1. 客户端发起RPC请求访问Namenode
  2. namenode会查询元数据,找到这个文件的存储位置对应的数据块的信
    息。
  3. namenode将文件对应的数据块的节点地址的全部或者部分放入一个队列
    中然后返回
  4. client收到这个数据块对应的节点地址
  5. client会从队列中取出第一个数据块对应的节点地址,会从这些节点地址
    中选择一个最近的节点进行读取
  6. 将Block读取之后,对Block进行checksum的验证,如果验证失败,说明数
    据块产生损坏,那么client会向namenode发送信息说明该节点上的数据
    块损坏,然后从其他节点中再次读取这个数据块
  7. 验证成功,则从队列中取出下一个Block的地址,然后继续读取
  8. 当把这一次的文件块全部读完之后,client会向namenode要下一批block
    的地址
  9. 当把文件全部读取完成之后,从client会向namenode发送一个读取完毕
    的信号,namenode就会关闭对应的文件
    在这里插入图片描述

写流程

  1. client发送RPC请求给namenode
  2. namenode接收到请求之后,对请求进行验证,例如这个请求中的文件是
    否存在,再例如权限验证
  3. 如果验证通过,namenode确定文件的大小以及分块的数量,确定对应的
    节点(会去找磁盘空间相对空闲的节点来使用),将节点地址放入队列
    中返回
  4. 客户端收到地址之后,从队列中依次取出节点地址,然后数据块依次放
    入对应的节点地址上
  5. 客户端在写完之后就会向namenode发送写完数据的信号,namenode会
    给客户端返回一个关闭文件的信号
  6. datanode之间将会通过管道进行自动的备份,保证复本数量
    在这里插入图片描述

删除流程

  1. Client发起RPC请求到namenode
  2. namenode收到请求之后,会将这个操作记录到edits中,然后将数据从内
    存中删掉,给客户端返回一个删除成功的信号
  3. 客户端收到信号之后认为数据已经删除,实际上数据依然存在datanode上
  4. 当datanode向namenode发送心跳消息(节点状态,节点数据)的时候,
    namenode就会检查这个datanode中的节点数据,发现datanode中的节点
    数据在namenode中的元数据中没有记录,namenode就会做出响应,就
    会命令对应的datanode删除指定的数据

hdfs的操作指令

hadoop fs -put a.txt /a.txt - 上传文件
hadoop fs -mkdir /hadoopnode01 - 创建目录
hadoop fs -rm /hadoop-2.7.1_64bit.tar.gz - 删除文件
hadoop fs -rmdir /hadoopnode01 - 删除目录
hadoop fs -rmr /a - 递归删除
hadoop fs -get /a.txt /home - 下载
hadoop fs -ls / - 查看
hadoop fs -lsr / - 递归查看
hadoop fs -cat /a.txt - 查看内容
hadoop fs -tail /a.txt - 产看文件的最后1000个字节
hadoop fs -mv /a/a.txt /a/b.txt - 移动或者重命名
hadoop fs -touchz /demo.txt - 创建空文件
hadoop fs -getmerge /a demo.txt - 合并下载

Hadoop插件的使用:

  1. 将hadoopbin_for_hadoop2.7.1.zip解压

  2. 复制hadoop-eclipse-plugin-2.7.1.jar 2.

  3. 找到eclipse的安装目录,将插件复制到eclipse安装目录下的子目录plugins

  4. 重启eclipse

  5. 在eclipse中指定hadoop的安装目录
    在这里插入图片描述

  6. Window -show view
    在这里插入图片描述

  7. 需要添加环境变量:HADOOP_USER_NAME=用户名

HDFS的API操作

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.junit.Test;

public class HDFSDemo {

	@Test
	public void get() throws IOException, URISyntaxException {

		// 创建连接
		// uri - 连接地址
		// conf - 配置
		Configuration conf = new Configuration();
		FileSystem fs = FileSystem.get(new URI("hdfs://192.168.60.132:9000"), conf);

		// 获取读取文件的流
		InputStream in = fs.open(new Path("/a/a.txt"));

		FileOutputStream out = new FileOutputStream("a.txt");

		// 读取数据
		byte[] bs = new byte[1024];
		int len = -1;
		while ((len = in.read(bs)) != -1) {
			out.write(bs, 0, len);
		}

		out.close();
	}

	@Test
	public void put() throws IOException, URISyntaxException, InterruptedException {

		// 创建连接
		Configuration conf = new Configuration();
		FileSystem fs = FileSystem.get(new URI("hdfs://192.168.60.132:9000"), conf, "root");

		OutputStream out = fs.create(new Path("/a/c.txt"));

		FileInputStream in = new FileInputStream("c.txt");

		// byte[] bs = new byte[1024];
		// int len = -1;
		// while ((len = in.read(bs)) != -1) {
		// out.write(bs, 0, len);
		// }
		//
		// in.close();
		IOUtils.copyBytes(in, out, conf);
	}

}

MapReduce


概述:

是hadoop中的分布式的计算框架
MapReduce意味着在计算过程中实际分为两大步:Map过程和Reduce过
程。
在这里插入图片描述
案例:统计文件中每一个单词出现的次数
WordCountMapper

import java.io.IOException;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

// 案例:统计每一个单词出现的次数
// KEYIN - 这一行的偏移量 --- 
// VALUEIN - 读取到这一行的数据
// KEYOUT - 输出的键的类型 --- 这一行中的每一个单词
// VALUEOUT - 输出的值的类型 --- 表示这一行中这个单词出现的次数
public class WordCountMapper extends Mapper<LongWritable, Text, Text, LongWritable >{

	@Override
	// key -- 这一行的偏移量
	// value --- 这一行的数据
	protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, LongWritable>.Context context)
			throws IOException, InterruptedException {
		
		System.err.println(value);
		// 获取到一行数据
		String str = value.toString();
		// 以空格为单位进行切分
		String[] arr = str.split(" ");
		
		for (String s : arr) {
			context.write(new Text(s), new LongWritable(1));
		}
	}
	
}

WordCountReducer

import java.io.IOException;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

// 案例:统计每一个单词出现的次数
// KEYIN --- 单词
// VALUEIN --- 次数
// KEYOUT --- 单词
// VALUEOUT
public class WordCountReducer extends Reducer<Text, LongWritable, Text, LongWritable > {
	
	@Override
	protected void reduce(Text key, Iterable<LongWritable> arg1,
			Reducer<Text, LongWritable, Text, LongWritable>.Context context) throws IOException, InterruptedException {
	
		long sum = 0;
		// 计算总的次数
		for (LongWritable count : arg1) {
			sum += count.get();
		}
		
		// 将单词以及对应的总次数写出
		context.write(key, new LongWritable(sum));
		
	}

}

WorldCountDriver

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class WorldCountDriver {
	
	public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
		
		Configuration conf = new Configuration();
		Job job = Job.getInstance(conf);
		
		// 需要给当前的job指定执行的入口类
		job.setJarByClass(WorldCountDriver.class);
		
		// 指定要执行的mapper
		job.setMapperClass(WordCountMapper.class);
		
		// 指定mapper执行完成之后的结果类型
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(LongWritable.class);
		
		// 指定要执行的reducer
		job.setReducerClass(WordCountReducer.class);
		
		// 指定reducer执行完成之后的结果类型
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(LongWritable.class);
		
		// 指定读取的文件
		FileInputFormat.setInputPaths(job, new Path("hdfs://192.168.60.132:9000/mr/words.txt"));
		// 指定写出的路径
		FileOutputFormat.setOutputPath(job, new Path("hdfs://192.168.60.132:9000/result"));
		
		job.waitForCompletion(true);
	}

}

上一篇 5.大数据学习之旅——hadoop-简介及伪分布式安装

猜你喜欢

转载自blog.csdn.net/qq_39188039/article/details/86223419
今日推荐