大數(shù)據(jù)介紹 大數(shù)據(jù)這個概念一直都是如火如荼,那什么是大數(shù)據(jù)呢?首先從名字來看,我們可以簡單地認為數(shù)據(jù)量大,而數(shù)據(jù)量大也就意味著計算量大。這樣理解本身是沒有任何問題的,只不過這并不能很好地定義大數(shù)據(jù)。 而業(yè)界的一家權(quán)威機構(gòu),針對大數(shù)據(jù)做了描述,認為大數(shù)據(jù)應該具備如下特征: 1)數(shù)據(jù)量(Volume):數(shù)據(jù)量大,可以達到 TB、PB 甚至更高。而這種規(guī)模的數(shù)據(jù),傳統(tǒng)的數(shù)據(jù)庫已經(jīng)不好處理了,所以才有了現(xiàn)在各種各樣的大數(shù)據(jù)框架。 2)多樣性(Variety):數(shù)據(jù)的類型繁多,比如簡單的數(shù)值、文本,地理位置、圖片、音頻、視頻等等,數(shù)據(jù)存在多樣性。而處理多樣性的數(shù)據(jù)所帶來的挑戰(zhàn),也就比以前更高; 3)價值(Value):原始數(shù)據(jù)都是雜亂無章的,我們無法直接得到有效信息。而對數(shù)據(jù)進行清洗、分類、匯總等各種處理之后,我們能夠從中找到一些規(guī)律,將其變成商業(yè)價值,這一步也就是數(shù)據(jù)分析師要做的事情。所以分析數(shù)據(jù)的目的是從中找到一些規(guī)律、信息,將其變成價值。而數(shù)據(jù)的價值密度和數(shù)據(jù)的總量通常是不成正比的,你的數(shù)據(jù)量增加一倍,但是價值未必增加一倍; 4)速度(Velocity):對于大數(shù)據(jù)而言,我們不僅追求大量數(shù)據(jù)的處理,還希望它能有讓人滿意的速度。在早期的大數(shù)據(jù)處理框架中,它是做不到實時的,只能進行離線批處理。但是很多場景下,我們是需要立刻就能計算出結(jié)果的,所以大數(shù)據(jù)領(lǐng)域也就慢慢誕生了更多的實時性框架。 以上便是大數(shù)據(jù)的 4V 特征。 而大數(shù)據(jù)的出現(xiàn),也必然會帶來一些技術(shù)性的革新。 比如數(shù)據(jù)存儲,大數(shù)據(jù)可以到 PB、EB、ZB 級別,這種數(shù)據(jù)量單臺機器已經(jīng)存儲不下了,所以數(shù)據(jù)存儲方面必然要發(fā)生改變。由原來的文件存儲變成了分布式文件存儲,也就是將一個大文件切分成多個小塊存儲在多臺機器上,這樣就解決了數(shù)據(jù)存儲的問題。 不僅如此,由于散落在多個機器上,如果某一臺機器掛掉了,那么就導致整個文件都無法讀取了。因此為了容錯,在切分成多個小塊的時候,還會將每一個塊多拷貝兩份,散落在不同的機器上。這樣一臺機器掛掉了,還可以從其它機器上讀,這一點在后續(xù)介紹 HDFS 的時候會詳細說。 除了數(shù)據(jù)存儲,還有數(shù)據(jù)計算。因為數(shù)據(jù)量大,必然也伴隨著計算量大,那該怎么辦呢?類比數(shù)據(jù)存儲,存儲的時候可以存在多臺機器上,那么計算的時候是不是也可以讓多臺機器一塊計算呢。所以將一個作業(yè)進行拆分,交給不同的機器進行計算,然后再將結(jié)果做一個歸并,這就是所謂的分布式計算。 而大數(shù)據(jù)生態(tài)圈中最著名的Hadoop,便是由分布式文件系統(tǒng)HDFS和分布式計算框架MapReduce 組成的,這個我們后面會說。 除了存儲和計算,還有網(wǎng)絡問題。以前單機的時候,數(shù)據(jù)就在你的本地,計算也在本地,所以沒什么好說的,直接讀取數(shù)據(jù)、計算就是了。但分布式文件存儲和分布式計算就不一樣了,因為數(shù)據(jù)被切分成了多塊,有可能某臺機器上的計算任務所需要的數(shù)據(jù)在其它的機器上,這是很正常的。因此很多時候數(shù)據(jù)之間的傳輸是不可避免的,這對網(wǎng)絡也是一個挑戰(zhàn),所以至少是萬兆網(wǎng),千兆已經(jīng)捉襟見肘了。特別是跨數(shù)據(jù)中心、跨地區(qū),要求會更高。 大數(shù)據(jù)處理都分為哪幾步
大數(shù)據(jù)在技術(shù)架構(gòu)上所帶來的挑戰(zhàn) 1. 對現(xiàn)有數(shù)據(jù)庫管理技術(shù)的挑戰(zhàn):對于 PB、EB 級別的大數(shù)據(jù)而言,使用目前的關(guān)系型數(shù)據(jù)庫存儲是不現(xiàn)實的,盡管數(shù)據(jù)庫也可以部署集群,但規(guī)模非常有限。而且由于數(shù)據(jù)量的原因,也很難使用現(xiàn)有的結(jié)構(gòu)化查詢語言來分析現(xiàn)有的大數(shù)據(jù); 2. 經(jīng)典數(shù)據(jù)庫技術(shù)并沒有考慮數(shù)據(jù)的多類別:大數(shù)據(jù)的 4V 特征中有一個 V 是多類別,現(xiàn)在的數(shù)據(jù)庫沒有辦法很好地存儲一些特殊類型的數(shù)據(jù); 3. 實時性技術(shù)的挑戰(zhàn):想從大量數(shù)據(jù)中提取相應的價值,花費的時間是不短的,如果使用現(xiàn)有的技術(shù)很難做到實時性; 4. 網(wǎng)絡架構(gòu)、數(shù)據(jù)中心、運維的挑戰(zhàn):數(shù)據(jù)一直在高速增長,當涉及到大量數(shù)據(jù)的傳輸時,對數(shù)據(jù)中心、運維會是一個不小的挑戰(zhàn); 如何對大數(shù)據(jù)進行存儲和分析呢 這是最直觀的一個問題,如果你都不能對大數(shù)據(jù)進行存儲、分析,那么也就談不上所謂的商業(yè)價值了。而數(shù)據(jù)的存儲和分析,自然需要由專業(yè)的框架來完成,當然你也可以自己開發(fā)一個框架,但這顯然是非常困難的,我們也不會這么做。因為在大數(shù)據(jù)的存儲和計算中,存儲容量、讀寫速度、計算效率等等,這些都是需要考慮的。 而幸運的是,Google 的三駕馬車:GFS, MapReduce, BigTable 解決了這一點,但 Google 并沒有將它們開源,只是發(fā)表了相應的技術(shù)論文。而 Hadoop 便是 Hadoop 的作者基于 Google 的論文、使用 Java 語言開發(fā)的。我們來介紹一下:
Hadoop 概述 下面我們就來認識一下Hadoop,看看它的概念是什么?核心組件有哪些?具有哪些優(yōu)勢?發(fā)展史等等。 提到 Hadoop,有狹義上的 Hadoop,還有廣義上的 Hadoop。
下面我們說的 Hadoop,指的是狹義上的 Hadoop,也就是 Hadoop 本身。 先說一下 Hadoop 這個名字的由來,這個名字沒有任何的意義,它是作者的兒子給一個玩具大象起的名字,所以 Hadoop 官網(wǎng)的 logo 也是一個大象。另外這些大數(shù)據(jù)框架基本上都是Apache的頂級項目,它們的官網(wǎng)都是項目名.apache.org,比如Hadoop的官網(wǎng)就是hadoop.apache.org。 那么 Hadoop 是什么呢? Hadoop 是一個可靠的、可擴展的、分布式的計算框架,它可以對大量的數(shù)據(jù)集進行并行處理。我們知道單臺機器的能力是不夠的,所以可以將多臺機器組成一個集群,而集群中每一臺機器都叫做一個節(jié)點,Hadoop 可以從單機(單節(jié)點)擴展到上千個節(jié)點,來對數(shù)據(jù)進行存儲和計算。如果存儲不夠了,怎么辦?直接加機器就好了,節(jié)點的擴展非常容易。 另外最重要的是,Hadoop 可以部署在廉價的機器上,而不需要使用昂貴的小型機、或者刀片機等等。而且還提供了故障恢復、容錯等機制。 Hadoop 主要由以下幾個部分組成。
HDFS 和 MapReduce 我們一開始說過了,但是還有一個 YARN,它是用來對集群資源進行管理、以及作業(yè)的調(diào)度的。還是舉之前的例子,如果一個作業(yè)所需要的數(shù)據(jù)不在當前節(jié)點上該怎么辦?顯然有兩種做法:
而在大數(shù)據(jù)領(lǐng)域中是有說法的,移動數(shù)據(jù)不如移動計算,因為數(shù)據(jù)的移動成本要比計算的移動成本高很多。所以這個時候就需要 YARN 了,當然 YARN 還用于資源的管理,給每個作業(yè)分配相應的資源等等。 Hadoop 的優(yōu)勢 那么 Hadoop 的優(yōu)勢都有哪些呢?
Hadoop 生態(tài)圈 我們說 Hadoop 分為狹義 Hadoop 和廣義 Hadoop。 狹義 Hadoop 指的是:一個適合大數(shù)據(jù)的分布式存儲(HDFS)、分布式計算(MapReduce)和資源調(diào)度(YARN)平臺,所以狹義 Hadoop 指的就是 Hadoop 框架本身。 廣義 Hadoop 指的是:Hadoop 生態(tài)系統(tǒng),這是一個很龐大的概念,Hadoop 框架是其中最重要、也是最基礎(chǔ)的一個部分;生態(tài)系統(tǒng)中的每一個子系統(tǒng)只解決某一個特定的問題域(甚至可能很窄),不搞統(tǒng)一型的一個全能系統(tǒng),而是小而精的多個小系統(tǒng)。 Hadoop 生態(tài)圈里面的東西還是非常非常多的,囊括了大數(shù)據(jù)處理的方方面面,并且這是一個成熟的生態(tài)圈。像 Flume 做日志采集、Sqoop 做數(shù)據(jù)的導入導出,還有調(diào)度系統(tǒng)以及分布式協(xié)調(diào)服務等等。我們這里學習的是 Hadoop,并且是狹義上的 Hadoop。 Hadoop 常用的發(fā)行版 首先是社區(qū)版,也就是 Apache 版本,直接去官網(wǎng)就可以下載。它的特點是純開源,可以直接在源碼的基礎(chǔ)上進行二次開發(fā);但是不同版本/框架之間的整合有時會比較麻煩,比如 jar 包的沖突等等。 然后是 CDH 版本,它是 cloudera 公司開發(fā)的 Hadoop,并且提供了 cloudera manager,可以通過頁面進行可視化操作,比如一鍵安裝各種框架、對框架升級等等,并且還幫你屏蔽了不同框架之間的 jar 包沖突。但是 CDH 不開源,并且與社區(qū)版本有點出入。但凡是使用 Hadoop 的公司,有百分之 60~70 使用的都是 CDH,包括筆者以前所在的公司,其信息中心就是采購的 CDH。 最后是 HDP版本,由 Hortonworkds 公司提供,原裝 Hadoop、支持 tez;但是企業(yè)級安全不開源。 如果是在學習的時候,使用哪種發(fā)行版都無所謂,但是在生產(chǎn)環(huán)境中最好使用 CDH 或者 HDP,這里我們就使用社區(qū)版了。 安裝 Hadoop 下面我們就開始安裝 Hadoop 了,你可以使用虛擬機,或者云服務器等等。我這里使用的騰訊云服務器,操作系統(tǒng)是 CentOS7。 另外 Hadoop 的運行模式有三種:
我們后續(xù)使用的是偽分布式,但是在學習的時候,和使用真正意義上的分布式之間是沒有太大區(qū)別的。 在學習的時候,不建議上來就搭建完全分布式的 Hadoop 集群,Hadoop 還沒搞明白就開始搭建分布式集群的話,真的是很容易造成從入門到放棄。一開始完全可以搭建一個單機版的偽集群,因為在學習的時候和真正的集群沒有太大區(qū)別。 下面就開始安裝 Hadoop 了,不過在安裝它之前,我們還需要安裝 jdk。因為 Hadoop 是 Java 語言編寫的,所以我們需要安裝 jdk,至于版本請保證在1.8以上。 這里我的軟件都安裝在 /opt 目錄下,其中 jdk 已經(jīng)安裝好了,至于它的安裝也很簡單,這里就不介紹了。 下面安裝 Hadoop,我們直接去官網(wǎng)下載即可,這里我下載的版本是 2.8.4。下載成功之后,直接解壓即可。 解壓之后的文件目錄如上圖所示,我們來介紹幾個重要的目錄。
目錄里面的文件我們在用到的時候會說,下面我們來介紹 Hadoop 最重要的三大組件,首先是 HDFS。 分布式文件系統(tǒng) HDFS 什么是HDFS,它和普通的文件系統(tǒng)之間有什么區(qū)別呢? HDFS(Hadoop Distributed File System)是一個分布式文件系統(tǒng),用于存儲文件,通過目錄樹來定位文件;其次它是分布式的,可以橫跨 N 個機器,由多個節(jié)點聯(lián)合起來實現(xiàn)其功能,集群中的節(jié)點有各自的角色。 HDFS 產(chǎn)生背景 隨著數(shù)據(jù)量越來越大,在一臺機器上無法存下所有的數(shù)據(jù),那么就分配到更多的機器上,但是這樣不方便管理和維護。因此迫切需要一種系統(tǒng)來管理多臺機器上的文件,這就是分布式文件管理系統(tǒng),HDFS 只是其中的一種。 HDFS 使用場景 適合一次寫入,多次讀出的場景,且不支持文件的修改。適合用來做數(shù)據(jù)分析,并不適合做網(wǎng)盤應用。很好理解,HDFS 的定位就決定了它不適合像關(guān)系型數(shù)據(jù)庫那樣,可以任意修改數(shù)據(jù)。而且寫入數(shù)據(jù),一定是大批量一次性寫,至于原因后面會解釋。 HDFS 的設(shè)計目標 1)解決硬件故障 HDFS 設(shè)計出來就是為了存儲大量數(shù)據(jù),因為 HDFS 可以跨上千個節(jié)點,每個節(jié)點只存儲數(shù)據(jù)的一部分。但是這樣的話,其中任何一個節(jié)點故障,都會導致無法讀取整個文件,所以 HDFS 還要具備相應的容錯性。 首先 HDFS 在接收到一個大文件之后,會將其切分成塊(block),每一個 block 的大小默認是 128M。然后將每一個塊再拷貝兩份(所以總共默認是 3 份,也就是三副本),分別散落在不同的節(jié)點上,這樣一臺節(jié)點掛了(或者磁盤壞掉了),還可以從其它節(jié)點上找。我們畫一張圖: 這里我們以 500M 的文件為例,顯然它頂多是個小型數(shù)據(jù),這里只是舉個例子。 因此以上便屬于硬件故障,HDFS 要具備快速檢測錯誤的能力,并且能從錯誤中自動恢復,這才是 HDFS 設(shè)計架構(gòu)的核心目標。不能說一臺機器癱了或者存儲壞掉了,整個 HDFS 集群就不能工作了。 2)流式數(shù)據(jù)訪問 運行在 HDFS 上的應用程序會以流的方式訪問數(shù)據(jù)集,這和普通的文件系統(tǒng)不同,因為 HDFS 更多地被應用于批處理,而不是和用戶之間進行交互式訪問。所以 HDFS 關(guān)注的是高吞吐量,而不是數(shù)據(jù)訪問的低延遲,從這一點我們也能看出 HDFS 不適合做實時處理。 3)大型數(shù)據(jù)集 HDFS 可以管理大型數(shù)據(jù)集,TB、PB 甚至更高的級別。而 HDFS 不怕文件大,就怕文件小,這是面試的時候經(jīng)常被問到的點,這背后更深層次的含義我們后面會說。總之一個 HDFS 集群可以有幾千個節(jié)點,可以管理非常大的文件。 4)移動計算比移動數(shù)據(jù)更劃算 這一點我們之前說過了,假設(shè)計算任務在 A 節(jié)點上,但是數(shù)據(jù)在 B 節(jié)點上。這個時候要么把計算調(diào)度到 B 機器上,要么把數(shù)據(jù)傳輸?shù)?A 機器上。而移動計算的成本比移動數(shù)據(jù)的成本低很多,所以我們應該將計算調(diào)度到 B 機器上,HDFS 也支持這一點。 HDFS 的架構(gòu) HDFS 有兩個核心概念:NameNode、DataNodes,并且是一個主從架構(gòu)。而 NameNode 就是 master,DataNodes 是 slave。注意:DataNodes 的結(jié)尾有一個 s,意味著會有多個 DataNode;但是 NameNode 后面沒有 s,因此它只有一個,事實上也確實如此。 HDFS 集群由一個 NameNode 和多個 DataNode 組成,NameNode 負責管理文件系統(tǒng)的 namespace(名字空間,比如文件的目錄結(jié)構(gòu)便是 namespace 的一部分),并提供給客戶端固定的訪問途徑。因為客戶端需要讀寫數(shù)據(jù),首先經(jīng)過的就是 NameNode。 除了 NameNode,還有多個 DataNode,DataNode 就是用來存儲數(shù)據(jù)的一個進程,通常一個節(jié)點對應一個 DataNode。所以一個 HDFS 集群可以由多個節(jié)點組成,其中一個節(jié)點負責啟動 NameNode 進程,剩余的節(jié)點負責啟動 DataNode 進程。在內(nèi)部,一個文件會被拆分多個塊,并默認以三副本存儲,然后默認存儲在多個 DataNode 對應的節(jié)點上。 注意:我們說客戶端創(chuàng)建、刪除文件,都是通過 NameNode,它負責執(zhí)行文件系統(tǒng)的類似 CRUD 的操作。并且最重要的是,它還決定了 block 和 DataNode 之間的映射關(guān)系。 假設(shè)由一個 150M 的文件,存儲的時候會被切分成兩個塊,那么問題來了:block1 存在哪個 DataNode 中呢,block2 又存在哪個 DataNode 中呢?其實這一點不用擔心,因為我們說 NameNode 會記錄每個 block 和 DataNode 的映射關(guān)系,這些便是數(shù)據(jù)的元信息。比如拆分成幾個塊,每個塊都散落在哪些 DataNode 上。 所以客戶端獲取數(shù)據(jù)的時候,一定要經(jīng)過 NameNode,不然這些元信息你拿不到。因此在存儲的時候,NameNode 會記錄這些元信息,當我們獲取的時候 NameNode 會根據(jù)元信息找到對應的 DataNode,而這個過程對于用戶來說是不可見的。
至于數(shù)據(jù)本身的讀寫,則是通過 DataNode 來完成的,因為數(shù)據(jù)存在 DataNode 對應的節(jié)點上。 所以我們可以再來總結(jié)一遍。 NameNode:就是 master,它是一個主管、管理者
DataNode:就是 slave,NameNode 下達命令,DataNode 執(zhí)行實際的操作
client:就是客戶端
還有一個 Secondary NameNode:它不是 NameNode 的替補,當 NameNode 掛掉時,并不能馬上替換 NameNode 并提供服務,它的作用如下
我們來看幾幅漫畫,寫得非常好,個人給翻譯了一遍。 從這里我們便了解了 HDFS 的整體架構(gòu),用一張圖總結(jié)就是: 那么下面再來總結(jié)一下 HDFS 的優(yōu)缺點。 優(yōu)點: 1)高容錯性:數(shù)據(jù)自動保存多個副本,它通過增加副本的形式,提高容錯性;即使某一個副本丟失,也可以自動恢復; 2)適合處理大數(shù)據(jù):數(shù)據(jù)規(guī)模大,能夠處理 TB、甚至 PB 級別的數(shù)據(jù);文件規(guī)模大,能夠處理百萬規(guī)模以上的文件,數(shù)量相當之大; 3)可構(gòu)建在廉價的機器之上,通過多副本機制,提高可靠性; 缺點 1)不適合低延時數(shù)據(jù)訪問,如果你想做到毫秒級存儲,別想了,做不到的; 2)無法高效地對大量小文件進行存儲,存一個 1G 的數(shù)據(jù)比存 10 個 100MB 的數(shù)據(jù)要高效很多;至于原因和我們之前說的 HDFS 不怕文件大,就怕文件小是類似的。
3)不支持并發(fā)寫入和文件的隨機修改,一個文件只能有一個寫,不允許多個線程同時寫。僅支持數(shù)據(jù)的 append,不支持文件的隨機修改。 HDFS 塊大小的設(shè)置 HDFS 中的文件在物理上是分塊存儲(block),塊的大小可以通過配置參數(shù)(df.blocksize)指定,默認大小是 128M,老版本是 64M。 那么這個塊大小是怎么來的呢?首先我們說讀取一個塊的時候,需要先經(jīng)過 NameNode 確定該塊在哪些節(jié)點上,而這是需要時間的,一般稱為尋址時間。而當尋址時間為塊讀取時間的 1% 時,是最佳狀態(tài)。 一般尋址時間為 10ms,那么塊讀取時間為 1s,而目前磁盤的傳輸速率普遍為 100M/s,因此塊大小大概 100M 左右。根據(jù)實際情況可能略有不同,但大致是 100多M 左右。 思考:為什么塊不能設(shè)置太小,也不能設(shè)置太大?
總結(jié):HDFS 塊的大小設(shè)置主要取決于磁盤的傳輸速率。 修改配置文件,啟動偽集群 下面來啟動集群,但需要先修改幾個配置文件。我們在介紹 Hadoop 目錄結(jié)構(gòu)的時候說過,配置文件都在安裝目錄的 etc/hadoop 目錄中。 修改 hadoop-env.sh 里面配置好 JAVA 的安裝路徑。 修改 core-site.xml 修改 hdfs-site.xml 修改 slaves 將集群當中的 DataNode 節(jié)點都寫在里面,而當前只有一個節(jié)點,它既是 NameNode 又是 DataNode,所以寫一個 localhost 進去就行。但該文件里面默認就是 localhost,因此這個文件當前不需要修改。之所以提一嘴,是想提示在搭建集群的時候,別忘記將 DataNode 所在節(jié)點都寫在里面。 目前只需要修改以上幾個文件,然后啟動集群(偽)。但在此之前需要先格式化 NameNode,注意:只需要在第一次啟動時格式化。
如果格式化成功,那么 hadoop.tmp.dir 參數(shù)指定的目錄會自動創(chuàng)建。 然后啟動 Hadoop 集群:
執(zhí)行該命令的時候會依次啟動 NameNode, DataNode, SecondaryNameNode,但會要求你三次輸入當前用戶的密碼,并且每次啟動、關(guān)閉的時候都是如此。在多節(jié)點通信的時候,顯然不能這樣,雖然目前是單節(jié)點,但每次輸入密碼也很麻煩,因此建議配置免密碼登錄。 啟動完畢,并且啟動時的日志信息也記錄在了文件里,但如果你查看的話會發(fā)現(xiàn)并沒有什么信息。這是因為顯示的文件不對,你只需要把結(jié)尾的 out 改成 log 就可以查看日志信息了,這個應該是 Hadoop 內(nèi)部的問題,不過無關(guān)緊要。 那么到底有沒有啟動成功呢?我們輸入 jps 查看一下。 如果出現(xiàn)了黃色方框里的內(nèi)容,那么就證明啟動成功了。另外這是三個獨立的進程,可能出現(xiàn)有的啟動成功,有的啟動失敗,比如你發(fā)現(xiàn)顯示的進程中沒有 NameNode,那就證明 NameNode 啟動失敗了,你就需要去對應的日志文件中查看原因。
只有當上面三個進程同時出現(xiàn),才算啟動成功。然后我們在瀏覽器輸入:ip:50070,可以查看 webUI 界面。 頁面信息大致如上,在 Summary 中有很多關(guān)于節(jié)點的信息,可以看一下。另外導航欄中的最后一個 utilities,點擊的話會出現(xiàn)一個下拉菜單,里面有一個 Browse the file system。點擊的話,可以查看整個文件的目錄結(jié)構(gòu),后面會說。 最后補充一點,我們不可以重復格式化 NameNode。因為該操作會產(chǎn)生新的集群 id,導致 NameNode 和 DataNode 的集群 id 不一致,集群找不到以往的數(shù)據(jù)。所以格式化 NameNode 的時候,務必要先刪除 data 數(shù)據(jù)和 log 日志,然后再格式化。因為兩者需要有一個共同的 id,這樣才能交互。 hdfs shell 命令 HDFS 的 shell 命令和 Linux 是非常類似的,比如查看某個目錄下的文件,Linux 是 ls,那么 hdfs shell 就是 hdfs dfs -ls,再比如查看文件內(nèi)容是 hdfs dfs -cat filename。兩者非常相似,只不過在 hdfs shell 中需要加上一個橫杠。 另外 hdfs dfs 還可以寫成 hadoop fs,對于 shell 操作來說兩者區(qū)別不大,下面就來介紹一些常用的命令。 hdfs dfs -help 某個命令 顯然這是查看某個命令使用方法的命令,比如查看 cat 的使用方法。 hdfs dfs -ls 目錄路徑 查看某個目錄有哪些文件,加上 -R 表示遞歸顯示。由于當前沒有文件,所以不演示了。 hdfs dfs -mkdir 目錄 在 hdfs 上面創(chuàng)建目錄,加上 -p 表示遞歸創(chuàng)建,和 Linux 是一樣的。 hdfs dfs -moveFromLocal 本地路徑 hdfs路徑 將本地文件或目錄移動到 hdfs 上面,注意是移動,移完之后本地就沒了。 hdfs dfs -cat 文件 查看一個文件的內(nèi)容。 hdfs dfs -appendToFile 追加的文件 追加到哪個文件 將一個文件的內(nèi)容追加到另一個文件里面去。 我們將本地 other.py 里的內(nèi)容追加到了 HDFS 上的 /code.py 文件中。 hdfs dfs [-chgrp、-chmod、-chown] 更改組、更改權(quán)限、更改所有者,這個和 Linux 中用法一樣。 hdfs dfs -copyFromLocal 本地路徑 hdfs路徑 將文件從本地拷貝到 HDFS 上面去,這個和剛才的 moveFromLocal 就類似于 Linux 中的 cp 和 mv。 hdfs dfs -copyToLocal hdfs路徑 本地路徑 將 HDFS 上的文件拷貝到本地,此時是 HDFS 路徑在前、本地路徑在后。 hdfs dfs -cp 源hdfs路徑 目的hdfs路徑 上面的拷貝都是針對本地路徑和 HDFS 路徑,而 -cp 則是在兩個 HDFS 路徑之間拷貝。 hdfs dfs -mv 源hdfs路徑 目的hdfs路徑 和 -cp 用法一樣,不過 -cp 是拷貝,-mv 是移動。 hdfs dfs -get hdfs路徑 本地路徑 等同于 copyToLocal。 hdfs dfs -put 本地路徑 hdfs路徑 等同于 copyFromLocal。 hdfs dfs -getmerge hdfs路徑(通配符) 本地路徑 將 hdfs 上面的多個文件合并下載到本地。 hdfs dfs -tail 文件名 顯示文件的結(jié)尾,類似于 Linux 的 tail。 hdfs dfs -rm 文件 刪除文件,如果是文件夾需要加上 -r。 hdfs dfs -rmdir 空目錄 刪除一個空目錄,不常用,一般使用 -rm。 hdfs dfs -du 目錄 統(tǒng)計目錄的大小信息:
hdfs dfs -setrep 數(shù)值 文件 設(shè)置文件的副本數(shù)量,比如 hdfs dfs -setrep 5 /file.txt,表示將 file.txt 的副本設(shè)置成 5。 使用webUI觀察HDFS存儲 我們上傳一個稍微大一點的文件進去吧,就把 jdk 壓縮包上傳到 HDFS 上。 這里我們上傳到了 HDFS 的根目錄,通過 webUI 來查看一下。 我們發(fā)現(xiàn)文件已經(jīng)在里面了,并且這個文件的大小是 180.06M,顯然會被切成兩個塊,每個塊的副本系數(shù)是 1,因為我們設(shè)置的是 1。然后點擊一下該文件: 可以看到拆分之后的兩個塊的信息,分別是 block0 和 block1,而且每個塊都有一個 ID,是依次增大的,并且兩個 Size 加起來也一定是 jdk 安裝包的大小。然后它存在什么地方呢?還記得之前配置的 hadoop.tmp.dir 嗎? 最終我們進入到 subdir0 這個目錄,層級非常的多,然后我們看看里面都包含了哪些內(nèi)容。 箭頭所指的就是 jdk 壓縮包的兩個塊,并且文件名的結(jié)尾就是對應的塊id,而且大小也和 webUI 上顯示的一樣。然后 jdk 壓縮包被切分成了兩個塊,而現(xiàn)在這兩個塊我們都找到了,如果將它們合并在一起話,那么 tar 命令能不能正常解壓呢?我們來試試。 現(xiàn)在你還覺得 HDFS 神奇嗎?所以就是之前說的,只是將文件切分成塊,然后散落在不同節(jié)點的本地存儲中。查找的時候,會去 NameNode 獲取元信息,找到相應的塊再組合起來,就這么簡單。因此 HDFS 還是需要依賴本地進行存儲的,只不過內(nèi)部的 NameNode 會幫助我們對塊進行管理,但本質(zhì)上就是文件的拆分與合并的過程。 Python連接HDFS 使用 HDFS SHELL 只是用來臨時做測試用,工作中肯定是通過代碼來操作的,那么下面來看看如何使用 Python 連接 HDFS,并進行相關(guān)操作。
首先 Python 若想操作 HDFS,需要下載一個第三方庫,也叫 hdfs,直接 pip install hdfs 即可。
client.list:查看指定目錄的內(nèi)容
client.status:獲取指定路徑的狀態(tài)信息
client.makedirs:創(chuàng)建目錄
如果不出意外的話,你在執(zhí)行的時候應該會報錯:hdfs.util.HdfsError: Permission denied:。因為默認情況下我們只能查看 HDFS 上的數(shù)據(jù),但是不能寫入、修改、刪除。 如果你創(chuàng)建目錄的話,就會拋出這個異常。至于解決辦法也很簡單,我們修改 hdfs-site.xml,在里面添加如下內(nèi)容,然后重啟 Hadoop 集群。
但如果你重啟集群之后立即執(zhí)行的話,那么還是會報錯,提示:Name node is in safe mode。因為 Hadoop 集群啟動之后會進入短暫的安全模式,你需要等待一會才可以創(chuàng)建,關(guān)于安全模式一會單獨說。 client.write、client.read:往文件里面寫內(nèi)容、讀內(nèi)容
如果你在執(zhí)行的時候出現(xiàn)了連接錯誤,那么就在 hosts 文件中增加服務器IP到主機名的映射。 然后注意這里的 write 方法,如果不指定額外的參數(shù),那么要求文件不能存在,否則會報錯,提示文件已經(jīng)存在。如果要對已存在的文件進行操作,那么需要顯式的指定參數(shù):overwrite 或者 append,也就是重寫或追加,相當于 Python 文件操作的 w 模式和 r 模式。
client.content:查看目錄的匯總情況 比如:當前目錄下有多少個子目錄、多少文件等等。
client.set_owner:設(shè)置所有者 client.set_permission:設(shè)置權(quán)限 client.set_replication:設(shè)置副本系數(shù) client.set_times:設(shè)置時間
client.resolve: 將帶有符號的路徑,轉(zhuǎn)換成絕對、規(guī)范化路徑
client.walk:遞歸遍歷目錄
client.upload:上傳文件
client.download:下載文件
client.checksum:獲取文件的校驗和
client.delete:刪除文件或目錄
當然還有一些其它操作,比如重命名:client.rename 等等,這里就不說了。 HDFS元數(shù)據(jù)管理 再來聊聊 HDFS 的元數(shù)據(jù)管理,首先元數(shù)據(jù)包含:文件名、副本系數(shù)(或者說副本因子)、塊id、以及散落在哪個 DataNode 上。 因此 HDFS 的元數(shù)據(jù)也就是整個 HDFS 文件系統(tǒng)的層級結(jié)構(gòu),以及每個文件的 block 信息。 而這些元信息存在于 hadoop.tmp.dir 中,我們來看一下。 然后 current 目錄里面存放了很多的文件: 首先 NameNode 啟動之后,這些元數(shù)據(jù)會在內(nèi)存中,因此為了防止重啟之后丟失,肯定要定期寫入磁盤。圖中的 fs_image 文件便是寫入之后的結(jié)果,但寫入是定期寫入的,假設(shè)每隔半小時寫入一次。 如果 NameNode 宕掉,那么還是會丟失半小時的數(shù)據(jù),這也是我們所無法忍受的。因此就像 Redis 一樣,在緩存數(shù)據(jù)的同時還將執(zhí)行的命令操作緩存起來,記錄在 edits 文件中。edits 文件是時刻記錄的,因為記錄的只是命令而已。 然后根據(jù) edits 中的命令,和 fsimage 綜合起來,生成一個新的 fsimage,再把老的fsimage給替換掉,這樣就確保了元數(shù)據(jù)的不丟失。但要注意,這一步并不是交給 NameNode 來做的,因為它還要處理來自客戶端的請求,如果合并的工作再交給它,那么 NameNode 的壓力就太大了。 那么給誰做呢?沒錯,正是 SecondaryNameNode。所以 NameNode 和它并不是所謂的主備關(guān)系,后者相當于前者的小弟,主要是幫大哥減輕壓力的。
HDFS的安全模式 在 HDFS 剛啟動的時候,會進入到一種特殊的模式:安全模式,這是 Hadoop 的一種自我保護機制,用于保證集群中數(shù)據(jù)塊的安全性。比如:副本系數(shù)是 3,但是某個塊的數(shù)量是 2,這個時候就會再拷貝一份,滿足副本系數(shù)。 如果 HDFS 是在安全模式下的話,那么客戶端不能進行任何文件修改的操作,比如:上傳文件,刪除文件,重命名,創(chuàng)建目錄等操作。當然正常情況下,安全模式會運行一段時間自動退出的,只需要我們稍等一會就行了,到底等多長時間呢,我們可以通過 50070 端口查看安全模式退出的剩余時間。 我這里的安全模式是關(guān)閉的,如果你當前處于安全模式的話,那么頁面信息會提示你還需多長時間才能結(jié)束安全模式。在安全模式下,雖然不能進行修改文件的操作,但是可以瀏覽目錄結(jié)構(gòu)、查看文件內(nèi)容。 此外我們可以通過命令行,顯式地控制安全模式的進入、查看、以及退出等等。 安全模式是 Hadoop 的一種保護機制,在啟動時,最好是等待集群自動退出該模式,然后進行文件操作。有的小伙伴在和 Hive, Spark 整合的時候,剛一啟動 HDFS,就開始啟動 Hive, Spark 寫數(shù)據(jù),結(jié)果發(fā)現(xiàn)寫的時候報錯了,此時應該先等待集群退出安全模式。 分布式計算框架 MapReduce 下面來介紹一下 MapReduce,源自于 Google 在 2004 年 12 月發(fā)表的 MapReduce 技術(shù)論文,它的思想邏輯很簡單,完全可以看成是 Python 中 map 和 reduce 的組合。 另外 B 站上有一位 MIT 大佬的公開課,介紹分布式系統(tǒng)的,里面對 Google 設(shè)計 HDFS 和 MapReduce 的流程進行了闡述。強烈推薦去看一下,或者也可以讀一讀原版論文。 MapReduce 實際上就是 map 和 reduce 兩者的組合:
比如我們要做一個詞頻統(tǒng)計: MapReduce 就是將一個作業(yè)拆分成多份,在多個機器上并行處理,然后再將處理之后的結(jié)果匯總在一起。因此它非常適合海量數(shù)據(jù)的離線處理,不怕你的數(shù)據(jù)量大,PB, EB 都無所謂,只要你的節(jié)點數(shù)量足夠即可。并且內(nèi)部的細節(jié)我們不需要關(guān)心,只需按照它提供的 API 進行編程,我們便能得到結(jié)果。 并且當你的計算資源不足時,你可以通過簡單的增加機器來擴展計算能力。并且一個節(jié)點掛了,它可以把上面的計算任務轉(zhuǎn)移到另一個節(jié)點上運行,不至于這個任務完全失敗。而且這個過程不需要人工參與,是由 Hadoop 內(nèi)部完成的。 但是對比 Spark, Flink 等框架,MapReduce其實是比較雞肋的。官方說使用 MapReduce 易開發(fā)、易運行,只是相對于我們自己實現(xiàn)而言,而使用 Spark, Flink 進行處理要比使用 MapReduce 清蒸的多。 因為 MapReduce 有以下幾個缺點: 1)不擅長實時計算,無法像傳統(tǒng)的關(guān)系型數(shù)據(jù)庫那樣,可以在毫秒級或者秒級內(nèi)返回結(jié)果。 2)不擅長流式計算,流式計算輸入的數(shù)據(jù)是動態(tài)的,而 MapReduce 的數(shù)據(jù)必須是靜態(tài)的,不能動態(tài)變化。這是因為 MR 自身的設(shè)計特點決定了數(shù)據(jù)源必須是靜態(tài)的。 3)不擅長 DAG(有向無環(huán)圖)計算,多個程序之間存在依賴,后一個應用程序的輸入依賴于上一個程序的輸出。在這種情況,MR 不是不能做,而是使用后,每個 MR 作業(yè)的輸出結(jié)果都會寫入到磁盤,然后再從磁盤中讀取,進行下一個操作。顯然這樣做會造成大量的磁盤 IO,導致性能非常的低下。 關(guān)于 MR 的實際操作就不說了,事實上現(xiàn)在基本都不用 MR 編程了,我們有 Spark,它的出現(xiàn)解決了 MR 的效率低下問題。而且還有 Hive,Hive 也是我們后面要學習的一個重要的大數(shù)據(jù)組件,很多公司都在用,它是將 MR 進行了一個封裝,可以讓我們通過寫 SQL 的方式來操作 HDFS 上的數(shù)據(jù),這樣就方便多了。 但既然是寫 SQL,那么肯定要像傳統(tǒng)關(guān)系型數(shù)據(jù)庫一樣,有表名、字段名、字段信息等等。沒錯,這些信息在 Hive 中也叫作元信息、或者元數(shù)據(jù),它一般存在 MySQL 等關(guān)系型數(shù)據(jù)庫中,實際的數(shù)據(jù)依舊是存儲在 HDFS 上,相當于幫你做了一層映射關(guān)系。 關(guān)于 Hive 我們介紹的時候再說,總之它也是一個非常重要的大數(shù)據(jù)組件,畢竟使用 SQL 進行編程肯定要比 MR 簡單的多,而 Hive 也可以使用 Python 進行連接、執(zhí)行操作。 資源調(diào)度框架 YARN 下面我們來介紹一下資源調(diào)度框架 YARN,但是在介紹它之前我們需要先了解為什么會有 YARN,一項技術(shù)的誕生必然是有其原因的。 首先我們用的都是 Hadoop 2.x 或 3.x,但在 1.x 的時候 MR 的架構(gòu)是怎樣的呢?當然不管是哪個版本,MR 都是 master/slave 架構(gòu)。 HDFS 是一個 NameNode 帶多個 DataNode,形成主從架構(gòu),在 1.x 的 MR 中也是如此,一個 JobTracker 帶多個 TaskTracker。JobTracker 用來跟蹤一個作業(yè),而我們說一個作業(yè)可以被拆分成多個任務,每個任務對應一個 TaskTracker。 當然這里的拆分并不是將計算本身拆分,而是將文件拆分,舉個例子:我們有 100G 的文件,分別散落在 10 個節(jié)點上。我們要對這 100G 的文件執(zhí)行兩次 Map、一次 Reduce,那么結(jié)果就是每個節(jié)點分別對 10G 的數(shù)據(jù)執(zhí)行兩次 Map、一次 Reduce。 另外 TaskTracker 可以和 JobTracker 進行通信,并需要告訴 JobTracker 自己是否存活。所以客戶端 Client 提交作業(yè)是先提交到 JobTracker 上面,然后再由 TaskScheduler(任務調(diào)度器)將任務調(diào)度到 TaskTracker 上運行,比如:MapTask, ReduceTask。 此外 TaskTracker 會定期向 JobTracker 會報節(jié)點的健康狀況、任務的執(zhí)行狀況,以及資源的使用情況等等。 但這個架構(gòu)是存在問題的,因為只有一個 JobTracker,它要跟蹤所有的作業(yè)。如果 JobTracker 掛掉了怎么辦?要是掛掉了,那么客戶端的所有作業(yè)都無法提交到集群上運行了。 此外 JobTracker 要負責和 Client 進行通信,還要和 TaskTracker 進行通信,因此它的壓力會非常大。在后續(xù)集群的擴展時,JobTracker 很容易成為瓶頸。此外最關(guān)鍵的一點,在 Hadoop1.x 的時候,JobTracker 僅僅只能支持 MapReduce 作業(yè),想提交 Spark 作業(yè)是不可能的。 并且這種集群的資源利用率也很低,比如我們有 Hadoop 集群,Saprk 集群,不同的集群進行不同的資源分配。有可能 Hadoop 集群處于空閑狀態(tài),Spark 集群處于缺資源狀態(tài),導致它們沒辦法充分利用集群的資源。 而解決這一點的辦法就是,所有的計算框架都運行在一個集群中,共享一個集群的資源,做到按需分配。而想實現(xiàn)這一點,首先要滿足支持不同種類的作業(yè),所以 YARN 便誕生了。 什么是 YARN YARN(Yet Another Resource Manager,另一種資源管理器),是一個通用的資源管理系統(tǒng),為上層應用提供統(tǒng)一的資源管理和調(diào)度,所以 YARN 支持不同種類作業(yè)的調(diào)度。在介紹 Hadoop 生態(tài)圈的時候,我們貼了一張圖,在 HDFS 之上的就是 YARN。而在 YARN 之上可以運行各種作業(yè),像 MapReduce 作業(yè)、Spark 作業(yè)等等都可以,只需要提交到 YARN 上面就可以了 YARN 就類似于 1.x 里面的 JobTracker,但是它內(nèi)部包含了兩個部分:一個是資源管理,一個是作業(yè)調(diào)度或監(jiān)控,這是兩個單獨的進程。而在 1.x 當中,都是通過 JobTracker 來完成的,所以它壓力大。 所以基于這種架構(gòu),會有一個全局的 Resource Manager,每一個應用程序都有一個 Application Master,比如:MapReduce 作業(yè)會有一個 MapReduce 對應的 AM,Spark 作業(yè)會有一個 Spark 對應的 AM。而一個應用程序可以是一個獨立 MapReduce 作業(yè),也可以是多個作業(yè)組成的 DAG(有向無環(huán)圖,多個任務之間有依賴)。 我們說 Resource Manager 是全局的,但除了 RM 之外每個節(jié)點還有各自的 NodeManager。目前拋出的概念有點多,我們來慢慢介紹。 Resource Manager
Resource Manager
Application Master
Container
所以整體流程如下:
整個流程并沒有那么復雜,并且在運行過程中 AM 是知道每一個 Task 的運行情況的,這便是 MR 在 YARN 上的執(zhí)行流程。注意:不僅僅是 MapReduce,還有 Spark,它們除了 AM 不同之外,整體的執(zhí)行流程是沒有任何區(qū)別的。 YARN環(huán)境部署 Hadoop2.x 自帶 YARN,如果我們想啟動 YARN,還是要先修改配置文件。下面看看 YARN 的單節(jié)點部署。 修改 yarn-env.sh 和 hadoop-env.sh 一樣,配置 JAVA_HOME。 修改 yarn-site.xml
修改 mapred-env.sh 老規(guī)矩,遇到 -env.sh 都是配 JAVA_HOME。 修改 mapred-site.xml 你會發(fā)現(xiàn) hadoop 沒有提供這個文件,不過有一個 mapred-site.xml.template,我們可以拷貝一份。
修改完畢,下面啟動集群。 我們看到多出了兩個進程,分別是RM和AM,關(guān)于YARN我們還可以通過webUI的方式查看,端口是8088。 里面包含了很多關(guān)于節(jié)點的信息以及任務的信息,注意圖中的 Active Nodes,我們看到目前有一個節(jié)點存活。因此在運行任務的時候,可以多通過 webUI 的方式關(guān)注一下節(jié)點和任務的信息。 但如果你還想查看程序的歷史運行情況,那么還需要額外配置一個參數(shù),修改 mapred-site.xml。
最后是提交作業(yè)到 YARN 上運行,但這里我們就不說了,因為還是那句話,現(xiàn)在基本上很少直接使用 MR 進行編程了。在后續(xù)學習 Spark 的時候,我們會學習如何將作業(yè)提交到 YARN 上運行,至于 MapReduce 我們了解一下它的概念即可。 而 YARN,它是一個資源管理器,我們需要掌握它的整體架構(gòu),在未來學習 Spark 的時候依舊需要了解 YARN。所以到時候我們再說如何將作業(yè)提交到 YARN 上執(zhí)行吧。 小結(jié) 如果想走進大數(shù)據(jù)的大門,那么 Hadoop 是必須要了解的。在了解完 Hadoop 之后,下一個目標就是 Hive,因為使用 MapReduce 編程其實是很不方便的。而 Hive 則是可以讓我們像寫 SQL 一樣來進行 MapReduce 編程,并且很多公司都在使用 Hive 這個大數(shù)據(jù)組件,我們以后再介紹。 最后我這里搭建的 Hadoop 集群其實是個偽集群,你也可以多找?guī)讉€節(jié)點搭建一個完全分布式集群。當然在工作中,這一塊應該是由專業(yè)的大數(shù)據(jù)團隊負責,我們只需要了解它的原理以及使用即可。 |
|