(Hadoop操作与应用)S3HDFS

HDFS的介绍

HDFS演变

  1. 源于谷歌GFS论文

在这里插入图片描述

DataNode(服务器A)存储文件的分割信息,文件和目录信息。DataNode(服务器B。C。D)存储分布式文件,并且备份在不同的服务器上。

HDFS基本概念

概念

是一个易于扩展分布式文件存储系统,运行在成百上千台低成本的机器上。用于海量文件信息进行存储和管理。解决TB,PB的存储问题

  1. NameNode(名称节点/主节点)
    是hdfs集群的主节点,NameNode关闭就无法访问Hadoop集群。用来存储元数据(大小、文件名称、文件权限、切分次数(block)、block的存储位置)
  2. DataNode(数据节点)
    从节点,用来存切分后的数据(提供磁盘空间)
  3. block(数据块)
    文件的每个切片成为一个block,hadoop2.x默认128M大小,可以修改。
  4. Rack(机架)
    (放服务器的机柜)
    用来存放部署Hadoop集群服务器的机架,不同机架的节点通过交换机通讯。hdfs通过机架感知策略,使NameNode确定每个DataNode所属机架id,使用副本存放策略,来改进数据的可靠性、可用性和网络带宽的利用率
  5. metadata(元数据)
    三种形式:
    1. 维护HDFS文件系统中文件和目录的信息,如,文件名、目录名、父目录信息、文件大小、修改时间、创建时间等。
    2. 记录文件内容存储的相关信息,如,文件分块情况、副本个数、每个副本所在的DataNode信息。
    3. 记录HDFS中所有的DataNode信息,用于DataNode管理。

HDFS特点

优点

  1. 高容错:数据自动保存多个副本。它通过增加副本的形式,提高容错性。
  2. 流式数据访问:一次写入,多次读取。文件一旦写入不能修改,只能追加。它能保证数据的一致性。
  3. 支持超大文件:将大文件切分成小文件
  4. 高数据吞吐量:不支持随机修改,只支持追加修改

缺点

  1. 高延迟:数据多,需要切片,需要做副本
  2. 不适合小文件存取:一个文件就占150字节,会增加namenode压力
  3. 不适合并发写入

HDFS结构和原理

HDFS存储架构

  • 采用主从架构(Master/Slave架构)
  • HDFS集群是由一个NameNode和多个DataNode组成
  1. NameNode:存储元数据在内存中,fsimage和edits用来将元数据持久化(将内存中的元数据放到磁盘中)fsimage放到磁盘,edits从磁盘中取出到内存。
  2. DataNode每隔一段时间向NameNode发送心跳包来证明我还活着,若没有收到心跳包,NameNode认为DataNode宕机了就会检查副本文件完整性。集群继续正常工作。

HDFS文件读写原理

  • HDFS写数据
    1. 客户端发出rpc,请求上传文件
    2. NN检查元数据的目录树(检查文件是否存在,存在不上传,不存在返回数据可以上传)
    3. NN告诉客户端可以上传
    4. 请求上传第一个block
    5. NN检查DN信息池(存储量),找出可用的DN。
    6. NN返回可用DN列表。
    7. 客户端和DN之间建立管道(Pipeline),各个DN之间都建立Pipeline。
    8. DN返回管道建立完毕信息
    9. 客户端和DN之间建立数据流开始发送数据
    10. 客户端以package(64k)为单位发送数据 ,DN之间也以package(64k)为单位发送数据。(没发送一次,DN之间也会互相发送)
    11. DN向前返回ACK确认信息(收到了)
    12. 通知客户端block发送完毕,请求发送下一个block,向上循环直到全部block发送完毕。
  • HDFS读数据
    1. 客户端向NN发送RPC请求,获取文件每个block数据所在位置
    2. DN返回每个block的DN地址列表
    3. 客户端收到地址列表后,挑出排序靠前(离DN进的)

HDFS的Shell操作

hadoop fs <args>:可以操作任何人间系统如,本地文件系统,HDFS等
hadoop dfs <args>主要针对HDFS已被hdfs dfs代替
hdfs dfs <args>

参数名称功能
-ls查看指定目录结构
-du统计目录下所有文件大小
-mv移动
-cp复制
-put上传文件
-cat查看文件内容
-text将文件输出为文本格式
-mkdir创建文件夹
-help帮助

ls

hadoop fs -ls [-d] [-h] [-R] <args>
参数说明
[-d]将目录显示为普通文件
[-h]人类可读的显示方式
[-R]递归显示目录树
[root@hadoop01 ~]# hadoop fs -ls -R /

在这里插入图片描述

mkdir命令

hadoop fs -mkdir [-p] <路径>
参数说明
[-p]递归创建

put命令

hadoop fs -put [-f] [-p] <要上传的文件的路径> <上传位置>
参数说明
[-f]覆盖目标文件
[-p]保留访问和修改时间、权限

案例–Shell定时采集数据到HDFS

  • 在/export/data/logs下创建文件
# 配置环境变量
export JAVA_HOME=/usr/java/jdk1.8.0_212
export HADOOP_HOME=/opt/hadoop
PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
# 日志存放目录
log_src_dir=/export/data/logs/log/
# 待上传温江存放目录
log_toupload_dir=/export/data/logs/toupload/
# 设置日期
date1=`date -d last-day +%Y_%m_%d`
# 日志上传hdfs 的路径
hdfs_root_dir=/data/clickLog/$date1/
# 打印环境变量信息
echo "envs:hadoop_home:$HADOOP_HOME"
# 读取日志文件目录判断是否有上传的文件
echo "log_src_dir:"$log_src_dir

ls $log_src_dir | while read fileName
do
	if [[ "$fileName" == access.log.* ]];then
		date=`date +%Y_%m_%d_%H_%M_%S`
		# 将文件移动到待上传目录并改名
		echo "moving $log_src_dir$fileName to $log_toupload_dir"xxxxx_click_log_$fileName"$date"
		mv $log_src_dir$fileName $log_toupload_dir"xxxxx_click_log_$fileName"$date
		# 将上传的文件path写入一个列表文件willDoing
		echo $log_toupload_dir"xxxxx_click_log_$fileName"$date >> $log_toupload_dir"willDoing."$date
	fi
done
# 找到列表文件
ls $log_toupload_dir | grep will | grep -v "_COPY_" | grep -v "_DONE_" | while read line
do
	# 打印信息
	echo "toupload is in file:"$line
	# 将上传文将列表改名为willDoing_COPY_
	mv $log_toupload_dir$line $log_toupload_dir$line"_COPY_"
	# 读取列表文件中的内容(待上传文件的path)
	cat $log_toupload_dir$line"_COPY_" | while read line
	do 
		echo "puting.......$line to hdfs path..........$hdfs_root_dir"
		hadoop fs -mkdir -p $hdfs_root_dir
		hadoop fs -put $line $hdfs_root_dir
	done
	mv $log_toupload_dir$line"_COPY_" $log_toupload_dir$line"_DONE_"
done

定期执行:

0 0 * * * /shell/xxxxxx.sh
参数6个意义:分 时 。。。。执行xxxxx.sh

直接执行:

sh 程序名.sh

HDFS的Java API操作

下载winutils解压

在这里插入图片描述

添加hadoop的win环境变量

在这里插入图片描述
在这里插入图片描述

复制文件下的hadoop.dll到System32下

在这里插入图片描述

API概念

通过Windows的Java编程语句访问HDFS,对HDFS进行增删查改

API

API说明
org.apache.hadoop.fs.FileSystem表示文件系统是文件系统的基类,可以被分布式文件系统集成,有很对实现类 LocalFileSystem本地文件系统,DistributedFileSystem分布式文件系统,FtpFileSystemFTP文件系统
fs.FileStatus向客户展示系统中文件和目录的元数据,如包含文件大小、块大小、副本信息、修改时间
fs.FSDataInputStream文件输入流,用于读取Hadoop文件
fs.FSDataOutputStream文件输出流,用于写hadoop 文件
conf.Configuration访问配置项,默认在core-site-xml中,用户可以添加相应配置项
fs.Path表示Hadoop文件系统中的一个文件或者一个目录的路径

在Java操作HDFS中,首先要创建一个客户端实例,主要涉及一下类

类名说明
Configuration封装了客户端或者服务器的配置。每一个配置都是以键值对存在, Configuration 会自动加载core-site-xml的HDFS配置文件
FileSystem是一个文件系统的对象,可以对文件进行操作常用方法如下表

FileSystem中常用方法

方法名说明
copyFromLocalFile(Path src,Path dst)从本地磁盘复制文件到HDFS。src是本地文件目录+文件名,dst是HDFS的路径+重置文件名
copyToLocalFile(Path src , Path dst)从HDFS复制文件到本地磁盘。src是HDFS文件目录+文件名,dst是本地的下载路径
mkdirs(Path f)建立HDFS的子目录
rename(Path src, Path dst)重命名文件或者文件夹,前者是要修改文件或者文件夹,后者是目标文件名或者文件夹名
delete(Path f)删除指定文件

Hadoop API学习网址点击前往

API案例

搭建项目环境

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  1. 修改pom.xml文件
    在这里插入图片描述
    添加以下内容(保存后所需jar包会自动下载)
<dependencies>
	<dependency>
		<groupId>org.apache.hadoop</groupId>
		<artifactId>hadoop-common</artifactId>
		<version>2.6.4</version>
	</dependency>
	<dependency>
		<groupId>org.apache.hadoop</groupId>
		<artifactId>hadoop-hdfs</artifactId>
		<version>2.6.4</version>
	</dependency>
	<dependency>
		<groupId>org.apache.hadoop</groupId>
		<artifactId>hadoop-client</artifactId>
    	<version>2.6.4</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>RELEASE</version>
	</dependency>
</dependencies>

在src/main/java下创建包-类

在这里插入图片描述
在这里插入图片描述

编写代码

  1. 获取fs操作对象
public class HDFS_CRUD {
    FileSystem fs = null;       // 定义全局变量fs操作对象
    @Before         // 表示下面的@Test执行之前先执行这个
    public void init() throws IOException {
        // 创建配置参数构造对象Configuration
        Configuration conf = new Configuration();
        // 设置参数指定文件系统类型
        conf.set("fs.defaultFS", "hdfs://hadoop01:9000");
        // 设置客户端的访问身份,root身份访问
        System.setProperty("HADOOP_USER_NAME","root");
        // 获取客户端对象
        fs = FileSystem.get(conf);
    }
    .
    .
    .
    .
}
  1. 传送本地文件到HDFS
// 传送本地文件到HDFS
    @Test
    public void testAddFileToHdfs() throws IOException {
        // 创建本地路径Path对象
        Path src = new Path("G:\\test.txt");
        // 创建HDFS路径Path对象
        Path dst = new Path("/user/root/testFile");
        // 实现资源上传
        fs.copyFromLocalFile(src,dst);
        // 资源关闭
        fs.close();
    }
  1. 从HDFS下载文件到本地
@Test
    public void testDownloadFileToLocal() throws IOException {
        // 实现文件下载
        fs.copyToLocalFile(new Path("/user/root/testFile"),
                new Path("G:\\"));
        fs.close();
    }
  1. 创建删除重命名目录
@Test
    public void testMkdirAndDeleteAndRename() throws IOException {

        // 创建目录
//        fs.mkdirs(new Path("/a/b/c"));
//        fs.mkdirs(new Path("/a1/b1/c1"));

        // 重命名目录
//        fs.rename(new Path("/a"),new Path("/a3"));

        // 删除文件夹,如果文件夹非空,删除时第二个参数必须为ture
        fs.delete(new Path("/a1"),true);
    }
  1. 查看目录信息(只显示文件)
    @Test
    public void testListFiles() throws IOException {
        // 获取迭代器对象true:递归获取
        RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/user/root"), true);
        // 变量迭代器
        while (listFiles.hasNext()){
            // 一个个获取listFiles中的内容
            LocatedFileStatus fileStatus = listFiles.next();
            // 打印当前文件名称
            System.out.println("文件名:"+fileStatus.getPath().getName());
            // 打印当前文件块大小
            System.out.println("文件块大小:"+fileStatus.getBlockSize());
            // 打印当前文件权限
            System.out.println("文件权限:"+fileStatus.getPermission());
            //打印当前文件内容长度
            System.out.println("文件内容长度:"+fileStatus.getLen());
            // 获取block块的信息(长度,DataNode信息)
            BlockLocation[] blockLocations = fileStatus.getBlockLocations();
            // 得到元数据的一个序列
            for (BlockLocation bl: blockLocations
                 ) {
                System.out.println("block-leng:"+ bl.getLength()+"----"+"block-offset:"+bl.getOffset());
                // 获取DataNode信息
                String[] hosts = bl.getHosts();
                // 得到文件在DataNode的序列
                for (String host:hosts
                     ) {
                    System.out.println(host);
                }
            }
            System.out.println("_________________________");
        }
    }

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值