Hadoop学习总结
生活随笔
收集整理的這篇文章主要介紹了
Hadoop学习总结
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
初識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做的事了。
?
下面以一個計算海量數據最大值為例:一個銀行有上億儲戶,銀行希望找到存儲金額最高的金額是多少,按照傳統的計算方式,我們會這樣:
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適合應用于大數據存儲和大數據分析的應用,適合于服務器幾千臺到幾萬臺的集群運行,支持PB級的存儲容量。
? ? ? ? Hadoop典型應用有:搜索、日志處理、推薦系統、數據分析、視頻圖像分析、數據保存等。
? ? ? ? 但要知道,Hadoop的使用范圍遠小于SQL或Python之類的腳本語言,所以不要盲目使用Hadoop,看完這篇試讀文章,我知道Hadoop不適用于我們的項目。
========
Hadoop快速入門
目的
先決條件
支持平臺
所需軟件
安裝軟件
下載
運行Hadoop集群的準備工作
單機模式的操作方法
偽分布式模式的操作方法
配置
免密碼ssh設置
執行
完全分布式模式的操作方法
目的
這篇文檔的目的是幫助你快速完成單機上的Hadoop安裝與使用以便你對Hadoop分布式文件系統(HDFS)和Map-Reduce框架有所體會,比如在HDFS上運行示例程序或簡單作業等。
先決條件
支持平臺
GNU/Linux是產品開發和運行的平臺。 Hadoop已在有2000個節點的GNU/Linux主機組成的集群系統上得到驗證。
Win32平臺是作為開發平臺支持的。由于分布式操作尚未在Win32平臺上充分測試,所以還不作為一個生產平臺被支持。
所需軟件
Linux和Windows所需軟件包括:
JavaTM1.5.x,必須安裝,建議選擇Sun公司發行的Java版本。
ssh 必須安裝并且保證 sshd一直運行,以便用Hadoop 腳本管理遠端Hadoop守護進程。
Windows下的附加軟件需求
Cygwin - 提供上述軟件之外的shell支持。
安裝軟件
如果你的集群尚未安裝所需軟件,你得首先安裝它們。
以Ubuntu Linux為例:
$ sudo apt-get install ssh?
$ sudo apt-get install rsync
在Windows平臺上,如果安裝cygwin時未安裝全部所需軟件,則需啟動cyqwin安裝管理器安裝如下軟件包:
openssh - Net 類
下載
為了獲取Hadoop的發行版,從Apache的某個鏡像服務器上下載最近的 穩定發行版。
運行Hadoop集群的準備工作
解壓所下載的Hadoop發行版。編輯 conf/hadoop-env.sh文件,至少需要將JAVA_HOME設置為Java安裝根路徑。
嘗試如下命令:
$ bin/hadoop?
將會顯示hadoop 腳本的使用文檔。
現在你可以用以下三種支持的模式中的一種啟動Hadoop集群:
單機模式
偽分布式模式
完全分布式模式
單機模式的操作方法
默認情況下,Hadoop被配置成以非分布式模式運行的一個獨立Java進程。這對調試非常有幫助。
下面的實例將已解壓的 conf 目錄拷貝作為輸入,查找并顯示匹配給定正則表達式的條目。輸出寫入到指定的output目錄。?
$ mkdir input?
$ cp conf/*.xml input?
$ bin/hadoop jar hadoop-*-examples.jar grep input output 'dfs[a-z.]+'?
$ cat output/*
偽分布式模式的操作方法
Hadoop可以在單節點上以所謂的偽分布式模式運行,此時每一個Hadoop守護進程都作為一個獨立的Java進程運行。
配置
使用如下的 conf/hadoop-site.xml:
<configuration>
? <property>
? ? <name>fs.default.name</name>
? ? <value>localhost:9000</value>
? </property>
? <property>
? ? <name>mapred.job.tracker</name>
? ? <value>localhost:9001</value>
? </property>
? <property>
? ? <name>dfs.replication</name>
? ? <value>1</value>
? </property>
</configuration>
免密碼ssh設置
現在確認能否不輸入口令就用ssh登錄localhost:
$ ssh localhost
如果不輸入口令就無法用ssh登陸localhost,執行下面的命令:
$ ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa?
$ cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
執行
格式化一個新的分布式文件系統:
$ bin/hadoop namenode -format
啟動Hadoop守護進程:
$ bin/start-all.sh
Hadoop守護進程的日志寫入到 ${HADOOP_LOG_DIR} 目錄 (默認是 ${HADOOP_HOME}/logs).
瀏覽NameNode和JobTracker的網絡接口,它們的地址默認為:
NameNode - http://localhost:50070/
JobTracker - http://localhost:50030/
將輸入文件拷貝到分布式文件系統:
$ bin/hadoop fs -put conf input
運行發行版提供的示例程序:
$ bin/hadoop jar hadoop-*-examples.jar grep input output 'dfs[a-z.]+'
查看輸出文件:
將輸出文件從分布式文件系統拷貝到本地文件系統查看:
$ bin/hadoop fs -get output output?
$ cat output/*
或者
在分布式文件系統上查看輸出文件:
$ bin/hadoop fs -cat output/*
完成全部操作后,停止守護進程:
$ bin/stop-all.sh
完全分布式模式的操作方法
關于搭建完全分布式模式的,有實際意義的集群的資料可以在這里找到。
========
Hadoop基礎教程之搭建開發環境及編寫Hello World
整個Hadoop是基于Java開發的,所以要開發Hadoop相應的程序就得用JAVA。在linux下開發JAVA還數eclipse方便。
1、下載
進入官網:http://eclipse.org/downloads/。
找到相應的版本進行下載,我這里用的是eclipse-SDK-3.7.1-linux-gtk版本。
2、解壓
下載下來一般是tar.gz文件,運行:
$tar -zxvf eclipse-SDK-3.7.1-linux-gtk.tar.gz -c ~/Tool
這里Tool是需要解壓的目錄。
解完后,在tool下,就可以看到eclipse文件夾。
運行:
$~/Tool/eclipse/eclipse
3、創建開始菜單項
每次運行時,輸入命令行比較麻煩,最好能創建在左側快捷菜單上。
$sudo gedit /usr/share/applications/eclipse.desktop
1)啟動文本編譯器,并創建文件,添加以下內容:
[Desktop Entry]
Version=1.0
Encoding=UTF-8
Name=Eclipse3.7.1
Exec=eclipse
TryExec=eclipse
Comment=Eclipse3.7.1,EclipseSDK
Exec=/usr/zjf/Tool/eclipse/eclipse
Icon=/usr/ zjf/Tool/eclipse/icon.xpm
Terminal=false
Type=Application
Categories=Application;Development;
[注意上面的路徑]?
? ? 2)創建啟動器
?
sudo gedit /usr/bin/eclipse
添加如下內容
#!/bin/sh
export MOZILLA_FIVE_HOME="/usr/lib/mozilla/"
export ECLIPSE_HOME="/usr/local/eclipse"
$ECLIPSE_HOME/eclipse $*?
? ? 3)添加可執行權限
?
sudo chmod +x /usr/bin/eclipse?
4)在開始菜單中輸入eclipse:
就會看到軟件圖標,然后將其拖到左側工具條中即可。
?
4、下載hadoop在eclise中的插件并配置
直接在網上搜:hadoop-0.20.2-eclipse-plugin.jar
https://issues.apache.org/jira/secure/attachment/12460491/hadoop-eclipse-plugin-0.20.3-SNAPSHOT.jar
下載后,將jar包放在eclipse安裝目錄下的plugins文件夾下。然后啟動eclipse
第一次啟動eclpse后,會讓我們設定一個工作目錄,即以后建的項目都在這個工作目錄下。
進入后,在菜單window->Rreferences下打開設置:
點擊browse選擇hadoop的源碼下的Build目錄,然后點OK
打開Window->View View->Other 選擇Map/Reduce Tools,單擊Map/Reduce Locations,會打開一個View,
添加Hadoop Loacation,其中Host和Port的內容跟據conf/hadoop-site.xml的配置填寫,UserName 是用戶名,如
在配置完后,在Project Explorer中就可以瀏覽到DFS中的文件,一級級展開,可以看到之前我們上傳的in文件夾,以及當是存放的2個txt文件,同時看到一個在計算完后的out文件夾。
現在我們要準備自己寫個Hadoop 程序了,所以我們要把這個out文件夾刪除,有兩種方式,一是可以在這樹上,執行右健刪除。 二是可以用命令行:
$bin/hadoop fs -rmr out
用$bin/hadoop fs -ls 查看
5、編寫HelloWorld
環境搭建好了,之前運行Hadoop時,直接用了examples中的示例程序跑了下,現在可以自己來寫這個HelloWorld了。
在eclipse菜單下 new Project 可以看到,里面增加了Map/Reduce選項:
選中,點下一步:
輸入項目名稱后,繼續(next), 再點Finish
然后在Project Explorer中就可以看到該項目了,展開,src發現里面啥也沒有,于是右健菜單,新建類(new->new class):
然后點擊Finish,就可以看到創建了一個java類了:
然后在這個類中填入代碼:
public static class TokenizerMapper
extends Mapper<Object, Text, Text, IntWritable>{
private final static IntWritable one = new IntWritable(1);
private Text word = new Text();
public void map(Object key, Text value, Context context
) throws IOException, InterruptedException {
System.out.println("key=" +key.toString());
System.out.println("Value=" + value.toString());
StringTokenizer itr = new StringTokenizer(value.toString());
while (itr.hasMoreTokens()) {
word.set(itr.nextToken());
context.write(word, one);
}
}
}
public static class IntSumReducer
extends Reducer<Text,IntWritable,Text,IntWritable> {
private IntWritable result = new IntWritable();
public void reduce(Text key, Iterable<IntWritable> values,
Context context
) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
result.set(sum);
context.write(key, result);
}
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
System.out.println("url:" + conf.get("fs.default.name"));
String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
if (otherArgs.length != 2) {
System.err.println("Usage: wordcount <in> <out>");
System.exit(2);
}
Job job = new Job(conf, "word count");
job.setJarByClass(WordCount.class);
job.setMapperClass(TokenizerMapper.class);
job.setCombinerClass(IntSumReducer.class);
job.setReducerClass(IntSumReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
填入代碼后,會看到一些錯誤,沒關系,點擊邊上的紅叉,然后選擇里面的import即可;
如果想偷懶,則可以直接在類的開頭帖入下面的這些引用:
import java.io.IOException;
import java.util.StringTokenizer;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;
這里,如果直接用源碼來操作,可能會GenericOptionsParser這個類找不到定義,還是紅叉,沒關系,如果還是紅叉,可以添加commons-cli-1.2.jar
?
這個jar包,在build/ivy/lib/Hadoop/Common下,右健Project Explorer中的MyHelloWorld工程,選擇Build Path->Config Build Path
在Liberaries Tab頁下,點擊Add External JARs 在彈出窗口中,跟據前面說的目錄,找到這個jar包,點確定后,回到工程,可以看到紅叉消失,說明編譯都通過了。
在確保整個工程沒有錯誤后,點擊上面的小綠箭頭,然后在彈出的小窗口上,選擇Run On Hadoop:
點OK后,會彈出小窗口:
然手中選擇Choose an existing server from the list below。然后找到之前配置的地址項,選中后,點Finish,然后系統不會Run起來,在控制臺(雙擊可最大化)中可以看到運行結果:
運行完后,用命令行可以看到 $bin/hadoop fs –ls 可以看到多了一個out文件夾,再用$bin/hadoop fs –cat out/*可以將out文件夾內容全顯示出來,則可以看到單詞的統計結果來。
問題1 :過程中,如果點了Run On Hadoop沒有反應,則可能你下的這個有問題,重新到:https://issues.apache.org/jira/secure/attachment/12460491/hadoop-eclipse-plugin-0.20.3-SNAPSHOT.jar
上下載,然后將下載的插件重命名為"hadoop-0.20.2-eclipse-plugin.jar",放入eclipse中的plugins目錄下。
問題2:運行后,如果結果里只輸入了個usage <in> <out>,則需要修改下參數,在運行菜單邊上小箭頭,下拉,點擊Run Configuration,:
左邊選中 JavaApplication中的 WordCount,右邊,在Arguments中輸入 in out。
然后再點Run 就可以看到結果了。
問題3:第二次運行會報錯,仔細看提示,可以看到報錯的是out目錄已經存在,所以需要手動來刪除一下。
========
Hadoop教程之編寫HelloWorld(2)
?前面我們寫了一個Hadoop程序,并讓它跑起來了。但想想不對啊,Hadoop不是有兩塊功能么,DFS和MapReduce。沒錯,上一節我們寫了一個MapReduce的HelloWorld程序,那這一節,我們就也學一學DFS程序的編寫。
DFS 是什么,之前已經了解過,它是一個分布式文件存儲系統。不管是遠程或本地的文件系統,其實從接口上講,應該是一至的,不然很難處理。同時在第2節的最后, 我們列出了很多一些DFS的操作命令,仔細看一下,這些命令其實跟linux中的文件操作命令很相似,
所以說,對于分布式文件系統,我們完全可以用本地文 件的方式來理解。
那理一下,一般常用操作有哪些? 當然我們可以從編程角度來:
創建、讀、寫一個文件,列出文件夾中的文件及文件夾列表,刪除文件夾,刪除目錄,移動文件或文件夾,重命名文件或文件夾。
同樣,這里我們就依葫蘆畫瓢跑起個程序來:
啟 動eclipse,新建Hadoop項目,名稱MyDFSTest,新建類DFSTest,點擊確定,然后同樣工程屬性Configure BuildPath中把 build/ivy/lib/Hadoop下的所有jar包都引用進來。「這里就不詳細截圖了,可以參考前一節中的內容」
在類中,添加main函數:
public static void main(String[] args) {
}
也可以在添加類時,勾選上創建main,則會自動添加上。
?
在Main函數中添加以下內容:
try {
Configuration conf = new Configuration();
conf.set("fs.default.name", "hdfs://localhost:9000");
FileSystem hdfs = FileSystem.get(conf);
Path path = new Path("in/test3.txt");
FSDataOutputStream outputStream = hdfs.create(path);
byte[] buffer = " 你好Hello".getBytes();
outputStream.write(buffer, 0, buffer.length);
outputStream.flush();
outputStream.close();
System.out.println("Create OK");
} catch (IOException e) {
e.printStackTrace();
}
直接添加進來會報錯,然后需要添加一些引用才行:
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
在沒有錯誤后,點擊工具條上的運行, 但這次跟前次不一樣,選擇Run as Java Application。然后,就可以在輸出框中看到Create OK的字樣了,表明程序運行成功。
這段代碼的意思是在in文件夾下,創建test3.txt,里面的內容是"你好Hello"。 在運行完后,我們可以到eclipse的Project Explorer中查看是否有這文件以及內容。同樣也可以用命令行查看$bin/hadoop fs -ls in。
好了,第一個操作DFS的程序跑起來了,那其它功能只要套上相應的處理類就可以了。
為了方便查找操作,我們列舉了張表:
操作說明
操作本地文件
操作DFS文件
主要命名空間
?
?
java.io.File
java.io.FileInputStream
java.io.FileOutputStream
org.apache.hadoop.conf.Configuration
org.apache.hadoop.fs.FileSystem
org.apache.hadoop.fs.Path
org.apache.hadoop.fs.FSDataInputStream;
org.apache.hadoop.fs.FSDataOutputStream
初使化對象
new File(路徑);
Configuration
FileSystem hdfs
創建文件
File.createNewFile();
FSDataOutputStream = hdfs.create(path)
FSDataOutputStream.write(
buffer, 0, buffer.length);
創建文件夾
File.mkdir()
hdfs.mkdirs(Path);
讀文件
new FileInputStream();
FileInputStream.read(buffer)
FSDataInputStream = hdfs.open(path);
FSDataInputStream.read(buffer);
寫文件
FileOutputStream.write(
buffer, 0, buffer.length);
FSDataOutputStream = hdfs.append(path)
FSDataOutputStream.write(
buffer, 0, buffer.length);
刪除文件(夾)
File.delete()
FileSystem.delete(Path)
列出文件夾內容
File.list();
FileSystem.listStatus()
重命令文件(夾)
File.renameTo(File)
FileSystem.rename(Path, Path) ? ? ? ?
有了這張表,以后不怕了,代碼搬搬即可。
接下來換個話題。
本人主要從事.net開發的,所以對于java上,還是有點生。所以接下來半章中,簡要的把JAVA的學習列一列。
JAVA和.net現在從語言角度看,的確有很多相似之處。但也有不同之處,這就是我們要學的。
在.Net中,主要有dll和exe, dll為類庫, exe為可執行程序,在exe中有唯一的main函數,作為函數入口。dll 類庫是無法執行的,exe可以雙擊運行,也可以命令行執行。編譯后,.net會把所有定義的類編譯進exe或dll中,一個工程產出文件就是一個。
在JAVA中,jar 對應的類庫,可以被別人調用。exe就不存在了。一個工程編譯后,產出物是一堆的.class文件,在開發中每一個定義的類,都會被編譯成這 個.class文件。而且一個.java文件中,不能定義多個頂級類(嵌套類是可以的),且文件名與類名必須相同,文
件所以的目錄必須和命名空間相同。所 以編譯后,可以講一個.java文件將會編譯成一個.class文件,且有與原先的目錄相同。
也就是說,java有點像散裝的一樣,產物就是一堆的.class文件。 那jar文件呢,簡單的說,就是一個zip包,把一堆的.class文件打包成一個壓縮包。
同時,一個工程中,支持多個main函數,即多個入口。
說了一堆,還不如實踐一下:
在eclipse中,創建一個JAVA project 取名為JAVAStudy。
然后創建兩個類,沒有目錄的,ch1 ch2 再創建一個包叫pkg1,在這個包下創建一個類ch3:
然后,每個類下都建一個main函數,內容打印類名:
public static void main(String[] args) {
System.out.println(ch1.class.getName());
}
注意,復制到ch2 ch3中后要改一下里面的類名。
然后每當你切換到一個新的類代碼中,點擊運行,都會提示Run As ,都選Java Application。 然后就可以看到結果了,每個類都可以作為入口執行。
OK,程序好了,如何發布呢,或如何從命令行運行呢?
我們進入目錄先看一下:
進入工程目錄,可以看到有src和bin,進入bin,就可以看到一個個的class文件了,的確跟前面描述一樣,目錄與代碼相同結構。
輸入java ch1 就可以看到結果了。執行ch3時,注意中間不是斜線,而是點,因為這里輸入的是命名空間+類名,而不是class文件的路徑。
如果不在這個目錄執行,看到會報錯,或命名空間輸錯了,也是這個錯。
如果我就在這里想執行呢? 可以這樣:
利用classpath指定class的路徑。
如何打成jar包:
進入bin目錄:
$cd bin
$jar cvf test.jar ch1.class ch2.class pkg1/.class
然后在bin目錄下就可以看到test.jar文件了。
如何執行jar呢,為了防止與里面的class文件沖突,我們將test.jar復制到外面來:
$cp test.jar ../
$cd ..
再執行:
$java –classpath test.jar ch1
同樣,輸入classpath就可以搞定了的。
了解了這些后,我們又可以做個試驗證了。 第一章中我們運行hadoop中Helloword時,是調用了example的jar包。所以這里我們可以把上一章的程序也來打個jar包,試下是否能運行:
$cd ~/workspace/MyHelloWorld ? ? ?//進入HelloWorld代碼目錄
$cd bin
$jar cvf test.jar *.class ? ? //打上jar包
$cp test.jar ../../hadoop-0.20.2 ? ?//將jar包復制到hadoop目錄下
$cd ../../hadoop-0.20.2
$bin/start-all.sh ? ? ? ? ? ? //啟動hadoop
$bin/hadoop test.jar WordCount in out //運行我們寫的程序
然后就可以看到與之前一樣的結果了。
========
Hadoop基礎教程-運行環境搭建
?一、Hadoop是什么
一個分布式系統基礎架構,由Apache基金會所開發。用戶可以在不了解分布式底層細節的情況下,開發分布式程序。充分利用集群的威力進行高速運算和存儲。 Hadoop實現了一個分布式文件系統(Hadoop Distributed File System),簡稱HDFS。HDFS有高容錯性的特點
,并且設計用來部署在低廉的(low-cost)硬件上;而且它提供高傳輸率(high throughput)來訪問應用程序的數據,適合那些有著超大數據集(large data set)的應用程序。HDFS放寬了(relax)POSIX的要求,可以以流的形式訪問(streaming access)文件系統中
的數據。Hadoop的框架最核心的設計就是:HDFS和MapReduce。HDFS為海量的數據提供了存儲,則 MapReduce為海量的數據提供了計算。
Hadoop主要用于一些分布式計算。在這個大數據年代,那這個的確是一個很不錯的工具。所以很有必要來學一學。
二、運行環境搭建
首先,這個是需要運行在linux系統中的,所以得安裝個linux才行,市面上有很多個linux的版本,如紅帽子、Fedra、Ubuntu。選哪種呢,對我這種習慣windows的來說,當然要使用方便的,所以選擇了Ubuntu。
安 裝Ubuntu,這里我就不多說了,在官網上有很多,其實也很簡單,一路下一步。當然這里可以安裝在Vmware虛擬機上,也可以直接安裝在硬盤上。 我個人建議,可以直接安裝在硬盤上,與現有windows做個雙系統。因為后面還要跑開發環境 eclipse,在虛擬機上會有
點吃力。 同時安裝在硬盤上后,還可以這樣玩,在進入windows后,安裝 vmware,然后新建虛擬機后,不要創建硬盤,直接使用硬盤的分區,這樣, 就可以在vmware中啟動安裝在硬盤上的ubuntu了。做到雙系統,雙啟動。這樣好處是,當要開發時,可以直接進ubuntu
系統,當只是看看代碼,以及后面模擬分布式部署時,就可以用vmware來啟動,同時再建上幾個虛擬機來進行分布式部署。?
操作系統準備好后,就需要一些組件了,hadoop比較簡單,只需要ssh和java環境,再加個下代碼的SVN。
先用 sudo apt-get install subversion ssh ant 這個命令,把SSH、Ant和SVN安裝起來。
java環境,可以在網上下載一個JDK安裝包,如:jdk-6u24-linux-i586.bin
安裝直接在目錄下運行./jdk-6u24-linux-i586.bin即可。
然后配置jdk目錄:
先進入安裝目錄 cd jdk-6u24-…
然后輸入 PWD 就可以看到java安裝目錄,復制下來:
命令行執行:sudo gedit /etc/profile
在打開的文件里,追加:
export JAVA_HOME=/home/administrator/hadoop/jdk1.6.0_27 //這里要寫安裝目錄
export PATH=${JAVA_HOME}/bin:$PATH
執行source /etc/profile 立即生效
驗證是否安裝完成,那比較容易了,在命令行下運行 java -version ant svn ssh 看是否找不到命令,如果都能找到,說明OK了。
三、下載代碼:
這是個開源的系統,代碼很方便用SVN就可以下載到,版本也很多,在這里我選擇0.20.2版本,一個是網上好多書都基于這個版本的,另外是看源碼,還是以前點版本吧,后面的版本里面肯定又加了很多。
運行這個命令來下載:
svn co http://svn.apache.org/repos/asf/hadoop/common/tags/release-0.20.2/
下載完成后,會在當前文件夾內產生一個新文件夾release-0.20.2,這里面就是代碼了。
為了后面方便操作,把這文件夾重命令一下:
mv release-0.20.2/ hadoop-0.20.2
好了,用圖形界面進入該文件夾,看一看:
?
四、編譯代碼
剛下完的代碼是無法直接運行的,需要編譯一下,但用什么編譯呢?
編譯前先修改一下build.xml,打開,將里面的版本號改成:0.20.2,如下:
看到代碼里面有個build.xml,這個是典型的用ant編譯用的配置文件,所以直接在命令行里輸入:
~/hadoop-0.20.2$ant
~/hadoop-0.20.2$ant jar
~/hadoop-0.20.2$ant examples
[注意] 編譯時需要聯網,否則在自動下載jar包時會掛掉。
然后屏幕會刷啊刷,等到完成看到下面字符時,也就OK了:
五、配置SSH
我們了解到,這個hadoop是支持分布式運行的,每臺機器到時都會來安裝hadoop程序,如果想啟動所有程序怎么辦? 一臺臺去啟動? 那也太土了, 當然是遠程去啟動咯。為實現這個目標,就得用上SSH了。
SSH是什么,說白了,這個就是一個遠程登陸器,跟遠程桌面、telnet差不多。在linux上所有操作都可以用命令行來完成,所有SSH也就是一個命令行形式,同時比telnet高級,因為通過了加密通道傳輸信息。
那我們就部署了一臺機器,還要這個SSH嗎? 答案是要的,因為在運行hadoop里,即使是本機的,里面也要通過SSH localhost的方式來啟動,這樣代碼統一。
前面不是安裝過SSH了么,還要配置什么?SSH正常登陸時,是需要輸入用戶名密碼的,但是當所有的hadoop子服務都受主服務管了后,最好就直接信任了,不要輸入帳號信息,所以我們配置的目的也就是這個。
先試一下,我用SSH登陸當前本機信息:
可以看到,登陸本機時,也要輸入一下密碼,怎么辦?
SSH是能過RSA加密的,所以有公鑰私鑰的說法,所以,我們先產生一對固定的公私鑰,運行這個ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa命令:
這里產生公私鑰,并生成在.ssh文件夾下,于是我們就進入看一下:
果然,這里多了兩個文件,id_dsa為私鑰,id_dsa.pub為公鑰
然后再把公鑰復制成authorized_key,即將這個公鑰固定為SSH登陸所用。
這步很重要,做完這步后,就可以再試一下登陸本機了:
看,現在再ssh localhost時,就直接進入,沒有再輸入帳號了。
到這里,SSH配置就成功了。
6、修改配置文件
在正式運行之前,還要修改一下配置文件才地,這里具體的配置參數,就不講,葫蘆畫瓢么,先跑起來,后面再來研究這是為啥:
在代碼的conf文件夾內,就可以找到下面幾個配置文件,分別配置成以下內容:
core-site.xml
<configuration>
<property>
<name>fs.default.name</name>
<value>hdfs://localhost:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/home/zjf/hadoop-0.20.2/tmpPath</value> !這里改下路徑
</property>
</configuration>
hdfs-site.xml
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
</configuration>
mapred-site.xml
<configuration>
<property>
<name>fs.default.name</name>
<value>hdfs://localhost:9000</value>
</property>
<property>
<name>mapred.job.tracker</name>
<value>hdfs://localhost:9001</value>
</property>
</configuration>
修改conf/hadoop-env.sh
將里面的JAVA_HOME注釋打開,并把里面的地址配置正確。
7、運行
Hadoop是一頭神奇的大象,那我們得站在大象背上說句Hello world了。
進入hadoop目錄: $cd Hadoop-0.20.2
首次運行,需要對namenode進行格式化:bin/hadoop namenode -format ? ?
啟動hadoop:
bin/start-all.sh
關閉hadoop可以用:
bin/stop-all.sh
如果驗證啟動成功呢?有兩種方式
訪問一下管理頁面看:
Job跟蹤:http://localhost:50030
NameNode結點:http://localhost:50070
?
用jps看一下有幾個java進程在運行,如果是下面幾個就正常了:
主要有DataNode NameNode SecondaryNameNode TaskTracker JobTracker這幾個進程,就表示正常了
系統啟動正常后,跑個程序吧
$mkdir input
$cd input
$echo "hello world">test1.txt
$echo "hello hadoop">test2.txt
$cd ..
$bin/hadoop dfs -put input in
$bin/hadoop jar build/hadoop-0.20.2-examples.jar wordcount in out
$bin/hadoop dfs -cat out/*?
最關健的是,最后輸入:
輸出這個結果這就表示我們的程序運行成功了。至于這結果是什么意思,我想看到后大概也猜到了吧,至于詳細解說,下期再看。
========
Hadoop基礎教程之高級編程
?從前面的學習中,我們了解到了MapReduce整個過程需要經過以下幾個步驟:
1.輸入(input):將輸入數據分成一個個split,并將split進一步拆成<key, value>。
2.映射(map):根據輸入的<key, value>進生處理,
3.合并(combiner):合并中間相兩同的key值。
4.分區(Partition):將<key, value>分成N分,分別送到下一環節。
5.化簡(Reduce):將中間結果合并,得到最終結果
6.輸出(output):負責輸入最終結果。
其中第3、4步又成洗牌(shuffle)過程。
從前面HelloWorld示例中,我們看到,我們只去個性化了Map和Reduce函數,那其他函數呢,是否可以個性化?答案當然是肯定的。下面我們就對每個環節的個性化進行介紹。
自定義輸入格式
輸 入格式(InputFormat)用于描述整個MapReduce作業的數據輸入規范。先對輸入的文件進行格式規范檢查,如輸入路徑,后綴等檢查;然后對 數據文件進行輸入分塊(split);再對數據塊逐一讀出;最后轉換成Map所需要的<key, value>健值對。
系統中提供豐富的預置輸入格式。最常用的以下兩種:
TextInputFormat:系統默認的數據輸入格式。將文件分塊,并逐行讀入,每一行記錄行成一對<key, value>。其中,key值為當前行在整個文件中的偏移量,value值為這一行的文本內容。
KeyValueTextInputFormat:這是另一個常用的數據輸入格式,讀入的文本文件內容要求是以<key, value>形式。讀出的結果也就直接形成<key, value>送入map函數中。
如果選擇輸入格式呢?那就只要在job函數中調用
job.setInputFormatClass(TextInputFormat.class);
在Hello中我們沒有設定,系統默認選擇了TextInputFormat。
一般情況夠用了,但某些情況下,還是無法滿足用戶的需求,所以還是需要個性化。個性化則按下面的方式進行:
如果數據我們是來源于文件,則可以繼承FileInputFormat:
? ? public class MyInputFormat extends FileInputFormat<Text,Text> {
? ? ? ?@Override
? ? ? ?public RecordReader<Text, Text> createRecordReader(InputSplit split,
? ? ? ? ? ? ?TaskAttemptContext context) throws IOException, InterruptedException {
? ? ? ? ? // TODO Auto-generated method stub
? ? ? ? ? return null;
? ? ? ?}
? ? }?
如果數據我們是來源于非文件,如關系數據,則繼承
? ? public class MyInputFormat extends InputFormat<Text,Text> {
? ? ? ?@Override
? ? ? ?public RecordReader<Text, Text> createRecordReader(InputSplit arg0,
? ? ? ? ? ? ?TaskAttemptContext arg1) throws IOException, InterruptedException {
? ? ? ? ? // TODO Auto-generated method stub
? ? ? ? ? return null;
? ? ? ?}
? ? ? ?@Override
? ? ? ?public List<InputSplit> getSplits(JobContext arg0) throws IOException,
? ? ? ? ? ? ?InterruptedException {
? ? ? ? ? // TODO Auto-generated method stub
? ? ? ? ? return null;
? ? ? ?}
? ? }?
這里比較清晰了,下面個函數為拆分成split,上面個函數跟據split輸出成Key,value。
自定義map處理
這個好理解,我們的HelloWorld程序中就自定義了map處理函數。然后在job中指定了我們的處理類:
job.setMapperClass(TokenizerMapper.class);
能不能沒有map呢? 可以的,如果沒有map,也就是這與上面的這個setMapperClass,則系統自動指定一個null,這時處理是將輸入的<key,value>值,不作任何修改,直接送到下一環節中。
個性化代碼如下:
? ? public static class TokenizerMapper
? ? ? ? ? ?extends Mapper<Object, Text, Text, IntWritable>{
? ? ? ? public void map(Object key, Text value, Context context
? ? ? ? ? ? ? ? ? ? ? ? ) throws IOException, InterruptedException {
? ? ? ? ? ? context.write(key, value);
? ? ? ? }
? ? ? }?
自定義合并Combiner
自定義合并Combiner類,主要目的是減少Map階段輸出中間結果的數據量,降低數據的網絡傳輸開銷。
Combine 過程,實際跟Reduce過程相似,只是執行不同,Reduce是在Reducer環節運行,而Combine是緊跟著Map之后,在同一臺機器上預先將 結時進行一輪合并,以減少送到Reducer的數據量。所以在HelloWorld時,可以看到,Combiner和Reducer用的是同一個類:
? ? job.setCombinerClass(IntSumReducer.class);
? ? job.setReducerClass(IntSumReducer.class);?
如何個性化呢,這個跟Reducer差不多了:
? ? public static class MyCombiner
? ? ? ? ? extends Reducer<Text,IntWritable,Text,IntWritable> {
? ? ? ?public void reduce(Text key, Iterable<IntWritable> values,
? ? ? ? ? ? ? ? ? ? ? ? ? Context context
? ? ? ? ? ? ? ? ? ? ? ? ? ) throws IOException, InterruptedException {
? ? ? ? ?context.write(key, new IntWritable(1));
? ? ? ?}
? ? ?}?
自定義分區Partitioner
在 MapReduce程序中,Partitioner決定著Map節點的輸出將被分區到哪個Reduce節點。而默認的Partitioner是 HashPartitioner,它根據每條數據記錄的主健值進行Hash操作,獲得一個非負整數的Hash碼,然后用當前作業的Reduce節點數取模 運算,有N個結點的話,就
會平均分配置到N個節點上,一個隔一個依次。大多情況下這個平均分配是夠用了,但也會有一些特殊情況,比如某個文件的,不能被拆 開到兩個結點中,這樣就需要個性化了。
個性化方式如下:
? ? public static class MyPartitioner
? ? ? ? ? extends HashPartitioner<K,V> {
? ? ? ?public void getPartition(K key, V value,int numReduceTasks) {
? ? ? ? ?super.getPartition(key,value,numReduceTasks);
? ? ? ?}
? ? ?}?
方式其實就是在執行之前可以改變一下key,來欺騙這個hash表。
自定義化簡(Reducer)
這一塊是將Map送來的結果進行化簡處理,并形成最終的輸出值。與前面map一樣,在HelloWorld中我們就見到過了。通過下面代碼可以設置其值:
job.setReducerClass(IntSumReducer.class);
同樣,也可以這樣類可以不設置,如果不設置的話,就是把前面送來的值,直接送向輸出格式器中。
如果要個性化,則如下:
? ? ? public static class IntSumReducer
? ? ? ? ?extends Reducer<Text,IntWritable,Text,IntWritable> {
? ? ? public void reduce(Text key, Iterable<IntWritable> values,
? ? ? ? ? ? ? ? ? ? ? ? ?Context context
? ? ? ? ? ? ? ? ? ? ? ? ?) throws IOException, InterruptedException {
? ? ? ? context.write(key, result);
? ? ? }
? ? }?
自定義輸出格式
數 據輸出格式(OutPutFormat)用于描述MapReduce作業的數據輸出規范。Hadoop提供了豐富的內置數據輸出格式。最常的數據輸出格式 是TextOutputFormat,也是系統默認的數據輸出格式,將結果以"key+\t+value"的形式逐行輸出到文本文件中。還有其它的, 如:
DBOutputFormat,FileOutputFormat,FilterOutputFormat,IndexUpdataOutputFormat,LazyOutputFormat,MapFileOutputFormat, 等等。
如果要個性化,則按下面方式進行:
? ? public class MyOutputFormat extends OutputFormat<Text,Text> {
? ? ? ?@Override
? ? ? ?public void checkOutputSpecs(JobContext arg0) throws IOException,
? ? ? ? ? ? ?InterruptedException {
? ? ? ? ? // TODO Auto-generated method stub
? ? ? ?}
? ? ? ?@Override
? ? ? ?public OutputCommitter getOutputCommitter(TaskAttemptContext arg0)
? ? ? ? ? ? ?throws IOException, InterruptedException {
? ? ? ? ? // TODO Auto-generated method stub
? ? ? ? ? return null;
? ? ? ?}
? ? ? ?@Override
? ? ? ?public RecordWriter<Text, Text> getRecordWriter(TaskAttemptContext arg0)
? ? ? ? ? ? ?throws IOException, InterruptedException {
? ? ? ? ? // TODO Auto-generated method stub
? ? ? ? ? return null;
? ? ? ?}
? ? }?
復合健——用戶自定義類型。
從前面的整個過程中可以看到,都是采用key-value的方式進行傳入傳出,而這些類型大多是單一的字符串,和整型。如果我的key中需要包含多個信息怎么辦?用字符串直接拼接么? 太不方便了,最好能夠自己定義一個類,作為這個key,這樣就方便了。 如果定義一個
類作為key 或value的類型? 有什么要求?就是這個類型必須要繼承WritableComparable<T>這個類,所以如果要自定義一個類型則可以這么實現:
? ? public class MyType implements WritableComparable<MyType> {
? ? ? ?private float x,y;
? ? ? ?public float GetX(){return x;}
? ? ? ?public float GetY(){return y;}
? ? ? ? ? @Override
? ? ? ? ? public void readFields(DataInput in) throws IOException {
? ? ? ? ? ? ?x = in.readFloat();
? ? ? ? ? ? ?y = in.readFloat();
? ? ? ? ? }
? ? ? ? ? @Override
? ? ? ? ? public void write(DataOutput out) throws IOException {
? ? ? ? ? ? ?out.writeFloat(x);
? ? ? ? ? ? ?out.writeFloat(y);
? ? ? ? ? }
? ? ? ? ? @Override
? ? ? ? ? public int compareTo(MyType arg0) {
? ? ? ? ? ? ?//輸入:-1(小于) 0(等于) 1(大于)
? ? ? ? ? ? ?return 0;
? ? ? ? ? }
? ? ? ?}?
這個示例中,我們添加了兩個float變量:x,y 。 這個信息能過int 和out按次序進行輸入輸出。最后,再實現一個比較函數即可。
Job任務的創建
? ? Job job = new Job(conf, "word count");
? ? ? ?job.setJarByClass(WordCount.class);
? ? ? ?job.setInputFormatClass(MyInputFormat.class);
? ? ? ?job.setMapperClass(TokenizerMapper.class);
? ? ? ?job.setCombinerClass(IntSumReducer.class);
? ? ? ?job.setPartitionerClass(MyPartitioner.class);
? ? ? ?job.setReducerClass(IntSumReducer.class);
? ? ? ?job.setOutputFormatClass(TextOutputFormat.class);
? ? ? ?job.setOutputKeyClass(Text.class);
? ? ? ?job.setOutputValueClass(IntWritable.class);
? ? ? ?FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
? ? ? ?FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));?
任務創建比較容易,其實就是new一個實例,然后把上面描述的過程類設置好,然后加上第2行中,jar包的主類,第10、11行的輸入輸出路徑。這樣就完事了。
Job任務的執行
單個任務的執行,沒有什么問題,可以用這個:
? ? job.waitForCompletion(true);
但多個任務呢? 多個任務的話,就會形成其組織方式,有串行,有并行,有無關,有組合的,如下圖:
圖中,Job2和Job3將會等Job1執行完了再執行,且可以同時開始,而Job4必須等Job2和Job3同時結束后才結束。
這個組合,就可以采用這樣的代碼來實現:
? ? Configuration conf = new Configuration();
? ? ? ? ? Job job1 = new Job(conf, "job1");
? ? ? ? ? //.. config Job1
? ? ? ? ? Job job2 = new Job(conf, "job2");
? ? ? ? ? //.. config Job2
? ? ? ? ? Job job3 = new Job(conf, "job3");
? ? ? ? ? //.. config Job3
? ? ? ? ? Job job4 = new Job(conf, "job4");
? ? ? ? ? //.. config Job4
? ? ? ? ? //添加依賴關系
? ? ? ? ? job2.addDependingJob(job1);
? ? ? ? ? job3.addDependingJob(job1);
? ? ? ? ? job4.addDependingJob(job2);
? ? ? ? ? job4.addDependingJob(job3);
? ? ? ? ? JobControl jc = new JobControl("jbo name");
? ? ? ? ? jc.addJob(job1);
? ? ? ? ? jc.addJob(job2);
? ? ? ? ? jc.addJob(job3);
? ? ? ? ? jc.addJob(job4);
? ? ? ? ? jc.run();?
總述
現在回頭看看,其實整個hadoop編程,也就是這幾塊內容了,要實現某個功能,我們就往上面這些步驟上套,然后聯起來執行,達到我們的目的。
========
hadoop 本地庫 說明
問題導讀
1.hadoop本地庫支持哪些平臺?
2.本地庫是否有32,64之分?
3.hadoop通過什么工具來檢測本地庫是否加載正確?
4.如何加載本地庫?包含哪些步驟?
5.本地庫在什么情況下不需要使用DistibutedCache?
概述
這個指南描述了hadoop本地庫,包括關于共享本地庫的小討論。
注意:
取決于你的環境,這個詞 “native libraries”涉及所有的*.so’,你需要編譯;這個詞 “native compression”涉及所有的*.so’的你需要編譯指定與壓縮相關的。當前,盡管如此,這個文檔僅限于hadoop本地庫 (libhadoop.so).文檔為libhdfs庫(libhdfs.so)點
這 here.
hadoop本地庫
處于性能考慮和非可用性 Java 實現,Hadoop的具有某些部件的本地實現,這些組件單獨是可用的。動態鏈接庫調用本地原生Hadoop庫。 在 *nix(如:Linux,unix) 平臺上本地庫名字為 libhadoop.so.
用法
相當容易使用hadoop本地庫:
1.查看組件
2.查看支持平臺
3.下載一個構建好的hadoop發布版本或則自己構建本地庫。無論是自己下載還是自己構建(編譯),本地的名字是相同的: libhadoop.so
4.安裝壓縮編解碼開發包(> > zlib-1.2,gzip-1.2):
如果你下載本地庫,安裝一個或則多個開發包,無論壓縮編解碼你想用于部署。
如果你想編譯本地庫,它是強制性安裝了開發包。
5.檢查運行時日志文件
組件
本地庫包含各種組件:
Compression Codecs (bzip2, lz4, snappy, zlib)
Native IO utilities for HDFS Short-Circuit Local Reads and Centralized Cache Management in HDFS
CRC32 校驗實現
支持平臺
hadoop本地庫僅支持在*nix平臺上,不支持 Cygwin和Mac OS X 平臺.
hadoop本地庫主要用在GNU/Linus平臺,已測試
RHEL4/Fedora
Ubuntu
Gentoo
上面hadoop 32/64位本地庫與相應的32/64 位 jvm工作
下載
hadoop預構建 32-位 i386-Linux本地庫作為hadoop分布式一部分是有效的,位于e lib/native目錄。你可以下載從hadoop Common Releases.
一定要安裝zlib和/或gzip 開發包?
構建
hadoop本地庫是用ANSI C編寫,并使用GNU自動工具鏈 (autoconf, autoheader, automake, autoscan, libtool)構建。這意味著他可以直接使用工具鏈 (autoconf, autoheader, automake, autoscan, libtool)在任何平臺上構建(查看支持平臺)
在平臺上包需要安裝:
C compiler (e.g. GNU C Compiler)
GNU Autools Chain: autoconf, automake, libtool
zlib-development package (stable version >= 1.2.0)
openssl-development package(e.g. libssl-dev)
一旦你安裝必備包使用標準的Hadoop的pom.xml文件,通過本地庫標識構建hadoop本地庫
[Bash shell] 純文本查看 復制代碼
?
1
$ mvn package -Pdist,native -DskipTests -Dtar
你可以查看新構建的庫在
[Bash shell] 純文本查看 復制代碼
?
1
$ hadoop-dist/target/hadoop-2.7.1/lib/native
請注意以下幾點:
1.它強制安裝 zlib 和 gzip 開發包在目標平臺,構建hadoop本地庫。盡管如此,如果你想安裝部署使用一個codec包,也是足夠的。
2.為了構建和部署hadoop本地庫,使用正確的zlib 32/64位 庫是需要的 ,在目標平臺上依賴32/64 位 jvm,
運行時
bin/hadoop腳本確保hadoop本地庫通過系統屬性-Djava.library.path=<path>在庫路徑。
在運行時,檢查hadoop MapReduce任務日志文件
1.如果所有的事情準備好,然后調試util.NativeCodeLoader ,嘗試加載自定義構建本地庫。。。 INFO util.NativeCodeLoader - Loaded the native-hadoop library
2.如果產生錯誤,然后:INFO util.NativeCodeLoader - Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
檢查
NativeLibraryChecker是一個工具用來檢測本地庫是否加載正確,你可以啟動nativelibrarychecker如下:
[Bash shell] 純文本查看 復制代碼
$ hadoop checknative -a
14/12/06 01:30:45 WARN bzip2.Bzip2Factory: Failed to load/initialize native-bzip2 library system-native, will use pure-Java version
14/12/06 01:30:45 INFO zlib.ZlibFactory: Successfully loaded & initialized native-zlib library
Native library checking:
hadoop: true /home/ozawa/hadoop/lib/native/libhadoop.so.1.0.0
zlib: ? true /lib/x86_64-linux-gnu/libz.so.1
snappy: true /usr/lib/libsnappy.so.1
lz4: ? ?true revision:99
bzip2: ?false
本地共享庫
你可以加載任何本地共享庫使用DistributedCache,分發和符號鏈接庫文件
這個例子展示了如何分發共享本地庫mylib.so,和從mapreduc任務加載的。1.首先復制庫到hdfs:bin/hadoop fs -copyFromLocal mylib.so.1 /libraries/mylib.so.1
2.job啟動程序應該包含下面:
[Bash shell] 純文本查看 復制代碼
?
DistributedCache.createSymlink(conf);
DistributedCache.addCacheFile("hdfs://host:port/libraries/mylib.so. 1#mylib.so", conf);
3.MapReduce 任務應該包含:
[Bash shell] 純文本查看 復制代碼
?
System.loadLibrary("mylib.so");
注意:
如果你下載或則構建了hadoop本地庫,不需要使用DistibutedCache使庫提供給mapreduce任務
版本:2.7.1?
========
總結
以上是生活随笔為你收集整理的Hadoop学习总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VC++图像存取总结
- 下一篇: opencv图像处理常用完整示例代码总结