看到題目有沒有一種高大上的感覺?
毛線,當前是個人、是個公司都在說自己搞大數據,每天沒有幾個PB的數據入庫,每天沒有幾個TB的分析數據產出敢說自己是大數據?
乘著大數據噱頭之風,我們還是要看一下大數據所運用的工具對于我們是否有用,小編之前寫項目時一直青睞于mysql,進來發現新的項目mysql已經無法適應,我們目前日數據產生量在10W級別時,mysql的查詢速度和穩定性的確出現了問題,借鑒當前分布式數據庫的經驗,我們決定采用Hbase集群,Hadoop作為hbase的基礎,被提到首要位置做研究。
我們首先看看hadoop的發展歷史和主要架構:
Hadoop歷史
雛形開始于2002年的Apache的Nutch,Nutch是一個開源Java 實現的搜索引擎。它提供了我們運行自己的搜索引擎所需的全部工具。包括全文搜索和Web爬蟲。
隨后在2003年Google發表了一篇技術學術論文谷歌文件系統(GFS)。GFS也就是google File System,google公司為了存儲海量搜索數據而設計的專用文件系統。
2004年Nutch創始人Doug Cutting基于Google的GFS論文實現了分布式文件存儲系統名為NDFS。
2004年Google又發表了一篇技術學術論文MapReduce。MapReduce是一種編程模型,用于大規模數據集(大于1TB)的并行分析運算。
2005年Doug Cutting又基于MapReduce,在Nutch搜索引擎實現了該功能。
2006年,Yahoo雇用了Doug Cutting,Doug Cutting將NDFS和MapReduce升級命名為Hadoop,Yahoo開建了一個獨立的團隊給Goug Cutting專門研究發展Hadoop。
不得不說Google和Yahoo對Hadoop的貢獻功不可沒。
Hadoop核心
Hadoop的核心就是HDFS和MapReduce,而兩者只是理論基礎,不是具體可使用的高級應用,Hadoop旗下有很多經典子項目,比如HBase、Hive等,這些都是基于HDFS和MapReduce發展出來的。要想了解Hadoop,就必須知道HDFS和MapReduce是什么。
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做的事了。
下面以一個計算海量數據最大值為例:一個銀行有上億儲戶,銀行希望找到存儲金額最高的金額是多少,按照傳統的計算方式,我們會這樣:
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
export PATH=$PATH:$JAVA_HOME/bin
保存退出,然后輸入 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上:
scp .ssh/id_rsa.pub hadoop@master:/home/hadoop/id_rsa_01.pub
slave02上:
scp .ssh/id_rsa.pub hadoop@master:/home/hadoop/id_rsa_02.pub
這二行執行完后,回到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目錄位置,大家根據實際情況修改)
export JAVA_HOME=/usr/java/jdk1.7.0_51
另外 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>
6 <value>hdfs://master:9000</value>
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的完整參數請參考
http://hadoop.apache.org/docs/r2.6.0/hadoop-project-dist/hadoop-common/core-default.xml
c) hdfs-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>dfs.datanode.ipc.address</name>
6 <value>0.0.0.0:50020</value>
7 </property>
8 <property>
9 <name>dfs.datanode.http.address</name>
10 <value>0.0.0.0:50075</value>
11 </property>
12 <property>
13 <name>dfs.replication</name>
14 <value>2</value>
15 </property>
16 </configuration>
注:dfs.replication表示數據副本數,一般不大于datanode的節點數。
hdfs-site.xml的完整參數請參考
http://hadoop.apache.org/docs/r2.6.0/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml
d) mapred-site.xml
1 <?xml version="1.0"?>
2 <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
3 <configuration>
4 <property>
5 <name>mapreduce.framework.name</name>
6 <value>yarn</value>
7 </property>
8 </configuration>
mapred-site.xml的完整參數請參考
e)yarn-site.xml
1 <?xml version="1.0"?>
2 <configuration>
3 <property>
4 <name>yarn.nodemanager.aux-services</name>
5 <value>mapreduce_shuffle</value>
6 </property>
7 </configuration>
yarn-site.xml的完整參數請參考
http://hadoop.apache.org/docs/r2.6.0/hadoop-yarn/hadoop-yarn-common/yarn-default.xml
另外,hadoop 1.x與2.x相比, 1.x中的很多參數已經被標識為過時,具體可參考
http://hadoop.apache.org/docs/r2.6.0/hadoop-project-dist/hadoop-common/DeprecatedProperties.html
最后一個文件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查看進程
5161 SecondaryNameNode
5320 ResourceManager
4989 NameNode
如果看到這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-dfs.sh
$HADOOP_HOME/sbin/start-yarn.sh
順利的話,master節點上有幾下3個進程:
7482 ResourceManager
7335 SecondaryNameNode
7159 NameNode
slave01、slave02上有幾下2個進程:
2296 DataNode
2398 NodeManager
同時可瀏覽:
查看狀態
另外也可以通過 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 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:$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