10小时入门大数据:第3章-分布式文件系统

HDFS概述及设计目标

什么是HDFS

·        hadoop实现了一个分布式文件系统四个单词的简写HDFS

·        源于google的GFS

·        论文发表于2003年,是GFS克隆版

HDFS的设计目标

·        非常巨大的分布式文件系统

·        运行在普通廉价的硬件上

·        易扩展,为用户提供性能不错的文件存储服务

HDFS架构

·        1 Master(NameNode/NN) 带 N个Slaves(DataNode/DN)

HDFS/YARN/HBase

·        1个文件会被拆分成多个Block

·        blocksize:128M

·        130M ==> 2个Block: 128M 和 2M

·        NN(namenode):

1)负责客户端请求的响应

2)负责元数据(文件的名称、副本系数、Block存放的DN)的管理

·        DN(datanode):

1)存储用户的文件对应的数据块(Block)

2)要定期向NN发送心跳信息,汇报本身机器所有的block信息,健康状况

·        A typical deployment has a dedicated machine that runs only the NameNode software.

Each of the other machines in the cluster runs one instance of the DataNode software.

The architecture does not preclude running multiple DataNodes on the same machine

but in a real deployment that is rarely the case.

·        NameNode + N个DataNode

·        建议:NN和DN是部署在不同的节点上

HDFS副本机制(容错)

·        replication factor:副本系数、副本因子

·        All blocks in a file except the last block are the same size

HDFS副本存放策略

·        第一个存放在当前操作的机架上

·        第二个和第三个存放在第二个机架上的不同机器上

·        越多的话就随机分配机器了

·        生产上至少要有两个机架

JDK安装和ssh安装和ssh免密码登陆配置

Hadoop伪分布式安装步骤
JDK安装

·        使用版本:hadoop-2.6.0-cdh5.7.0
·        解压jdktar -zxvf jdk-7u79-linux-x64.tar.gz -C ~/app/
·        进入到解压的目录文件里边,使用pwd显示目录信息,拷贝这个信息配置环境变量
·        配置环境变量vim ~/.bash_profile
·      export JAVA_HOME=.../jdk.1.7.0_79
·      export PATH=$JAVA_HOME/bin:$PATH

·        配置生效source ~/.bash_profile
·        echo $JAVA_HOEM查看配置是否成功
·        java -version

安装SSH
 

·        yum install -y ssh
·        ssh-keygen -t rsa
·        拷贝公钥cp ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys
·        测试ssh localhost,ssh 机器名字

HDFS伪分布式环境搭建

   参考网页http://archive.cloudera.com/cdh5/cdh/5/hadoop-2.6.0-cdh5.7.0/hadoop-project-dist/hadoop-common/SingleCluster.html

http://archive.cloudera.com/cdh5/cdh/5/hadoop-2.6.0-cdh5.7.0.tar.gz
解压tar -zxvf hadoop-2.6.0-cdh5.7.0.tar.gz -C ~/app/
进入到解压的hadoop文件下
cd /etc
vim /hadoop-env.sh设置一下java的JAVA_HOME参数
vim /core-site.xml
# 修改一下机器名字和端口
		  <property>
            <name>fs.default.name</name>
            <value>hdfs://节点机器名字:port</value> // 8020
          </property>
          
         # 临时文件
          <property>
            <name>hadoop.tmp.dir</name>
			<value>/home/hadoop/app/tmp</value>
          </property>
vim /hdfs-site.xml设置副本数为1,因为默认是3
        <property>
·            <name>dfs.replication</name>
·            <value>1</value>
·          </property>

vim slaves主机名,有多少个datanode就需要写在这里边,这里暂时不用配置这个文件
启动hdfs,先到hadoop的目录下 或者cd到bin目录下(/home/hadoop/app/hadoop-2.6.0-cdh5.7.0/bin)
格式化文件系统(仅仅第一次执行,不要重复执行),:bin/hdfs namenode -format (表明在bin目录下执行hdfs命令)
启动hdfs: sbin/start-dfs.sh
 验证是否启动成功:
方式1:
jps
 DataNode
 SecondaryNameNode
 NameNode
方式二:浏览器访问方式: http://ip:50070
 停止hdfs
 sbin/stop-dfs.sh

HDFS shell操作

将hadoop的bin目录配置成环境变量中,和jdk的配置是一样的操作
vim ~/.bash_profile
export HADOOP_HOME=/.../hadoop...cdh5.7.0
export PATH=$HADOOP_HOME/bin:$PATH
source ~/.bash_profile

hdfs dfs,hadoop fs这就是操作hadoop的命令,可以查看到命令的介绍和帮助信息
 在/data/目录下创建一个hello.txt文件,vim hello.txt
 查看hadoop的根目录hadoop fs -ls /​​

 将data下面的hello.txt传递到hadoop上边去hadoop fs -put hello.txt /

 查看hadoop上边的文件的内容hadoop fs -text /hello.txt
 在hadoop上边创建一个目录hadoop fs -mkdir /test
 递归创建文件夹hadoop fs -mkdir -p /test/a/b
 递归展示目录hadoop fs -ls -R /或者-lsr选项
 使用别的方式拷贝本地文件到hadoop上边hadoop fs -copyFromLocal hello.txt /test/a/b/h.txt
 查看拷贝的文件的内容hadoop fs -cat /test/a/b/h.txt
 将hadoop上边的内容拿到本地来hadoop fs -get /text/a/b/h.txt
 删除文件hadoop fs rm /hello.txt
 删除文件夹目录hadoop fs rm -R /test
 从浏览器上边去浏览文件信息http://ip:50070上边的Utilities
 上传一个大的文件hadoop的安装包查看大小信息
 java操作HDFS开发环境搭建
·        idea+maven创建java工程
·        添加HDFS依赖
·        JAVA API 操作文件系统
具体操作
·        统一管理版本和添加hadoop的依赖包
 

      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
           <modelVersion>4.0.0</modelVersion>
        
           <groupId>com.imooc.hadoop</groupId>
           <artifactId>hadoop-train</artifactId>
           <version>1.0</version>
           <packaging>jar</packaging>
        
           <name>hadoop-train</name>
           <url>http://maven.apache.org</url>
        
           <!--自己定义统一管理Hadoop的版本-->
           <properties>
               <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
               <hadoop.version>2.6.0-cdh5.7.0</hadoop.version>
           </properties>
        
           <!--添加一个cdh的仓库,url必须指定正确的路径-->
           <repositories>
               <repository>
                   <id>cloudera</id>
                   <url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
               </repository>
           </repositories>
        
           <dependencies>
               <!--添加hadoop依赖-->
               <dependency>
                   <groupId>org.apache.hadoop</groupId>
                   <artifactId>hadoop-client</artifactId>
                   <version>${hadoop.version}</version>
               </dependency>
               <!--添加单元测试的依赖-->
             <dependency>
                 <groupId>junit</groupId>
                 <artifactId>junit</artifactId>
                 <version>4.10</version>
                 <scope>test</scope>
             </dependency>
         </dependencies>
        </project>

JAVA代码
 

 	package com.imooc.hadoop.hdfs;
 	import org.apache.hadoop.conf.Configuration;
 	import org.apache.hadoop.fs.*;
 	import org.apache.hadoop.io.IOUtils;
 	import org.apache.hadoop.util.Progressable;
 	import org.junit.After;
 	import org.junit.Before;
 	import org.junit.Test;
 	import java.io.BufferedInputStream;
 	import java.io.File;
 	import java.io.FileInputStream;
 	import java.io.InputStream;
 	import java.net.URI;
 	
 	/**
 	- Hadoop HDFS Java API 操作
 	  */
 	public class HDFSApp {
 	    public static final String HDFS_PATH = "hdfs://ip:8020";
 	    FileSystem fileSystem = null;
 	    Configuration configuration = null;
 	    /**
 	   * 创建HDFS目录
 	   */
 	    @Test
 	    public void mkdir() throws Exception {
 	        fileSystem.mkdirs(new Path("/hdfsapi/test"));
 	    }
 	
 	    /**
 	   * 创建文件
 	   */
 	    @Test
 	    public void create() throws Exception {
 	        FSDataOutputStream output = fileSystem.create(new Path("/hdfsapi/test/a.txt"));
 	        output.write("hello hadoop".getBytes());
 	        output.flush();
 	        output.close();
 	    }
 	
 	    /**
 	   * 查看HDFS文件的内容
 	   */
 	    @Test
 	    public void cat() throws Exception {
 	        FSDataInputStream in = fileSystem.open(new Path("/hdfsapi/test/a.txt"));
 	        IOUtils.copyBytes(in, System.out, 1024);
 	        in.close();
 	    }
 	    /**
 	   * 重命名
 	   */
 	    @Test
 	    public void rename() throws Exception {
 	        Path oldPath = new Path("/hdfsapi/test/a.txt");
 	        Path newPath = new Path("/hdfsapi/test/b.txt");
 	        fileSystem.rename(oldPath, newPath);
 	    }
 	
 	    /**
 	   * 上传文件到HDFS
 	   *
 	   * @throws Exception
 	   */
 	    @Test
 	    public void copyFromLocalFile() throws Exception {
 	        Path localPath = new Path("/Users/rocky/data/hello.txt");
 	        Path hdfsPath = new Path("/hdfsapi/test");
 	        fileSystem.copyFromLocalFile(localPath, hdfsPath);
 	    }
 	
 	    /**
 	   * 上传文件到HDFS
 	   */
 	    @Test
 	    public void copyFromLocalFileWithProgress() throws Exception {
 	        InputStream in = new BufferedInputStream(
 	            new FileInputStream(
 	                new File("/Users/rocky/source/spark-1.6.1/spark-1.6.1-bin-2.6.0-cdh5.5.0.tgz")));
 	
 	        FSDataOutputStream output = fileSystem.create(new Path("/hdfsapi/test/spark-1.6.1.tgz"), new Progressable() {                                                          public void progress() {
 	            System.out.print("."); //带进度提醒信息
 	       	  }});
 	        IOUtils.copyBytes(in, output, 4096);
 	    }
 	    
 	    /**
 	   * 下载HDFS文件
 	   */
 	    @Test
 	    public void copyToLocalFile() throws Exception {
 	        Path localPath = new Path("/Users/rocky/tmp/h.txt");
 	        Path hdfsPath = new Path("/hdfsapi/test/hello.txt");
 	        fileSystem.copyToLocalFile(hdfsPath, localPath);
 	    }
 	
 	    /**
 	   * 查看某个目录下的所有文件
 	   */
 	    @Test
 	    public void listFiles() throws Exception {
 	        FileStatus[] fileStatuses = fileSystem.listStatus(new Path("/"));
 	
 	        for(FileStatus fileStatus : fileStatuses) {
 	            String isDir = fileStatus.isDirectory() ? "文件夹" : "文件";
 	            short replication = fileStatus.getReplication();
 	            long len = fileStatus.getLen();
 	            String path = fileStatus.getPath().toString();
 	
 	            System.out.println(isDir + "\t" + replication + "\t" + len + "\t" + path);
 	        }
 	
 	    }
 	
 	    /**
 	   * 删除
 	   */
 	    @Test
 	    public void delete() throws Exception{
 	        fileSystem.delete(new Path("/"), true);
 	    }
 	    @Before
 	    public void setUp() throws Exception {
 	        System.out.println("HDFSApp.setUp");
 	        configuration = new Configuration();
 	        fileSystem = FileSystem.get(new URI(HDFS_PATH), configuration, "hadoop");
 	    }
 	
 	    @After
 	    public void tearDown() throws Exception {
 	        configuration = null;
 	        fileSystem = null;
 	
 	        System.out.println("HDFSApp.tearDown");
 	    }

HDFS写数据流程
文件写流程图解
告诉客户端读写请求
namenode协调全局把控
datanode负责数据的存储
写过程
发起请求(多少兆什么的)
客户端收到请求(客户端需要告诉block的大小,副本多少等)
好的客户端需要知道一些事情(blocksize,副本因子)
将文件拆分成blocks
客户端和namenode通信告诉blocksize以及副本等
namenode思考怎么做呢,计算
将结果告诉客户端(存放到哪儿)
客户端发数据到datanode上
datanode1接受数据的同时将数据发送到另外一个datanode,进行副本处理,第二个也是同样的处理,最后一个datanode写完了,就说明第一个block写完了
每个datanode将信息告诉namenode写完了
namenode知道了之后客户端也知道了
重复剩下的block块
客户端处理完了之后关闭流
namenode将元信息存储到内存或者磁盘
HDFS读数据流程
读过程
用户告诉客户端读取数据,读哪个文件
客户端将文件名给namenode获取元数据信息
namenode告诉block信息和datanode的集合
客户端知道了信息block和存放在哪个datanode
客户端和datanode交互下载文件
故障的容错,hdfs都做了很好的处理
HDFS文件系统的优缺点
优点
数据冗余(多副本存储在节点上),硬件容错(某台挂掉也能用)
处理流式的数据访问,这里的流式是一次存储多次读写的操作
适合存储大文件
可构建在廉价的机器上
缺点(不能满足下列问题)
低延时的数据访问
小文件存储,元信息太多











 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值