1. 程式人生 > >Day3.Hadoop學習筆記1

Day3.Hadoop學習筆記1

零、概述

一、概述

  • Hadoop衍生自Nutch(搜尋引擎和web爬蟲),面臨的問題:海量資料儲存和計算

  • Big Data大資料,談的不僅僅是資料量,其實包含了資料量(Volume)、時效性(Velocity)、多樣性(Variety)、可疑性(Veracity)
    綜上所述,我們可以總結出大資料的4V特徵:
    Volume 資料體量龐大 (PB級->EB級->ZB級)
    Velocity 速度要求快 (資料輸入輸出的速度)
    Varity 資料型別多樣 (文字|影象|音視訊)
    Veracity 資料價值密度低 (商業價值高)

  • Hadoop是一個開源儲存和計算框架,HDFS大規模資料儲存服務,MapReduce實現了對海量資料的並行處理和分析。

  • 使用領域:電商推薦、論壇(精裝營銷)、交通(實時路況)、醫療、電信、金融

一、引言

  • Hadoop是什麼?
    一種老牌的大資料解決方案。包括如下兩部分:
    HDFS(Hadoop Distribute FileSystem):hadoop分散式檔案系統。
    MapReduce:平行計算框架的稱呼,源自於該計算模型的實現策略。

  • Hadoop ECO System(hadoop的生態圈)

    HDFS:分散式儲存
    MapReduce:平行計算

    HBASE:hadoop的資料庫系統,基於HDFS之上的一款NoSQL資料庫。面向列儲存的NOSQL資料庫,使用HDFS作為底層儲存服務
    Kafka:分散式訊息佇列,解決高併發
    Flume:分散式日誌採集系統,實現對資料收集、轉移以及聚合
    Hive:一款基於SQL的解析引擎,可以將SQL翻譯成MapReduce計算,降低程式設計師使用門檻。一款工具,將使用者的SQL翻譯成MapReduce任務
    zookeeper:分佈協調服務框架
    (瞭解)
    Mahout: 一個可以擴充套件的及其學習以及資料探勘庫。
    Spark:一個快速的通用的計算引擎用於計算Hadoop上的資料。基於記憶體。

  • 分散式計算(拓展自學)
    1、離線的大資料分析系統
    (Hadoop MapReduce,Spark Core)
    2、線上的實時流處理分析
    (Storm,Spark Streaming,Flink)

二、瞭解HDFS(hadoop分散式檔案系統)

  • HDFS借鑑了GFS的資料冗餘度思想
    存在批量的硬碟;【DataNode 資料節點】
    HDFS預設冗餘度為“3”,就是一份同樣資料儲存三份;
    利用“水平復制”提升上傳效率;
    以“資料塊”作為單位進行資料傳輸(1.x版本 64m、2.x版本 128m);
    存在一個“管理員”進行管控排程【NameNode 名稱節點】

  • hadoop的安裝模式(三種)
    本地模式(一臺)、偽分佈模式(一臺)、全分佈環境(至少三臺)

  • HDFS區別其他分散式檔案系統:
    ①是一個高容錯性系統——高容錯性(fault-tolerant)
    ②提供高吞吐量的資料訪問——高吞吐量(high throughput)
    ③廉價機器,成本低——(low-cost)
    ④超大資料儲存——超大資料集(large data set)

三、HDFS環境搭建(偽分散式,單機跨程序)

  1. 安裝好Linux64位後,執行操作啟用ip
ifconfig -a		//檢視ip情況
vi /etc/sysconfig/network-scripts/ifcfg-eth0	//進入vi編輯,多使用tab補全避免出錯
//將onboot改成yes
儲存編輯後
ifup eth0	//啟動eth0
ifconfig -a		//檢視ip生效否(我的inet addr是192.168.153.137)
  1. 關閉防火牆
[[email protected] ~]# service iptables stop
iptables: Setting chains to policy ACCEPT: filter          [  OK  ]
iptables: Flushing firewall rules:                         [  OK  ]
iptables: Unloading modules:                               [  OK  ]
[[email protected] ~]# chkconfig iptables off
  1. 軟體需求
CentOS-6.5-x86_64-minimal.iso
jdk-8u171-linux-x64.rpm
  1. 建議,修改主機名
[[email protected] ~]# vi /etc/sysconfig/network
NETWORKING=yes
HOSTNAME=CentOS
[[email protected] ~]# reboot # 重啟虛擬機器
  1. 配置主機名和ip對映關係
vi /etc/hosts	#配置主機名和IP對映關係
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.153.137 CentOS	#新增這一句

ping Centos	#能夠ping通,表示正常
  1. 安裝JDK jdk-8u171-linux-x64.rpm
yum install -y lrzsz	#安裝外掛,支援彈出視窗上傳
rz	#開啟視窗上傳
//上傳jdk
rpm -ivh jdk-8u171-linux-x64.rpm	#安裝
ls /usr/	#檢視下是否安裝上

vi /root/.bashrc	#編輯環境變數,如下(已將下方的HADOOP的環境變數也配置了)

HADOOP_HOME=/usr/hadoop-2.6.0
JAVA_HOME=/usr/java/latest
PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
CLASSPATH=.
export JAVA_HOME
export PATH
export CLASSPATH
export HADOOP_HOME

source /root/.bashrc	#載入當前環境變數
java -version	#檢視下,是否配置上

如果,解除安裝RPM安裝的JDK

[[email protected] ~]# rpm -qa | grep jdk	#檢視
jdk1.8-1.8.0_171-fcs.x86_64
[[email protected] ~]# rpm -e jdk1.8-1.8.0_171-fcs.x86_64	#解除安裝
  1. SSH 免密碼認證(本機免密碼登入自己)
ssh-keygen -t rsa	#加密演算法加密
ssh-copy-id CentOS	#第一次
  1. 安裝HDFS(解壓配置HADOOP_HOME) hadoop-2.6.0_x64.tar.gz
tar -zxf hadoop-2.6.0_x64.tar.gz -C /usr/
#配置環境變數,ps上邊已經配過

後續課程中Hbase、Hive、Spark On Yarn都需要識別系統的HADOOP_HOME

  1. 配置Hadoop的配置檔案etc/hadoop目錄下*
    core-site.xml
<property>
    <name>fs.defaultFS</name>
    <value>hdfs://CentOS:9000</value>
</property>
<property>
    <name>hadoop.tmp.dir</name>
    <value>/usr/hadoop-2.6.0/hadoop-${user.name}</value>
</property>

參考:http://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/core-default.xml

hdfs-site.xml

<property>
    <name>dfs.replication</name>
    <value>1</value>
</property>

參考:http://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml

slaves

CentOS	#將localhost改成CentOS

參考:http://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/SingleCluster.html

  1. 啟動HDFS
#第一次啟動,需要格式化namenode,要初始化fsimage映象
hdfs namenode -format
#指令 啟動hdfs/停止hdfs 注意:沒有空格
start-dfs.sh |stop-dfs.sh 
#檢視 java程序 jps
[[email protected] ~]# jps
3217 Jps
2979 DataNode
3115 SecondaryNameNode
1935 NameNode

正常,可以嘗試啟動瀏覽器:http://192.168.153.137:50070/

四、HDFS Shell(HDFS的shell命令)

[[email protected] ~]# hdfs dfs -help	# 或者hadoop fs -help 檢視幫助,檢視命令
Usage: hadoop fs [generic options]

	-appendToFile 	#追加檔案
	-cat 	#檢視檔案
	-chmod 	#修改檔案rwx全新啊
	-copyFromLocal 	#同 -put 拷貝
	-copyToLocal 	#同 -get 拷貝	(跨平臺 Linux和HDFS之間)
	-rm 	#刪除檔案
	-mv 	#移動,剪下
	-cp 	#拷貝(HDFS內的操作)
	-touchz #建立空檔案
	-text 	#檢視
	-tail 	#尾部檢視	

五、JavaAPI操作HDFS

  1. Windows測試HDFS API 注意事項
  • 解壓hadoop安裝包並在Windows 配置HADOOP_HOME環境變數
  • hadoop_dll2.6.0_64bit.zip中的winutils.exehadoop.dll檔案拷貝到Hadoop的bin目錄下
  • 在Win7 上配置CentOS和IP的對映關係C:\Windows\System32\drivers\etc下hosts檔案追加
192.168.153.137 CentOS
  • 重啟IDEA 確保開發編輯器可以識別 HADOOP_HOME
  1. 匯入依賴
	<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
    </dependency>
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-common</artifactId>
      <version>2.6.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-hdfs</artifactId>
      <version>2.6.0</version>
    </dependency>
  1. 測試
  • 解決HADOOP寫許可權問題?
    ①解決方案一、關閉HDFS許可權檢查
    修改hdfs-site.xml重啟hdfs
<property>
    <name>dfs.permissions.enabled</name>
    <value>false</value>
</property>

②解決方案二、欺騙hadoop,讓程式認為是root使用者在寫資料(修改java啟動虛擬機器引數),如下圖
圖1

  • 程式碼示例
import org.apache.commons.io.IOUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.junit.Before;
import org.junit.Test;

import java.io.*;
/**
 * Created by Turing on 2018/12/3
 */

public class HDFSDemo {
    private FileSystem fileSystem;

    @Before
    public void before() throws IOException {
        Configuration conf = new Configuration();

        conf.set("fs.defaultFS","hdfs://CentOS:9000");//core-site.xml
        conf.set("dfs.replication","1");
        fileSystem=FileSystem.get(conf);
    }

    /**
     * 上傳1
     * @throws IOException
     */
    @Test
    public void testUpload() throws IOException {
        FileInputStream is = new FileInputStream("C:\\Users\\Administrator\\Desktop\\study.txt");
        Path path = new Path("/hdfs_study1.txt");
        OutputStream os= (OutputStream) fileSystem.create(path);
        IOUtils.copy(is,os);    //org.apache.commons.io.IOUtils;
        is.close();
        os.close();
    }

    /**
     * 下載1
     * @throws IOException
     */
    @Test
    public void testDownload() throws IOException {
        OutputStream os = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\study222.txt");
        Path path = new Path("/hdfs_study1.txt");
        InputStream is= (InputStream) fileSystem.open(path);
        org.apache.hadoop.io.IOUtils.copyBytes(is,os,1024,true);
    }


    /**
     * 上傳2
     */
    @Test
    public void testUpload02() throws IOException {
        Path src=new Path("C:\\Users\\Administrator\\Desktop\\study222.txt");
        Path dst = new Path("/hdfs_study333.txt");
        fileSystem.copyFromLocalFile(src,dst);
    }

    /**
     * 下載2
     * @throws IOException
     */
    @Test
    public void testDownLoad02() throws IOException {
        Path dst=new Path("C:\\Users\\Administrator\\Desktop\\study333.txt");
        Path src = new Path("/hdfs_study1.txt");
        //如果出錯了,嘗試使用過載方法
        //fileSystem.copyToLocalFile(src,dst);
        fileSystem.copyToLocalFile(false,src,dst,true);
    }

    /**
     * 刪除
     * @throws IOException
     */
    @Test
    public void testDelete() throws IOException {
        Path src = new Path("/aa1.csv");
        //第二個引數 boolean recursive 是否遞迴刪除
        fileSystem.delete(src,true);
    }

    /**
     * 建立資料夾
     * @throws IOException
     */
    @Test
    public void testMkdir() throws IOException {
        Path src = new Path("/day1/study4");
        fileSystem.mkdirs(src);
    }

    /**
     * 遞迴遍歷檔案(只檔案)
     * @throws IOException
     */
    @Test
    public void testListFiles() throws IOException {
        Path src = new Path("/");
        RemoteIterator<LocatedFileStatus> files = fileSystem.listFiles(src, true);
        while (files.hasNext()){
            LocatedFileStatus file = files.next();
            System.out.println(file.getPath()+" "+file.isDirectory());
        }
    }

    /**
     * 遍歷根下檔案
     * @throws IOException
     */
    @Test
    public void testListFileStatus() throws IOException {
        Path src = new Path("/");
        FileStatus[] fileStatuses = fileSystem.listStatus(src);
        for (FileStatus fileStatus : fileStatuses) {
            System.out.println(fileStatus.getPath()+" "+fileStatus.isDirectory());
        }
    }
}