start-dfs.sh 啓動hdfs集羣
start-yarn.sh 啓動yarn集羣
./hadoop-daemon.sh start namenode/datanode 單個節點的啓動
局部統計(各幹各的:Map):每一臺機器上在其對應的數據上,執行相同的程序,每一個實例執行一部分的程序,得到每一臺機器上的結果
結果就是A:1000, 也就是A這個單詞出現了1000次,同樣的在其他的機器上也會有A出現的次數,
全局統計(彙總:Reduce):在局部統計的基礎之上在進行一次全局統計,使用A 的哈希值對3的模(這裏是舉例說明),那麼都會是等於一個值,非A的哈希值對3的模肯定會和A 不一樣,一這種方式找到所有機器上key=A的結果,進行統計,從而使的相同key 的的結果能到達下一階段的相同的地方。
而在中間程序在每臺機器上的運行,分發,map 到reduce 階段數據的分發等都是框架取做的,程序員只需要關注的就是計算的邏輯。
Mapper任務
- 將本地輸入文件按照一定標註分片,按照block的配置大小分片,每一個輸入片由一個mapp進程處理。
- 將輸入片按照一定的規則解析爲鍵值對,有一個默認的規則是,鍵是行號,值是行內容
- 調用mapper 程序(我們寫的處理邏輯),在2階段解析出來的每一個鍵值對,每一對會調用一次mapper,對輸入的鍵值在處理,生成的還會是鍵值對
- 對3階段輸出的鍵值對進行分區,比較是基於鍵的,分類多少個區就是Reduce任務運行的數量,比如我們的鍵表示省份(如北京、上海、山東等),那麼就可以按照不同省份進行分區,同一個省份的鍵值對劃分到一個區中。
- 對每個分區中的鍵值進行排序。
Reduce任務:
- 調用reduce方法,一個鍵會對應很多的值,(<a,1>,<a,3>...),鍵相等的鍵值對調用一次reduce方法,每次調用會產生零個或者多個鍵值對。最後把這些輸出的鍵值對寫入到HDFS文件中。
在你跑程序之前還應該配置yarn集羣,這個集羣負責機器資源的分配,配置文件
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.resourcemanager.hostname</name>
<value>master</value>
</property>
yarn.resourcemanager.hostname 的值就是yarn主節點的機器(就好比使 dfs 的namenode),nodemanager也最好能放在和dataNode的機器上,因爲在跑程序的時候是在yarn的node上跑的,此時這些node離數據越近自然也就越好了,當啓動start-yarn.sh腳本的時候,這個腳本也會去讀slaves的配置文件,然後將配置文件中的那些node 中都會去啓動nodemanager,這樣nodemanager和dataNode就都在一起了。
還需要配置一個文件:指定mp程序在單機運行的時候就不需要這個配置,但是需要分佈式運行,那麼就需要在yarn上運行。
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>
import java.io.IOException;
/*
KEYIN: 是MR提供的程序讀取到一行數據的始偏移量 Long
VALUEIN: 使MR提供的程序讀取到一行數據的內容 String
KEYOUT: 是用戶邏輯處理方法返回處理完成之後返回給框架中key 的類型 String
VALUEOUT: 是用戶邏輯處理方法返回處理完成之後返回給框架中key 對應的value 的值 Integer
Long, String, Integer 等java 的類型是不能在hadoop中傳輸,hadoop 有自己的這些類型,產生這些類型的原因
是數據需要在hadoop 機器之間需要傳輸,序列化, 反序列化等有較大開銷,
Long: LongWritable
String: Text
Int: IntWritable
*/
public class Map extends Mapper<LongWritable, Text, Text, IntWritable> {
/*
MR 提供的方法,沒讀一行數據就會調用一次我們寫的map方法,數據已經被框架傳遞夠來
只需要寫計算數據的邏輯
*/
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String line = value.toString();
String[] split = line.split(" ");
for (String k:split) {
context.write(new Text(k), new IntWritable(1));
}
}
}
public class Red extends Reducer<Text, IntWritable,Text, IntWritable> {
/*
MR 框架提供的reduce端程序接受到的是每一組數據key是一樣的,但是 values是會有很多個得,
這裏如 a:1, a:1, a:1, a:1,整理好一組後調一次reduce
*/
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
int cnt = 0;
for (IntWritable val:values) {
cnt += val.get();
}
context.write(key, new IntWritable(cnt));
}
}
public class JobSubmiter {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf);
// 設置整個job需要的jar包
// 通過JobSubmiter來找到其他依賴WCMapper和WCReducer
job.setJarByClass(JobSubmiter.class);
// 本job使用的mapper和reducer類
job.setMapperClass(Map.class);
job.setReducerClass(Red.class);
// 指定reducer的輸出kv類型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
// 指定mapper的輸出kv類型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
// 定義輸入,及數據位置
// job.setInputFormatClass(TextInputFormat.class);
FileInputFormat.setInputPaths(job,new Path("/webLog/input"));
// 定義輸出,及輸出位置
// job.setOutputFormatClass(TextOutputFormat.class);
FileOutputFormat.setOutputPath(job, new Path("/webLog/output"));
// 向yarn 提交
boolean completion = job.waitForCompletion(true);// 打印程序運行進度
System.exit(completion?0:1);
}
}
本地機器上傳到集羣
scp hadooptest2.jar [email protected]:/root
運行:
hadoop jar hadooptest2.jar MapReduce.JobSubmiter