看到題目有沒有一種高大上的感覺?
毛線,目前是個人、是個公司都在說自己搞大資料,每天沒有幾個PB的資料入庫,每天沒有幾個TB的分析資料産出敢說自己是大資料?
乘着大資料噱頭之風,我們還是要看一下大資料所運用的工具對于我們是否有用,小編之前寫項目時一直青睐于mysql,進來發現新的項目mysql已經無法适應,我們目前日資料産生量在10W級别時,mysql的查詢速度和穩定性的确出現了問題,借鑒目前分布式資料庫的經驗,我們決定采用Hbase叢集,Hadoop作為hbase的基礎,被提到首要位置做研究。
我們首先看看hadoop的發展曆史和主要架構:
Hadoop曆史
Hadoop核心
HDFS
HDFS(Hadoop Distributed File System,Hadoop分布式檔案系統),它是一個高度容錯性的系統,适合部署在廉價的機器上。HDFS能提供高吞吐量的資料通路,适合那些有着超大資料集(large data set)的應用程式。
HDFS的設計特點是:
1、大資料檔案,非常适合上T級别的大檔案或者一堆大資料檔案的存儲,如果檔案隻有幾個G甚至更小就沒啥意思了。
2、檔案分塊存儲,HDFS會将一個完整的大檔案平均分塊存儲到不同電腦上,它的意義在于讀取檔案時可以同時從多個主機取不同區塊的檔案,多主機讀取比單主機讀取效率要高得多得都。
3、流式資料通路,一次寫入多次讀寫,這種模式跟傳統檔案不同,它不支援動态改變檔案内容,而是要求讓檔案一次寫入就不做變化,要變化也隻能在檔案末添加内容。
4、廉價硬體,HDFS可以應用在普通PC機上,這種機制能夠讓給一些公司用幾十台廉價的計算機就可以撐起一個大資料叢集。
5、硬體故障,HDFS認為所有計算機都可能會出問題,為了防止某個主機失效讀取不到該主機的塊檔案,它将同一個檔案塊副本配置設定到其它某幾個主機上,如果其中一台主機失效,可以迅速找另一塊副本取檔案。
HDFS的關鍵元素:
Block:将一個檔案進行分塊,通常是64M。
NameNode:儲存整個檔案系統的目錄資訊、檔案資訊及分塊資訊,這是由唯一一台主機專門儲存,當然這台主機如果出錯,NameNode就失效了。在Hadoop2.*開始支援activity-standy模式----如果主NameNode失效,啟動備用主機運作NameNode。
DataNode:分布在廉價的計算機上,用于存儲Block塊檔案。
MapReduce
通俗說MapReduce是一套從海量·源資料提取分析元素最後傳回結果集的程式設計模型,将檔案分布式存儲到硬碟是第一步,而從海量資料中提取分析我們需要的内容就是MapReduce做的事了。
下面以一個計算海量資料最大值為例:一個銀行有上億儲戶,銀行希望找到存儲金額最高的金額是多少,按照傳統的計算方式,我們會這樣:
Java代碼
收藏代碼
Long moneys[] ...
Long max = 0L;
for(int i=0;i<moneys.length;i++){
if(moneys[i]>max){
max = moneys[i];
}
如果計算的數組長度少的話,這樣實作是不會有問題的,還是面對海量資料的時候就會有問題。
MapReduce會這樣做:首先數字是分布存儲在不同塊中的,以某幾個塊為一個Map,計算出Map中最大的值,然後将每個Map中的最大值做Reduce操作,Reduce再取最大值給使用者。
MapReduce的基本原理就是:将大的資料分析分成小塊逐個分析,最後再将提取出來的資料彙總分析,最終獲得我們想要的内容。當然怎麼分塊分析,怎麼做Reduce操作非常複雜,Hadoop已經提供了資料分析的實作,我們隻需要編寫簡單的需求指令即可達成我們想要的資料。
hadoop架構
Hadoop使用主/從(Master/Slave)架構,主要角色有NameNode,DataNode,secondary NameNode,JobTracker,TaskTracker組成。
其中NameNode,secondary NameNode,JobTracker運作在Master節點上,DataNode和TaskTracker運作在Slave節點上。
1,NameNode
NameNode是HDFS的守護程式,負責記錄檔案是如何分割成資料塊的,以及這些資料塊被存儲到哪些資料節點上。它的功能是對記憶體及I/O進行集中管理。
2,DataNode
叢集中每個從伺服器都運作一個DataNode背景程式,背景程式負責把HDFS資料塊讀寫到本地檔案系統。需要讀寫資料時,由NameNode告訴用戶端去哪個DataNode進行具體的讀寫操作。
3,Secondary NameNode
Secondary NameNode是一個用來監控HDFS狀态的輔助背景程式,如果NameNode發生問題,可以使用Secondary NameNode作為備用的NameNode。
4,JobTracker
JobTracker背景程式用來連接配接應用程式與Hadoop,使用者應用送出到叢集後,由JobTracker決定哪個檔案處理哪個task執行,一旦某個task失敗,JobTracker會自動開啟這個task。
5,TaskTracker
TaskTracker負責存儲資料的DataNode相結合,位于從節點,負責各自的task。
hadoop搭建方法:
我們接下來就看一下hadoop 2.6全分布安裝是怎麼完成的:
環境:centos 6.6 + hadoop2.6
虛拟機:(vmware fusion 7.0.0)
虛拟機hostname / IP位址
master / 192.168.187.102
slave01 / 192.168.187.103
slave02 / 192.168.187.104
注:前三個步驟都是準備工作,如果已經完成,可直接進入步驟四
步驟一: 先在3台虛拟機上,設定hostname及修改hosts檔案
1.1 先正确設定各虛拟機的hostname
sudo vi /etc/sysconfig/network
将HOSTNAME=後的内容,改成想要的機器名
1.2 修改hosts檔案
sudo vi /etc/hosts
192.168.187.102 master
192.168.187.103 slave01
192.168.187.104 slave02
這樣,就不用記IP了
這一步完成後,最好重新開機一次系統,以便生效。然後可以用ping master(或slave01、slave02)試下,正常的話,應該能ping通
注:hostname不要命名為“xxx.01,xxx.02”之類以“.數字”結尾,否則到最後hadoop的NameNode服務将啟動失敗。
步驟二:在3台虛拟機上安裝jdk
yum install java
注:hadoop是java寫的,jdk是必須的。上述指令,會安裝openjdk最基本的運作時,沒有源碼和javac等其它工具。如果要安裝javac等編譯工具及源碼
yum install java-1.7.0-openjdk-devel
yum install java-1.7.0-openjdk-src
另外openjdk安裝後,不會默許設定JAVA_HOME環境變量,要檢視安裝後的目錄,可以用指令
sudo update-alternatives --config java 看到
預設jre目錄為:/usr/lib/java/jvm/jre-1.7.0-openjdk.x86_64
如要設定環境變量,可用指令 sudo vi /etc/profile
在最後添加
export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.75.x86_64
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/jre/lib/dt.jar:$JAVA_HOME/jre/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin
注:如果不喜歡openjdk,想安裝oracle官方的jdk,可按下面步驟操作
a) rpm -qa | grep java
即:檢視目前已經安裝的跟java相關的包,如果顯示有openjdk在其中
b) yum -y remove java
一般這樣就會解除安裝幹淨,執行完以後,再運作 a)中的rpm -qa | grep java看看,如果還有殘留,可運作
rpm -e --nodeps tzdata-java-2015a-1.el6.noarch (最後的部分為要删除的包名,即剛才查出來的結果)
重新安裝sun jdk,先從官網下載下傳安裝檔案
a) 上傳rpm安裝檔案到虛拟機,參考下面的指令
scp jdk-7u51-linux-x64.rpm root@master:/home/hadoop/
b) 到虛拟機上,執行安裝
rpm -ivh jdk-7u51-linux-x64.rpm
c) 然後修改環境變量 sudo vi /etc/profile,在最後加下面三行
export JAVA_HOME=/usr/java/jdk1.7.0_51
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
儲存退出,然後輸入 source /etc/profile 以便讓新環境變量生效
注:如果機器上之前用 yum install hadoop之類的指令安裝過低版本的hadoop,也必須先解除安裝幹淨
步驟三:在3台虛拟機上建立專門使用者hadoop
useradd hadoop (建立使用者)
passwd hadoop (設定密碼,為簡單起見,3台機器上的hadoop密碼最好設定成一樣,比如hadoop123)
為了友善,建議将hadoop加入root使用者組,操作方法:
先以root身份登入,然後輸入
usermod -g root hadoop ,執行完後hadoop即歸屬于root組了,可以再輸入
id hadoop 檢視輸出驗證一下,如果看到類似下面的輸出:
uid=502(hadoop) gid=0(root) 組=0(root)
就表示OK了
步驟四:配置ssh免密碼登入
hadoop工作時,各節點要互相通訊,正常情況下linux之間通訊要提供使用者名、密碼(目的是保證通訊安全),如果需要人工幹預輸入密碼,顯然不友善,做這一步的目的,是讓各節點能自動通過安全認證,不影響正常通訊。
4.1 先在master上,生成公鑰、私鑰對
以hadoop身份登入到系統
cd (進入個人主目錄,預設為/home/hadoop)
ssh-keygen -t rsa -P '' (注:最後是二個單引号)
即:以rsa算法,生成公鑰、私鑰對,-P ''表示空密碼。該指令運作完後,會在個人主目錄下生成.ssh目錄,裡面會有二個檔案id_rsa(私鑰) ,id_rsa.pub(公鑰)
4.2 導入公鑰
cat .ssh/id_rsa.pub >> .ssh/authorized_keys
執行完以後,可以在本機上測試下,用ssh連接配接自己,即:ssh localhost (或ssh master),如果不幸還是提示要輸入密碼,說明還沒起作用,還有一個關鍵的操作
chmod 600 .ssh/authorized_keys (修改檔案權限,否則不起作用)
然後再測試下 ssh localhost ,如果不需要輸入密碼,就連接配接成功,表示ok,一台機器已經搞定了。
4.3 在其它機器上生成公鑰、密鑰,并将公鑰檔案複制到master
a) 以hadoop身份登入其它二台機器 slave01、slave02,執行 ssh-keygen -t rsa -P '' 生成公鑰、密鑰
b) 然後用scp指令,把公鑰檔案發放給master(即:剛才已經搞定的那台機器)
slave01上:
slave02上:
這二行執行完後,回到master中,檢視下/home/hadoop目錄,應該有二個新檔案id_rsa_01.pub、id_rsa_02.pub,然後在master上,導入這二個公鑰
cat id_rsa_01.pub >> .ssh/authorized_keys
cat id_rsa_02.pub >> .ssh/authorized_keys
這樣,master這台機器上,就有所有3台機器的公鑰了。
4.4 将master上的“最全”公鑰,複制到其它機器
a) 繼續保持在master上,
scp .ssh/authorized_keys hadoop@slave01:/home/hadoop/.ssh/authorized_keys
scp .ssh/authorized_keys hadoop@slave02:/home/hadoop/.ssh/authorized_keys
b) 修改其它機器上authorized_keys檔案的權限
slave01以及slave02機器上,均執行指令
chmod 600 .ssh/authorized_keys
4.5 驗證
在每個虛拟機上,均用 ssh 其它機器的hostname 驗證下,如果能正常無密碼連接配接成功,表示ok
小結:該步驟非常重要,主要思路是在各節點上生成公鑰、私鑰,然後将公鑰發放其它所有節點。RSA算法是非對稱加密算法,僅公布“公鑰”,隻要私鑰不外洩,還是不能解密的,是以安全性依然有保障。
如果本步驟失敗,根據我個人經驗,多半是權限問題,請檢查hadoop是否具有足夠權限,建議将hadoop加入sudoers清單及root使用者組。另外,這裡也整理了一些SSH免密碼設定失敗的原因,請移步 ssh 免密碼設定失敗原因總結
步驟五:上傳并解壓hadoop2.6
a)在本機上,用scp指令上傳hadoop2.6到master
scp hadoop-2.6.0.tar.gz hadoop@master:/home/hadoop/
b) 以hadoop身份登入到master,運作以下指令解壓
tar -zxvf hadoop-2.6.0.tar.gz
步驟六:修改配置
一共有7個檔案要修改:
$HADOOP_HOME/etc/hadoop/hadoop-env.sh
$HADOOP_HOME/etc/hadoop/yarn-env.sh
$HADOOP_HOME/etc/hadoop/core-site.xml
$HADOOP_HOME/etc/hadoop/hdfs-site.xml
$HADOOP_HOME/etc/hadoop/mapred-site.xml
$HADOOP_HOME/etc/hadoop/yarn-site.xml
$HADOOP_HOME/etc/hadoop/slaves
其中$HADOOP_HOME表示hadoop根目錄,本文中預設為/home/hadoop/hadoop-2.6.0
a) hadoop-env.sh 、yarn-env.sh
這二個檔案主要是修改JAVA_HOME後的目錄,改成實際本機jdk所在目錄位置
vi etc/hadoop/hadoop-env.sh (及 vi etc/hadoop/yarn-env.sh)
找到下面這行的位置,改成(jdk目錄位置,大家根據實際情況修改)
另外 hadoop-env.sh中 , 建議加上這句:
export HADOOP_PREFIX=/home/hadoop/hadoop-2.6.0
b) core-site.xml 參考下面的内容修改:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
3 <configuration>
4 <property>
5 <name>fs.defaultFS</name>
7 </property>
8 <property>
9 <name>hadoop.tmp.dir</name>
10 <value>/home/hadoop/tmp</value>
11 </property>
12 </configuration>
注:/home/hadoop/tmp 目錄如不存在,則先mkdir手動建立
core-site.xml的完整參數請參考
<a href="https://link.jianshu.com?t=http://hadoop.apache.org/docs/r2.6.0/hadoop-project-dist/hadoop-common/core-default.xml" target="_blank">http://hadoop.apache.org/docs/r2.6.0/hadoop-project-dist/hadoop-common/core-default.xml</a>
c) hdfs-site.xml
5 <name>dfs.datanode.ipc.address</name>
6 <value>0.0.0.0:50020</value>
9 <name>dfs.datanode.http.address</name>
10 <value>0.0.0.0:50075</value>
12 <property>
13 <name>dfs.replication</name>
14 <value>2</value>
15 </property>
16 </configuration>
注:dfs.replication表示資料副本數,一般不大于datanode的節點數。
hdfs-site.xml的完整參數請參考
<a href="https://link.jianshu.com?t=http://hadoop.apache.org/docs/r2.6.0/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml" target="_blank">http://hadoop.apache.org/docs/r2.6.0/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml</a>
d) mapred-site.xml
1 <?xml version="1.0"?>
5 <name>mapreduce.framework.name</name>
6 <value>yarn</value>
8 </configuration>
mapred-site.xml的完整參數請參考
<a href="https://link.jianshu.com?t=http://hadoop.apache.org/docs/r2.6.0/hadoop-mapreduce-client/hadoop-mapreduce-client-core/mapred-default.xml" target="_blank">http://hadoop.apache.org/docs/r2.6.0/hadoop-mapreduce-client/hadoop-mapreduce-client-core/mapred-default.xml</a>
e)yarn-site.xml
2 <configuration>
3 <property>
4 <name>yarn.nodemanager.aux-services</name>
5 <value>mapreduce_shuffle</value>
6 </property>
7 </configuration>
yarn-site.xml的完整參數請參考
<a href="https://link.jianshu.com?t=http://hadoop.apache.org/docs/r2.6.0/hadoop-yarn/hadoop-yarn-common/yarn-default.xml" target="_blank">http://hadoop.apache.org/docs/r2.6.0/hadoop-yarn/hadoop-yarn-common/yarn-default.xml</a>
另外,hadoop 1.x與2.x相比, 1.x中的很多參數已經被辨別為過時,具體可參考
<a href="https://link.jianshu.com?t=http://hadoop.apache.org/docs/r2.6.0/hadoop-project-dist/hadoop-common/DeprecatedProperties.html" target="_blank">http://hadoop.apache.org/docs/r2.6.0/hadoop-project-dist/hadoop-common/DeprecatedProperties.html</a>
最後一個檔案slaves暫時不管(可以先用mv slaves slaves.bak 将它改名),上述配置弄好後,就可以在master上啟用 NameNode測試了,方法:
$HADOOP_HOME/bin/hdfs namenode –format 先格式化
15/02/12 21:29:53 INFO namenode.FSImage: Allocated new BlockPoolId: BP-85825581-192.168.187.102-1423747793784
15/02/12 21:29:53 INFO common.Storage: Storage directory /home/hadoop/tmp/dfs/name has been successfullyformatted.
等看到這個時,表示格式化ok
$HADOOP_HOME/sbin/start-dfs.sh
啟動完成後,輸入jps檢視程序,如果看到以下二個程序:
5161 SecondaryNameNode
4989 NameNode
表示master節點基本ok了
再輸入$HADOOP_HOME/sbin/start-yarn.sh ,完成後,再輸入jps檢視程序
5320 ResourceManager
如果看到這3個程序,表示yarn也ok了
f) 修改slaves
如果剛才用mv slaves slaves.bak對該檔案重命名過,先運作 mv slaves.bak slaves 把名字改回來,再
vi slaves 編輯該檔案,輸入
slave01
slave02
儲存退出,最後運作
$HADOOP_HOME/sbin/stop-dfs.sh
$HADOOP_HOME/sbin/stop-yarn.sh
停掉剛才啟動的服務
步驟七:将master上的hadoop目錄複制到slave01,slave02
仍然保持在master機器上
cd 先進入主目錄
scp -r hadoop-2.6.0 hadoop@slave01:/home/hadoop/
scp -r hadoop-2.6.0 hadoop@slave02:/home/hadoop/
注:slave01、slave02上的hadoop臨時目錄(tmp)及資料目錄(data),仍然要先手動建立。
步驟八:驗證
master節點上,重新啟動
$HADOOP_HOME/sbin/start-yarn.sh
順利的話,master節點上有幾下3個程序:
7482 ResourceManager
7335 SecondaryNameNode
7159 NameNode
slave01、slave02上有幾下2個程序:
2296 DataNode
2398 NodeManager
同時可浏覽:
<a href="https://link.jianshu.com?t=http://master:50070/" target="_blank">http://master:50070/</a>
<a href="https://link.jianshu.com?t=http://master:8088/" target="_blank">http://master:8088/</a>
檢視狀态
另外也可以通過 bin/hdfs dfsadmin -report 檢視hdfs的狀态報告
其它注意事項:
a) master(即:namenode節點)若要重新格式化,請先清空各datanode上的data目錄(最好連tmp目錄也一起清空),否則格式化完成後,啟動dfs時,datanode會啟動失敗
b) 如果覺得master機器上隻運作namenode比較浪費,想把master也當成一個datanode,直接在slaves檔案裡,添加一行master即可
c) 為了友善操作,可修改/etc/profile,把hadoop所需的lib目錄,先加到CLASSPATH環境變量中,同時把hadoop/bin,hadoop/sbin目錄也加入到PATH變量中,可參考下面的内容:
export HADOOP_HOME=/home/hadoop/hadoop-2.6.0
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$HADOOP_HOME/share/hadoop/common/hadoop-common-2.6.0.jar:$HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-client-core-2.6.0.jar:$HADOOP_HOME/share/hadoop/common/lib/commons-cli-1.2.jar
export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/sbin:$HADOOP_HOME/bin