细 细 品 味 Hadoop Hadoop 集 群 ( 第 6 期 ) 精 华 集 锦 csaxp 虾 皮 工 作 室 http://www.cnblogs.com/xia520pi/ 2012 年 5 月 15 日
Hadoop 集 群 ( 第 6 期 ) WordCount 运 行 详 解 1 MapReduce 理 论 简 介 1.1 MapReduce 编 程 模 型 MapReduce 采 用 分 而 治 之 的 思 想, 把 对 大 规 模 数 据 集 的 操 作, 分 发 给 一 个 主 节 点 管 理 下 的 各 个 分 节 点 共 同 完 成, 然 后 通 过 整 合 各 个 节 点 的 中 间 结 果, 得 到 最 终 结 果 简 单 地 说,MapReduce 就 是 任 务 的 分 解 与 结 果 的 汇 总 在 Hadoop 中, 用 于 执 行 MapReduce 任 务 的 机 器 角 色 有 两 个 : 一 个 是 JobTracker; 另 一 个 是 TaskTracker,JobTracker 是 用 于 调 度 工 作 的,TaskTracker 是 用 于 执 行 工 作 的 一 个 Hadoop 集 群 中 只 有 一 台 JobTracker 在 分 布 式 计 算 中,MapReduce 框 架 负 责 处 理 了 并 行 编 程 中 分 布 式 存 储 工 作 调 度 负 载 均 衡 容 错 均 衡 容 错 处 理 以 及 网 络 通 信 等 复 杂 问 题, 把 处 理 过 程 高 度 抽 象 为 两 个 函 数 : map 和 reduce,map 负 责 把 任 务 分 解 成 多 个 任 务,reduce 负 责 把 分 解 后 多 任 务 处 理 的 结 果 汇 总 起 来 需 要 注 意 的 是, 用 MapReduce 来 处 理 的 数 据 集 ( 或 任 务 ) 必 须 具 备 这 样 的 特 点 : 待 处 理 的 数 据 集 可 以 分 解 成 许 多 小 的 数 据 集, 而 且 每 一 个 小 数 据 集 都 可 以 完 全 并 行 地 进 行 处 理 1.2 MapReduce 处 理 过 程 在 Hadoop 中, 每 个 MapReduce 任 务 都 被 初 始 化 为 一 个 Job, 每 个 Job 又 可 以 分 为 两 种 阶 段 :map 阶 段 和 reduce 阶 段 这 两 个 阶 段 分 别 用 两 个 函 数 表 示, 即 map 函 数 和 reduce 函 数 map 函 数 接 收 一 个 <key,value> 形 式 的 输 入, 然 后 同 样 产 生 一 个 <key,value> 形 式 的 中 间 输 出,Hadoop 函 数 接 收 一 个 如 <key,(list of values)> 形 式 的 输 入, 然 后 对 这 个 value 集 合 进 行 处 理, 每 个 reduce 产 生 0 或 1 个 输 出,reduce 的 输 出 也 是 <key,value> 形 式 的 MapReduce 处 理 大 数 据 集 的 过 程 河 北 工 业 大 学 软 件 工 程 与 理 论 实 验 室 编 辑 : 虾 皮 1
2 运 行 WordCount 程 序 单 词 计 数 是 最 简 单 也 是 最 能 体 现 MapReduce 思 想 的 程 序 之 一, 可 以 称 为 MapReduce 版 Hello World, 该 程 序 的 完 整 代 码 可 以 在 Hadoop 安 装 包 的 src/examples 目 录 下 找 到 单 词 计 数 主 要 完 成 功 能 是 : 统 计 一 系 列 文 本 文 件 中 每 个 单 词 出 现 的 次 数, 如 下 图 所 示 2.1 准 备 工 作 现 在 以 hadoop 普 通 用 户 登 录 Master.Hadoop 服 务 器 1) 创 建 本 地 示 例 文 件 首 先 在 /home/hadoop 目 录 下 创 建 文 件 夹 file 接 着 创 建 两 个 文 本 文 件 file1.txt 和 file2.txt, 使 file1.txt 内 容 为 Hello World, 而 file2.txt 的 内 容 为 Hello Hadoop 河 北 工 业 大 学 软 件 工 程 与 理 论 实 验 室 编 辑 : 虾 皮 2
2) 在 HDFS 上 创 建 输 入 文 件 夹 3) 上 传 本 地 file 中 文 件 到 集 群 的 input 目 录 下 2.2 运 行 例 子 1) 在 集 群 上 运 行 WordCount 程 序 备 注 : 以 input 作 为 输 入 目 录,output 目 录 作 为 输 出 目 录 已 经 编 译 好 的 WordCount 的 Jar 在 /usr/hadoop 下 面, 就 是 hadoop-examples-1.0.0.jar, 所 以 在 下 面 执 行 命 令 时 记 得 把 路 径 写 全 了, 不 然 会 提 示 找 不 到 该 Jar 包 2)MapReduce 执 行 过 程 显 示 信 息 Hadoop 命 令 会 启 动 一 个 JVM 来 运 行 这 个 MapReduce 程 序, 并 自 动 获 得 Hadoop 的 配 置, 同 时 把 类 的 路 径 ( 及 其 依 赖 关 系 ) 加 入 到 Hadoop 的 库 中 以 上 就 是 Hadoop Job 的 运 行 记 录, 从 这 里 可 以 看 到, 这 个 Job 被 赋 予 了 一 个 ID 号 :job_201202292213_0002, 而 且 得 知 输 入 文 件 有 两 个 (Total input paths to process : 2), 同 时 还 可 以 了 解 map 的 输 入 输 出 记 录 (record 数 及 字 节 数 ), 以 及 reduce 输 入 输 出 记 录 比 如 说, 在 本 例 中,map 的 task 数 量 是 2 个,reduce 河 北 工 业 大 学 软 件 工 程 与 理 论 实 验 室 编 辑 : 虾 皮 3
的 task 数 量 是 一 个 map 的 输 入 record 数 是 2 个, 输 出 record 数 是 4 个 等 信 息 2.3 查 看 结 果 1) 查 看 HDFS 上 output 目 录 内 容 从 上 图 中 知 道 生 成 了 三 个 文 件, 我 们 的 结 果 在 part-r-00000 中 2) 查 看 结 果 输 出 文 件 内 容 3 WordCount 源 码 分 析 3.1 特 别 数 据 类 型 介 绍 Hadoop 提 供 了 如 下 内 容 的 数 据 类 型, 这 些 数 据 类 型 都 实 现 了 WritableComparable 接 口, 以 便 用 这 些 类 型 定 义 的 数 据 可 以 被 序 列 化 进 行 网 络 传 输 和 文 件 存 储, 以 及 进 行 大 小 比 较 BooleanWritable: 标 准 布 尔 型 数 值 ByteWritable: 单 字 节 数 值 DoubleWritable: 双 字 节 数 FloatWritable: 浮 点 数 IntWritable: 整 型 数 LongWritable: 长 整 型 数 Text: 使 用 UTF8 格 式 存 储 的 文 本 NullWritable: 当 <key,value> 中 的 key 或 value 为 空 时 使 用 3.2 旧 的 WordCount 分 析 1) 源 代 码 程 序 package org.apache.hadoop.examples; 河 北 工 业 大 学 软 件 工 程 与 理 论 实 验 室 编 辑 : 虾 皮 4
import java.io.ioexception; import java.util.iterator; import java.util.stringtokenizer; import org.apache.hadoop.fs.path; import org.apache.hadoop.io.intwritable; import org.apache.hadoop.io.longwritable; import org.apache.hadoop.io.text; import org.apache.hadoop.mapred.fileinputformat; import org.apache.hadoop.mapred.fileoutputformat; import org.apache.hadoop.mapred.jobclient; import org.apache.hadoop.mapred.jobconf; import org.apache.hadoop.mapred.mapreducebase; import org.apache.hadoop.mapred.mapper; import org.apache.hadoop.mapred.outputcollector; import org.apache.hadoop.mapred.reducer; import org.apache.hadoop.mapred.reporter; import org.apache.hadoop.mapred.textinputformat; import org.apache.hadoop.mapred.textoutputformat; public class WordCount public static class Map extends MapReduceBase implements Mapper<LongWritable, Text, Text, IntWritable> private final static IntWritable one = new IntWritable( 1 ); private Text word = new Text(); public void map(longwritable key, Text value, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException String line = value.tostring(); StringTokenizer tokenizer = new StringTokenizer(line); while (tokenizer.hasmoretokens()) word.set(tokenizer.nexttoken()); output.collect(word, one); 河 北 工 业 大 学 软 件 工 程 与 理 论 实 验 室 编 辑 : 虾 皮 5
public static class Reduce extends MapReduceBase implements Reducer<Text, IntWritable, Text, IntWritable> public void reduce(text key, Iterator<IntWritable> values, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException int sum = 0 ; while (values.hasnext()) sum += values.next().get(); output.collect(key, new IntWritable(sum)); public static void main(string[] args) throws Exception JobConf conf = new JobConf(WordCount. class ); conf.setjobname("wordcount" ); conf.setoutputkeyclass(text.class ); conf.setoutputvalueclass(intwritable.class ); conf.setmapperclass(map.class ); conf.setcombinerclass(reduce.class ); conf.setreducerclass(reduce.class ); conf.setinputformat(textinputformat.class ); conf.setoutputformat(textoutputformat.class ); FileInputFormat.setInputPaths(conf, new Path(args[ 0 ])); FileOutputFormat.setOutputPath(conf, new Path(args[ 1 ])); JobClient.runJob(conf); 3) 主 方 法 Main 分 析 public static void main(string[] args) throws Exception JobConf conf = new JobConf(WordCount. class ); conf.setjobname("wordcount" ); 河 北 工 业 大 学 软 件 工 程 与 理 论 实 验 室 编 辑 : 虾 皮 6
conf.setoutputkeyclass(text.class ); conf.setoutputvalueclass(intwritable.class ); conf.setmapperclass(map.class ); conf.setcombinerclass(reduce.class ); conf.setreducerclass(reduce.class ); conf.setinputformat(textinputformat.class ); conf.setoutputformat(textoutputformat.class ); FileInputFormat.setInputPaths(conf, new Path(args[ 0 ])); FileOutputFormat.setOutputPath(conf, new Path(args[ 1 ])); JobClient.runJob(conf); 首 先 讲 解 一 下 Job 的 初 始 化 过 程 main 函 数 调 用 Jobconf 类 来 对 MapReduce Job 进 行 初 始 化, 然 后 调 用 setjobname() 方 法 命 名 这 个 Job 对 Job 进 行 合 理 的 命 名 有 助 于 更 快 地 找 到 Job, 以 便 在 JobTracker 和 Tasktracker 的 页 面 中 对 其 进 行 监 视 JobConf conf = new JobConf(WordCount. class ); conf.setjobname("wordcount" ); 接 着 设 置 Job 输 出 结 果 <key,value> 的 中 key 和 value 数 据 类 型, 因 为 结 果 是 < 单 词, 个 数 >, 所 以 key 设 置 为 Text 类 型, 相 当 于 Java 中 String 类 型 Value 设 置 为 IntWritable, 相 当 于 Java 中 的 int 类 型 conf.setoutputkeyclass(text.class ); conf.setoutputvalueclass(intwritable.class ); 然 后 设 置 Job 处 理 的 Map( 拆 分 ) Combiner( 中 间 结 果 合 并 ) 以 及 Reduce( 合 并 ) 的 相 关 处 理 类 这 里 用 Reduce 类 来 进 行 Map 产 生 的 中 间 结 果 合 并, 避 免 给 网 络 数 据 传 输 产 生 压 力 conf.setmapperclass(map.class ); conf.setcombinerclass(reduce.class ); conf.setreducerclass(reduce.class ); 接 着 就 是 调 用 setinputpath() 和 setoutputpath() 设 置 输 入 输 出 路 径 conf.setinputformat(textinputformat.class ); conf.setoutputformat(textoutputformat.class ); 河 北 工 业 大 学 软 件 工 程 与 理 论 实 验 室 编 辑 : 虾 皮 7
(1)InputFormat 和 InputSplit InputSplit 是 Hadoop 定 义 的 用 来 传 送 给 每 个 单 独 的 map 的 数 据,InputSplit 存 储 的 并 非 数 据 本 身, 而 是 一 个 分 片 长 度 和 一 个 记 录 数 据 位 置 的 数 组 生 成 InputSplit 的 方 法 可 以 通 过 InputFormat() 来 设 置 当 数 据 传 送 给 map 时,map 会 将 输 入 分 片 传 送 到 InputFormat,InputFormat 则 调 用 方 法 getrecordreader() 生 成 RecordReader,RecordReader 再 通 过 creatkey() creatvalue() 方 法 创 建 可 供 map 处 理 的 <key,value> 对 简 而 言 之,InputFormat() 方 法 是 用 来 生 成 可 供 map 处 理 的 <key,value> 对 的 Hadoop 预 定 义 了 多 种 方 法 将 不 同 类 型 的 输 入 数 据 转 化 为 map 能 够 处 理 的 <key,value> 对, 它 们 都 继 承 自 InputFormat, 分 别 是 : InputFormat ---BaileyBorweinPlouffe.BbpInputFormat ---ComposableInputFormat ---CompositeInputFormat ---DBInputFormat ---DistSum.Machine.AbstractInputFormat ---FileInputFormat ---CombineFileInputFormat ---KeyValueTextInputFormat ---NLineInputFormat ---SequenceFileInputFormat ---TeraInputFormat ---TextInputFormat 其 中 TextInputFormat 是 Hadoop 默 认 的 输 入 方 法, 在 TextInputFormat 中, 每 个 文 件 ( 或 其 一 部 分 ) 都 会 单 独 地 作 为 map 的 输 入, 而 这 个 是 继 承 自 FileInputFormat 的 之 后, 每 行 数 据 都 会 生 成 一 条 记 录, 每 条 记 录 则 表 示 成 <key,value> 形 式 : key 值 是 每 个 数 据 的 记 录 在 数 据 分 片 中 字 节 偏 移 量, 数 据 类 型 是 LongWritable; value 值 是 每 行 的 内 容, 数 据 类 型 是 Text (2)OutputFormat 每 一 种 输 入 格 式 都 有 一 种 输 出 格 式 与 其 对 应 默 认 的 输 出 格 式 是 TextOutputFormat, 这 种 输 出 方 式 与 输 入 类 似, 会 将 每 条 记 录 以 一 行 的 形 式 存 入 文 本 文 件 不 过, 它 的 键 和 值 可 以 是 任 意 形 式 的, 因 为 程 序 内 容 会 调 用 tostring() 方 法 将 键 和 值 转 换 为 String 类 型 再 输 出 3)Map 类 中 map 方 法 分 析 public static class Map extends MapReduceBase implements Mapper<LongWritable, Text, Text, IntWritable> private final static IntWritable one = new IntWritable( 1 ); private Text word = new Text(); 河 北 工 业 大 学 软 件 工 程 与 理 论 实 验 室 编 辑 : 虾 皮 8
public void map(longwritable key, Text value, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException String line = value.tostring(); StringTokenizer tokenizer = new StringTokenizer(line); while (tokenizer.hasmoretokens()) word.set(tokenizer.nexttoken()); output.collect(word, one); Map 类 继 承 自 MapReduceBase, 并 且 它 实 现 了 Mapper 接 口, 此 接 口 是 一 个 规 范 类 型, 它 有 4 种 形 式 的 参 数, 分 别 用 来 指 定 map 的 输 入 key 值 类 型 输 入 value 值 类 型 输 出 key 值 类 型 和 输 出 value 值 类 型 在 本 例 中, 因 为 使 用 的 是 TextInputFormat, 它 的 输 出 key 值 是 LongWritable 类 型, 输 出 value 值 是 Text 类 型, 所 以 map 的 输 入 类 型 为 <LongWritable,Text> 在 本 例 中 需 要 输 出 <word,1> 这 样 的 形 式, 因 此 输 出 的 key 值 类 型 是 Text, 输 出 的 value 值 类 型 是 IntWritable 实 现 此 接 口 类 还 需 要 实 现 map 方 法,map 方 法 会 具 体 负 责 对 输 入 进 行 操 作, 在 本 例 中, map 方 法 对 输 入 的 行 以 空 格 为 单 位 进 行 切 分, 然 后 使 用 OutputCollect 收 集 输 出 的 <word,1> 4)Reduce 类 中 reduce 方 法 分 析 public static class Reduce extends MapReduceBase implements Reducer<Text, IntWritable, Text, IntWritable> public void reduce(text key, Iterator<IntWritable> values, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException int sum = 0 ; while (values.hasnext()) sum += values.next().get(); output.collect(key, new IntWritable(sum)); Reduce 类 也 是 继 承 自 MapReduceBase 的, 需 要 实 现 Reducer 接 口 Reduce 类 以 map 的 输 出 作 为 输 入, 因 此 Reduce 的 输 入 类 型 是 <Text,Intwritable> 而 Reduce 的 输 出 是 单 词 河 北 工 业 大 学 软 件 工 程 与 理 论 实 验 室 编 辑 : 虾 皮 9
和 它 的 数 目, 因 此, 它 的 输 出 类 型 是 <Text,IntWritable> Reduce 类 也 要 实 现 reduce 方 法, 在 此 方 法 中,reduce 函 数 将 输 入 的 key 值 作 为 输 出 的 key 值, 然 后 将 获 得 多 个 value 值 加 起 来, 作 为 输 出 的 值 3.3 新 的 WordCount 分 析 1) 源 代 码 程 序 package org.apache.hadoop.examples; 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; public class WordCount 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 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> 河 北 工 业 大 学 软 件 工 程 与 理 论 实 验 室 编 辑 : 虾 皮 10
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(); 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); 1)Map 过 程 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 河 北 工 业 大 学 软 件 工 程 与 理 论 实 验 室 编 辑 : 虾 皮 11
StringTokenizer itr = new StringTokenizer(value.toString()); while (itr.hasmoretokens()) word.set(itr.nexttoken()); context.write(word, one); Map 过 程 需 要 继 承 org.apache.hadoop.mapreduce 包 中 Mapper 类, 并 重 写 其 map 方 法 通 过 在 map 方 法 中 添 加 两 句 把 key 值 和 value 值 输 出 到 控 制 台 的 代 码, 可 以 发 现 map 方 法 中 value 值 存 储 的 是 文 本 文 件 中 的 一 行 ( 以 回 车 符 为 行 结 束 标 记 ), 而 key 值 为 该 行 的 首 字 母 相 对 于 文 本 文 件 的 首 地 址 的 偏 移 量 然 后 StringTokenizer 类 将 每 一 行 拆 分 成 为 一 个 个 的 单 词, 并 将 <word,1> 作 为 map 方 法 的 结 果 输 出, 其 余 的 工 作 都 交 有 MapReduce 框 架 处 理 2)Reduce 过 程 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); Reduce 过 程 需 要 继 承 org.apache.hadoop.mapreduce 包 中 Reducer 类, 并 重 写 其 reduce 方 法 Map 过 程 输 出 <key,values> 中 key 为 单 个 单 词, 而 values 是 对 应 单 词 的 计 数 值 所 组 成 的 列 表,Map 的 输 出 就 是 Reduce 的 输 入, 所 以 reduce 方 法 只 要 遍 历 values 并 求 和, 即 可 得 到 某 个 单 词 的 总 次 数 3) 执 行 MapReduce 任 务 public static void main(string[] args) throws Exception Configuration conf = new Configuration(); String[] otherargs = new GenericOptionsParser(conf, args).getremainingargs(); if (otherargs.length!= 2) System.err.println("Usage: wordcount <in> <out>"); 河 北 工 业 大 学 软 件 工 程 与 理 论 实 验 室 编 辑 : 虾 皮 12
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); 在 MapReduce 中, 由 Job 对 象 负 责 管 理 和 运 行 一 个 计 算 任 务, 并 通 过 Job 的 一 些 方 法 对 任 务 的 参 数 进 行 相 关 的 设 置 此 处 设 置 了 使 用 TokenizerMapper 完 成 Map 过 程 中 的 处 理 和 使 用 IntSumReducer 完 成 Combine 和 Reduce 过 程 中 的 处 理 还 设 置 了 Map 过 程 和 Reduce 过 程 的 输 出 类 型 :key 的 类 型 为 Text,value 的 类 型 为 IntWritable 任 务 的 输 出 和 输 入 路 径 则 由 命 令 行 参 数 指 定, 并 由 FileInputFormat 和 FileOutputFormat 分 别 设 定 完 成 相 应 任 务 的 参 数 设 定 后, 即 可 调 用 job.waitforcompletion() 方 法 执 行 任 务 4 WordCount 处 理 过 程 本 节 将 对 WordCount 进 行 更 详 细 的 讲 解 详 细 执 行 步 骤 如 下 : 1) 将 文 件 拆 分 成 splits, 由 于 测 试 用 的 文 件 较 小, 所 以 每 个 文 件 为 一 个 split, 并 将 文 件 按 行 分 割 形 成 <key,value> 对, 如 图 4-1 所 示 这 一 步 由 MapReduce 框 架 自 动 完 成, 其 中 偏 移 量 ( 即 key 值 ) 包 括 了 回 车 所 占 的 字 符 数 (Windows 和 Linux 环 境 会 不 同 ) 图 4-1 分 割 过 程 2) 将 分 割 好 的 <key,value> 对 交 给 用 户 定 义 的 map 方 法 进 行 处 理, 生 成 新 的 <key,value> 对, 如 图 4-2 所 示 河 北 工 业 大 学 软 件 工 程 与 理 论 实 验 室 编 辑 : 虾 皮 13
分 割 结 果 <0, Hello World > <12, Bye World > map() map 方 法 输 出 <World,1> <World,1> <0, Hello Hadoop > <13, Bye Hadoop > map() <Hadoop,1> <Hadoop,1> 图 4-2 执 行 map 方 法 3) 得 到 map 方 法 输 出 的 <key,value> 对 后,Mapper 会 将 它 们 按 照 key 值 进 行 排 序, 并 执 行 Combine 过 程, 将 key 至 相 同 value 值 累 加, 得 到 Mapper 的 最 终 输 出 结 果 如 图 4-3 所 示 map 方 法 输 出 排 序 结 果 Combine 输 出 <World,1> <World,1> Map 端 排 序 <World,1> <World,1> Combine 过 程 <World,2> <Hadoop,1> <Hadoop,1> Map 端 排 序 <Hadoop,1> <Hadoop,1> Combine 过 程 <Hadoop,2> 图 4-3 Map 端 排 序 及 Combine 过 程 4)Reducer 先 对 从 Mapper 接 收 的 数 据 进 行 排 序, 再 交 由 用 户 自 定 义 的 reduce 方 法 进 行 处 理, 得 到 新 的 <key,value> 对, 并 作 为 WordCount 的 输 出 结 果, 如 图 4-4 所 示 Combine 输 出 排 序 结 果 Reduce 输 出 <World,2> <Hadoop,2> Reduce 端 排 序 <Bye,list(1,1)> <Hadoop,list(2)> <Hello,list(1,1)> <Word,list(2)> reduce() <Bye,2> <Hadoop,2> <Hello,2> <Word,2> 图 4-4 Reduce 端 排 序 及 输 出 结 果 河 北 工 业 大 学 软 件 工 程 与 理 论 实 验 室 编 辑 : 虾 皮 14
5 MapReduce 新 旧 改 变 Hadoop 最 新 版 本 的 MapReduce Release 0.20.0 的 API 包 括 了 一 个 全 新 的 Mapreduce JAVA API, 有 时 候 也 称 为 上 下 文 对 象 新 的 API 类 型 上 不 兼 容 以 前 的 API, 所 以, 以 前 的 应 用 程 序 需 要 重 写 才 能 使 新 的 API 发 挥 其 作 用 新 的 API 和 旧 的 API 之 间 有 下 面 几 个 明 显 的 区 别 新 的 API 倾 向 于 使 用 抽 象 类, 而 不 是 接 口, 因 为 这 更 容 易 扩 展 例 如, 你 可 以 添 加 一 个 方 法 ( 用 默 认 的 实 现 ) 到 一 个 抽 象 类 而 不 需 修 改 类 之 前 的 实 现 方 法 在 新 的 API 中,Mapper 和 Reducer 是 抽 象 类 新 的 API 是 在 org.apache.hadoop.mapreduce 包 ( 和 子 包 ) 中 的 之 前 版 本 的 API 则 是 放 在 org.apache.hadoop.mapred 中 的 新 的 API 广 泛 使 用 context object( 上 下 文 对 象 ), 并 允 许 用 户 代 码 与 MapReduce 系 统 进 行 通 信 例 如,MapContext 基 本 上 充 当 着 JobConf 的 OutputCollector 和 Reporter 的 角 色 新 的 API 同 时 支 持 " 推 " 和 " 拉 " 式 的 迭 代 在 这 两 个 新 老 API 中, 键 / 值 记 录 对 被 推 mapper 中, 但 除 此 之 外, 新 的 API 允 许 把 记 录 从 map() 方 法 中 拉 出, 这 也 适 用 于 reducer " 拉 " 式 的 一 个 有 用 的 例 子 是 分 批 处 理 记 录, 而 不 是 一 个 接 一 个 新 的 API 统 一 了 配 置 旧 的 API 有 一 个 特 殊 的 JobConf 对 象 用 于 作 业 配 置, 这 是 一 个 对 于 Hadoop 通 常 的 Configuration 对 象 的 扩 展 在 新 的 API 中, 这 种 区 别 没 有 了, 所 以 作 业 配 置 通 过 Configuration 来 完 成 作 业 控 制 的 执 行 由 Job 类 来 负 责, 而 不 是 JobClient, 它 在 新 的 API 中 已 经 荡 然 无 存 河 北 工 业 大 学 软 件 工 程 与 理 论 实 验 室 编 辑 : 虾 皮 15
编 者 简 介 基 本 信 息 姓 名 : 解 耀 伟 性 别 : 男 笔 名 : 虾 皮 民 族 : 汉 学 历 : 研 究 生 专 业 : 计 算 机 应 用 技 术 电 子 信 箱 : xieyaowei1986@163.com 学 校 : 河 北 工 业 大 学 (211 工 程 ) 求 职 意 向 希 望 在 IT 行 业 从 事 软 件 研 发 等 工 作 编 程 语 言 Java C# C ExtJS Flex 汇 编 PHP VB, 熟 练 程 度 由 左 到 右 逐 级 减 弱 个 人 经 历 大 学 期 间 1) 担 任 职 务 : 学 生 会 生 活 部 部 长 生 活 委 员 团 支 书 2) 获 得 奖 项 : 二 等 奖 学 金 (2 次 ) 三 好 学 生 (1 次 ) 研 究 生 期 间 1) 担 任 职 务 : 班 长 2) 获 得 奖 项 : 优 秀 班 干 部 (1 次 ) 工 作 经 历 实 验 室 项 目 : 国 家 863 计 划 项 目 1 项 ; 国 家 技 术 基 础 专 项 2 项 ; 河 北 省 技 术 专 项 1 项 研 究 生 课 题 : 基 于 Hadoop 分 布 式 搜 索 引 擎 研 究 个 人 评 价 性 格 开 朗, 善 于 与 人 沟 通, 上 进 心 强, 品 德 优 秀, 吃 苦 耐 劳, 喜 欢 团 队 合 作, 能 积 极 服 从 上 级 的 安 排 寄 言 相 信 您 的 信 任 与 我 的 能 力 将 为 我 们 带 来 共 同 的 成 功
参 考 文 献 感 谢 以 下 文 章 的 编 写 作 者, 没 有 你 们 的 铺 路, 我 或 许 会 走 得 很 艰 难, 参 考 不 分 先 后, 贡 献 同 等 珍 贵 1 Hadoop 实 战 陆 嘉 恒 机 械 工 业 出 版 社 2 实 战 Hadoop 刘 鹏 电 子 工 业 出 版 社 3 Hadoop 上 运 行 WordCount 以 及 本 地 调 试 地 址 :http://www.beoop.com/archives/244.html 4 命 令 行 运 行 hadoop 实 例 wordcount 程 序 地 址 :http://blog.csdn.net/xw13106209/article/details/6862480 5 Hadoop 示 例 程 序 WordCount 运 行 及 详 解 地 址 :http://samuschen.iteye.com/blog/763940 6 Hadoop 的 安 装 与 配 置 及 示 例 wordcount 的 运 行 地 址 :http://wenku.baidu.com/view/41eac9d850e2524de5187ef3.html