2018年第22周-大數據的HDFS

Hadoop與大數據

Hadoop能夠說是大數據的代名詞。
其實準確來講是Hadoop家族是大數據的代名詞,家族成員有:Hadoop、Hive、Pig、HBase、Sqoop、Zookeeper、Avro、Chukwa等。家族成員每一個基本均可以獨擋一面,但結合他們,就能夠架構出一個大數據平臺。成員太多了,只能一個個的學,能夠先學習Zookeeper,再到Hadoop,再到Hive等。
Hadoop又包含兩部分:分別是HDFS和YARN。這篇文章將着重講解Hadoop的搭建和HDFS。java

Hadoop基本結構

clipboard.png

Hadoop搭建(HDFS部分)

使用Hadoop版本是hadoop-2.7.3.tar.gz
假設有6臺機器,分別是(角色以逗號分開):node

s1.jevoncode.com,zookeeper,namenode,zkfc,
s2.jevoncode.com,zookeeper,namenode,zkfc,
s3.jevoncode.com,zookeeper,
s4.jevoncode.com,datanode,journalnode,
s5.jevoncode.com,datanode,journalnode,
s6.jevoncode.com,datanode,journalnode,

它們之間需免密鑰登陸,這裏就略,可自行百度。我這裏提供關鍵命令:
1.在s1建立sshkeyshell

ssh-keygen

2.複製公鑰到s2apache

ssh-copy-id root@s2.jevoncode.com

搭建Zookeeper

只要涉及多臺機器協調服務,這就不得不安裝ZooKeeper了。
安裝過程出門左轉《2018年第16周-ZooKeeper基本概念(配搭建過程和Master-Workers例子)》
現假設咱們在s1,s2和s3安裝了ZooKeeper。編程

搭建Hadoop的HDFS

Hadoop的全部配置都在目錄:
1.配置hadoop-env.sh,設置JDK目錄和Hadoop目錄bootstrap

export JAVA_HOME=/opt/jdk1.8.0_172
export HADOOP_CONF_DIR=/usr/local/hadoop-2.7.3/etc/hadoops

2.配置core-site.xml,指定邏輯主機名、hadoop的數據目錄和ZooKeeper的地址segmentfault

<configuration>
    <!--用來指定hdfs的老大,ns爲固定屬性名,表示兩個namenode-->
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://ns</value>
    </property>
    <!--用來指定hadoop運行時產生文件的存放目錄-->
    <property>
        <name>hadoop.tmp.dir</name>
        <value>/usr/local/hadoopDataDir/tmp</value>
    </property>
    <!--執行zookeeper地址-->
    <property>
        <name>ha.zookeeper.quorum</name>
        <value>s1.jevoncode.com:2181,s2.c7.local.jevoncode.com:2181,s3.jevoncode.com:2181</value>
    </property>
</configuration>

3.配置hdfs-site.xml,配置邏輯主機名,namenode節點地址,journalnode節點地址,journalnode的數據目錄,指定故障轉移控制器,配置fencing,指定namenode和datanode的數據目錄,副本的個數,權限和節點之間的帶寬設置,安全

<configuration>
    <!--執行hdfs的nameservice爲ns,和core-site.xml保持一致-->
    <property>
        <name>dfs.nameservices</name>
        <value>ns</value>
    </property>
    <!--定義ns下有兩個namenode,分別是nn1,nn2,而後再具體定義n1和n2-->
    <property>
        <name>dfs.ha.namenodes.ns</name>
        <value>nn1,nn2</value>
    </property>
    <!--nn1的RPC通訊地址-->
    <property>
        <name>dfs.namenode.rpc-address.ns.nn1</name>
        <value>s1.jevoncode.com:9000</value>
    </property>
    <!--nn1的http通訊地址-->
    <property>
        <name>dfs.namenode.http-address.ns.nn1</name>
        <value>s1.jevoncode.com:50070</value>
    </property>
    <!--nn2的RPC通訊地址-->
    <property>
        <name>dfs.namenode.rpc-address.ns.nn2</name>
        <value>s2.jevoncode.com:9000</value>
    </property>
    <!--nn2的http通訊地址-->
    <property>
        <name>dfs.namenode.http-address.ns.nn2</name>
        <value>s2.jevoncode.com:50070</value>
    </property>

    <!--指定namenode的元數據在JournalNode上的存放位置,這樣,namenode2能夠從jn集羣裏獲取
         最新的namenode的信息,達到熱備的效果
         格式:qjournal://host1:port1;host2:port2;host3:port3/journalId  
         其中,journalId 是該命名空間的惟一 ID
     -->
    <property>
        <name>dfs.namenode.shared.edits.dir</name>
        <value>qjournal://s4.jevoncode.com:8485;s5.jevoncode.com:8485;s6.jevoncode.com:8485/ns</value>
    </property>
    <!--指定JournalNode存放數據的位置-->
    <property>
        <name>dfs.journalnode.edits.dir</name>
        <value>/usr/local/hadoopDataDir/journal</value>
    </property>

    <!--開啓namenode故障時自動切換-->
    <property>
        <name>dfs.ha.automatic-failover.enabled</name>
        <value>true</value>
    </property>
    <!--配置切換的實現方式-->
    <property>
        <name>dfs.client.failover.proxy.provider.ns</name>
        <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
    </property>
    <!--配置規避機制-->
    <property>
        <name>dfs.ha.fencing.methods</name>
        <value>sshfence</value>
    </property>
    <!--配置規避機制的ssh登陸祕鑰所在的位置,其餘用戶就指定用戶的sshkey,如/homg/jevoncode/.ssh/id_rsa-->
    <property>
        <name>dfs.ha.fencing.ssh.private-key-files</name>
        <value>/root/.ssh/id_rsa</value>
    </property>
 
    <!--配置namenode數據存放的位置,能夠不配置,若是不配置,默認用的是core-site.xml裏配置的hadoop.tmp.dir的路徑-->
    <property>
        <name>dfs.namenode.name.dir</name>
        <value>file:///usr/local/hadoopDataDir/namenode</value>
    </property>
    <!--配置datanode數據存放的位置,能夠不配置,若是不配置,默認用的是core-site.xml裏配置的hadoop.tmp.dir的路徑-->
    <property>
        <name>dfs.datanode.data.dir</name>
        <value>file:///usr/local/hadoopDataDir/datanode</value>
    </property>
 
    <!--配置block副本數量-->
    <property>
        <name>dfs.replication</name>
        <value>3</value>
    </property>
    <!--設置hdfs的操做權限,false表示任何用戶均可以在hdfs上操做文件-->
    <property>
        <name>dfs.permissions</name>
        <value>false</value>
    </property>

    <!-- 修改內網帶寬限制爲100MB,默認是10MB-->
    <property>
        <name>dfs.balance.bandwidthPerSec</name>
        <value>104857600</value>
    </property>
     
 
</configuration>

4.建立目錄/usr/local/hadoopDataDirbash

mkdir -p /usr/local/hadoopDataDir

5.配置/etc/profile網絡

export HADOOP_HOME=/usr/local/hadoop-2.7.3
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

6.在ZooKeeper建立高可用(HA)用的數據結點

hdfs zkfc -formatZK,這個指令的做用是在zookeeper集羣上生成ha

7.啓動journalnode服務,在s4,s5,s6節點執行命令:

hadoop-daemons.sh start journalnode

8.格式化namenode,在s1節點執行命令:

hadoop namenode -format

9.在s1啓動namenode:

hadoop-daemon.sh start namenode

10.在s2設置namenode狀態並啓動namenode

hdfs namenode  -bootstrapStandby
hadoop-daemon.sh start namenode

11.在s4,s5,s6節點啓動datanode服務:

hadoop-daemon.sh start datanode

12.在namenode節點s1,s2啓動故障轉移控制器

hadoop-daemon.sh start zkfc

13.現能夠查看node結點的啓動狀況

http://s1.jevoncode.com:50070/

因爲故障轉移控制器也只是將standby狀態的namenode替換爲active狀態,但以前的active namenode仍是會被kiil掉,而不是重啓,因此在兩個namenode節點都須要shell腳原本監聽進程,當進程關閉時自動拉起:
文件名: hdfs-monitor.sh

#!/bin/bash
while true; do
beginTime=`date +%Y%m%d%H%M%S`
echo $beginTime "monitor namenode"
procnum=`ps -ef|grep "namenode"|grep -v grep|wc -l`  
if [ $procnum -eq 0 ]; then
 echo "namenode is crash, restart up..."
 hadoop-daemon.sh start namenode
 echo "finish"
fi
sleep 30  
done

此腳本會每30秒檢查namenode進程是否還存在,不存在則自動拉起。
爲了保存這shell腳本的日誌,咱們建立目錄

mkdir /usr/local/monitor/namenode/
cp hdfs-monitor.sh /usr/local/monitor/namenode/

後臺執行hdfs-monitor.sh

nohup ./hdfs-monitor.sh &

HDFS

HDFS(Hadoop distributed filesystem),Hadoop分佈式文件系統。
熟悉操做系統,特別是須要熟悉Linux系統,搭建大數據平臺也是須要不少Linux知識的,能夠看鳥哥私房菜,個人基本都是從他那學的。熟悉操做系統都知道,操做系統有一塊是文件系統,文件系統封裝了操做磁盤的細節,每一個磁盤都有默認的數據塊大小,這是磁盤進行讀/寫的最小單位。因而咱們操做文件,就由文件系統映射到磁盤上對應的塊,這對用戶來講是無感知的。
一樣的,在大數據裏,一個機器是不可能裝下全部數據,哪怕能裝滿你的業務等數據,但磁盤的讀寫是個硬傷,1T硬盤,假設讀的數據傳輸速度爲100MB/s,讀完正磁盤的數據至少得花2.5個小時。因此假設咱們有個100個機器,每部機器存儲1%的數據,並行讀寫(都是順序讀),不到兩分鐘就能夠讀完全部數據。但僅使用1%的磁盤容量有點浪費,因而咱們能夠存儲多個數據集。因而經過網絡管理多臺機器存儲的文件的系統,稱爲分佈式文件系統(DFS)。
因此若是你熟悉Linux的文件系統,學起這個分佈式文件系統會沒那麼吃力。
此係統架構於網絡之上,勢必也引入網絡編程的複雜性。如文件系統的可以容忍節點故障且不丟失任何數據。爲了不數據丟失,最多見的作法是複製(replication) :系統保存數據的副本(replica),一旦系統發生故障,就可使用另外保存的副本。

HDFS的設計

HDFS以流式訪問數據的形式來存儲超大文件,運行於商業硬件集羣上。

  • 超大文件,指具備幾百M、幾百G甚至幾百TB大小的文件。
  • 流式訪問數據,在我認爲,應該就是順序訪問,與隨機訪問相對應。HDFS的構建思路:一次寫入,屢次讀寫。每次分析都將涉及該數據集的大部分數據甚至所有,所以讀取整個數據集的時間延遲 比 讀取第一條記錄的時間延遲更重要。
  • 商用硬件,Hadoop並不須要運行在昂貴且高可靠的硬件上。就是工業批量生產的廉價機子。HDFS的涉及可以在機子故障時,可以繼續運行且不讓用戶察覺到明顯的中斷。因此在前期機器規劃時,機子不用規劃太大,一個機子幾十T硬盤大小,幾十個邏輯核,那就不必了。我以爲隨便十幾核,幾T數據便可,關鍵是要能夠加機子,N個屌絲賽過一個高富帥。
  • 低時間延遲的數據訪問,要求低時間延遲數據訪問的應用,例如幾十毫秒響應的,不適合在HDFS上運行。HDFS重在數據量,而不是響應時間上,我在上一週文章就提到。HDFS是爲了高數據吞吐量應用設計的,這可能會以提升時間延遲做爲代價。固然這前提也是資源必定的狀況下,能夠試下加機子,惋惜暫時我尚未這個資源去嘗試。
  • 小量的小文件,因爲namenode將文件系統的元數據存儲在內存中,所以該文件系統所能存儲的文件總數受限於namenode的內存容量。根據經驗,每一個文件、目錄和數據塊的存儲信息大約站150字節。所以,HDFS默認數據塊大小是128M,若是你有100萬個文件(122T左右),每一個文件佔一個數據塊,至少須要300M內存。
  • 追加和不能修改,HDFS中的文件寫入只支持單個寫入者,並且寫操做老是以「追加」方式在文件末尾寫數據。不支持在文件的任意位置進行修改。這第二點說的的流式訪問數據是匹配起來的。

HDFS的架構

clipboard.png

namenode和datanode

HDFS集羣上的機子都運行兩個服務,分別是namenode和datanode,運行namnode服務的爲管理節點,運行datanode的是工做節點。通常是有一個active狀態的namenode、一個standby狀態的namenode和多個datanode。
namenode管理文件系統的命名空間。它維護這文件系統樹及整顆樹內全部的文件和目錄。這些信息以兩個文件形式永久保存在磁盤上:命名空間鏡像文件和編輯日誌文件。namnode也記錄着每一個文件中各個塊所在的數據節點信息,但它並不永久保存塊的位置信息,由於這些信息會在系統啓動時根據datanode給的信息重建。
datanode是文件系統的工做結點。它們提供存儲並檢索數據塊的功能(受客戶端或namenode調度),而且按期向namenode發送它們所存儲的塊的列表。
客戶端(client)表明用戶經過namenode和datanode交互來訪問整個文件系統。客戶端提供一個類型POSIX(可移植操做系統節目)的文件系統接口,所以用戶在編程時無需知道namenode和datanode也可實現其功能。

OJM(quorum journal manager)

若是namenode失效了(就是沒有Active狀態的namenode),那麼全部的客戶端,包括MapReduce做業,均沒法讀寫文件,由於namenode時惟一存儲原數據與文件到數據塊映射的地方。知道有新的namenode上線,Hadoop才能繼續往外提供服務。
若是想要從一個失效的namenode恢復,系統管理員得啓動一個擁有文件系統原數據副本的新的namenode,並配置datanode和客戶端以便使用這個新的namenode,這個新的namenode只有知足如下情形才能響應服務:
1.將命名空間的映像導入內存中;
2.重演編輯日誌;
3.接收到足夠多的來自datanode1數據塊報告並退出安全模式。
對於一個大型,並擁有大量文件和數據塊的集羣,namenode的冷啓動須要30分鐘,甚至更長時間。
Hadoop2針對上述問題,增長了對HDFS高可用用(HA)的支持。在這一個視線中,引入了一對活動-備用(active-standby)的namenode。架構上作了如下修改:

  • namenode之間須要經過高可用共享存儲實現編輯日誌的共享。當standby namenode接管工做後,它將通讀共享編輯日誌直至末尾,以實現與active namenode的狀態同步,並繼續讀取由活動namenode寫入的新條目。
  • datanode須要同時向兩個namenode發送數據塊處理報告,由於數據塊的映射信息存儲在namenode的內存中,而非磁盤。
  • 客戶端須要使用特定的機制來處理namenode的失效問題,這一機制對用戶是透明的。這個能夠從hdfs-site.xml配置的屬性dfs.nameservices看出來,不會指定特定某個namenode,而是設置爲一組,經過組名去訪問,這一過程Hadoop就會選擇Active狀態的namenode來交互。
  • standby namenode爲active namenode命令空間設置週期性檢查點。

高可用共享存儲有兩種選擇:NFS過濾器或羣體日誌管理器(QJM,quorum journal manager)。
QJM是一個專用的HDFS實現,爲提供一個高可用的編輯日誌而設計,被推薦用於大多數據HDFS部署中。
QJM以一組日誌節點(journalnode)的形式運行,每一次編輯必須寫入多數journalnode中。在本篇文章中的部署,就是使用三個journalnode,因此係統可以容忍其中任何一個的損失。這種安排與ZooKeeper的工做方式相似,但並無用Zookeeper。
QJM在同一時間僅容許一個namenode向編輯日誌中寫入數據。

QJM理解

首先,Hadoop不是隻有namenode和datanode,做爲商用,就必須高可用,因而有了QJM。
其次,QJM雖然沒有用Zookeeper實現,但QJM也只Hadoop高可用實現的一部分(高可用共享存儲的一個選擇),還要有選取新的namenode做爲active namenode這個實現,也就是後續要將的zkfc,它是基於Zookeeper的實現。

zkfc(ZooKeeper Failover Controller)

除了上述描述的QJM,做爲高可用,還須要可以選取新的namenode做爲active namenode。這個選取過程稱爲故障轉移。Hadoop有一個稱爲故障轉移控制器(failover controller),管理着將namenode之間的active和standby狀態,在兩個都是standby狀態的namenode時,failover controller會將其中一個namenode狀態爲active,因此若是你沒有啓動故障轉移控制,會發現兩個namenode都是standby,整個HDFS都沒法使用。
轉移控制器有不少實現方式,但默認一種是使用了ZooKeeper來確保有且僅有一個active namenode。每一個namenode節點都運行着一個輕量級的故障轉移控制器,其工做做用就是監視宿主namenode是否失效(經過一個簡單的心跳機制實現)並在namenode失效時進行故障切換。

在本篇文章中的部署過程,hadoop-daemon.sh start zkfc 就是啓動故障轉移控制器。用jps命令就能看到java進程名爲DFSZKFailoverController。

因爲沒法確切知道失效的namenode是否已經中止運行。Hadoop提供了方法「規避(fencing)」來確保先前active namenode不會執行危害系統並致使系統崩潰的操做。這個fencing是這樣配置的:

<property>
        <name>dfs.ha.fencing.methods</name>
        <value>sshfence(jevoncode:10034)</value>
    </property>

當active namenode崩潰時,standby namenode會先根據上面的配置,經過ssh確認active namenode已經關閉(強制關閉,kill),而後再將自己狀態至爲active。
客戶端的故障轉移經過客戶端類庫實現透明處理。HDFS URI使用一個邏輯主機名,該邏輯主機名映射到一對namenode地址,客戶端類庫會根據這個配置訪問每個naemnode,直到完成請求。這配置是dfs.nameservices,以下:

<!--執行hdfs的nameservice爲ns,和core-site.xml保持一致-->
    <property>
        <name>dfs.nameservices</name>
        <value>ns</value>
    </property>
    <!--定義ns下有兩個namenode,分別是nn1,nn2,而後再具體定義n1和n2-->
    <property>
        <name>dfs.ha.namenodes.ns</name>
        <value>nn1,nn2</value>
    </property>
    <!--nn1的RPC通訊地址-->
    <property>
        <name>dfs.namenode.rpc-address.ns.nn1</name>
        <value>s1.jevoncode.com:9000</value>
    </property>
    <!--nn1的http通訊地址-->
    <property>
        <name>dfs.namenode.http-address.ns.nn1</name>
        <value>s1.jevoncode.com:50070</value>
    </property>
    <!--nn2的RPC通訊地址-->
    <property>
        <name>dfs.namenode.rpc-address.ns.nn2</name>
        <value>s2.jevoncode.com:9000</value>
    </property>
    <!--nn2的http通訊地址-->
    <property>
        <name>dfs.namenode.http-address.ns.nn2</name>
        <value>s2.jevoncode.com:50070</value>
    </property>
相關文章
相關標籤/搜索