实验七 MapReduce实验:计数器
實驗指導:
7.1 實驗目的
基于MapReduce思想,編寫計數器程序。
7.2 實驗要求
能夠理解MapReduce編程思想,然后會編寫MapReduce版本計數器程序,并能執行該程序和分析執行過程。
7.3 實驗背景
7.3.1 MapReduce計數器是什么?
計數器是用來記錄job的執行進度和狀態的。它的作用可以理解為日志。我們可以在程序的某個位置插入計數器,記錄數據或者進度的變化情況。
7.3.2 MapReduce計數器能做什么?
MapReduce 計數器(Counter)為我們提供一個窗口,用于觀察 MapReduce Job 運行期的各種細節數據。對MapReduce性能調優很有幫助,MapReduce性能優化的評估大部分都是基于這些 Counter 的數值表現出來的。
在許多情況下,一個用戶需要了解待分析的數據,盡管這并非所要執行的分析任務 的核心內容。以統計數據集中無效記錄數目的任務為例,如果發現無效記錄的比例 相當高,那么就需要認真思考為何存在如此多無效記錄。是所采用的檢測程序存在 缺陷,還是數據集質量確實很低,包含大量無效記錄?如果確定是數據集的質量問 題,則可能需要擴大數據集的規模,以增大有效記錄的比例,從而進行有意義的分析。
計數器是一種收集作業統計信息的有效手段,用于質量控制或應用級統計。計數器 還可輔助診斷系統故障。如果需要將日志信息傳輸到map或reduce任務,更好的 方法通常是嘗試傳輸計數器值以監測某一特定事件是否發生。對于大型分布式作業 而言,使用計數器更為方便。首先,獲取計數器值比輸出日志更方便,其次,根據 計數器值統計特定事件的發生次數要比分析一堆日志文件容易得多。?
7.3.3 內置計數器
MapReduce 自帶了許多默認Counter,現在我們來分析這些默認 Counter 的含義,方便大家觀察 Job 結果,如輸入的字節數、輸出的字節數、Map端輸入/輸出的字節數和條數、Reduce端的輸入/輸出的字節數和條數等。下面我們只需了解這些內置計數器,知道計數器組名稱(groupName)和計數器名稱(counterName),以后使用計數器會查找groupName和counterName即可。
7.3.4 計數器使用
7.3.4.1 定義計數器
枚舉聲明計數器:
// 自定義枚舉變量Enum Counter counter = context.getCounter(Enum enum)自定義計數器:
// 自己命名groupName和counterName Counter counter = context.getCounter(String groupName,String counterName)7.3.4.2 為計數器賦值
初始化計數器:
counter.setValue(long value);//設置初始值計數器自增:
counter.increment(long incr);// 增加計數7.3.4.3 獲取計數器的值
獲取枚舉計數器的值:
Configuration conf = new Configuration(); Job job = new Job(conf, "MyCounter"); job.waitForCompletion(true); Counters counters=job.getCounters(); Counter counter=counters.findCounter(LOG_PROCESSOR_COUNTER.BAD_RECORDS_LONG);// 查找枚舉計數器,假如Enum的變量為BAD_RECORDS_LONG long value=counter.getValue();//獲取計數值獲取自定義計數器的值:
Configuration conf = new Configuration(); Job job = new Job(conf, "MyCounter"); job.waitForCompletion(true); Counters counters = job.getCounters(); Counter counter=counters.findCounter("ErrorCounter","toolong");// 假如groupName為ErrorCounter,counterName為toolong long value = counter.getValue();// 獲取計數值獲取內置計數器的值:
Configuration conf = new Configuration(); Job job = new Job(conf, "MyCounter"); job.waitForCompletion(true); Counters counters=job.getCounters(); // 查找作業運行啟動的reduce個數的計數器,groupName和counterName可以從內置計數器表格查詢(前面已經列舉有) Counter counter=counters.findCounter("org.apache.hadoop.mapreduce.JobCounter","TOTAL_LAUNCHED_REDUCES")?;// 假如groupName為org.apache.hadoop.mapreduce.JobCounter,counterName為TOTAL_LAUNCHED_REDUCES long value=counter.getValue();// 獲取計數值獲取所有計數器的值:
Configuration conf = new Configuration(); Job job = new Job(conf, "MyCounter"); Counters counters = job.getCounters(); for (CounterGroup group : counters) {for (Counter counter : group) {System.out.println(counter.getDisplayName() + ": " + counter.getName() + ": "+ counter.getValue());} }7.3.5 自定義計數器
MapReduce允許用戶編寫程序來定義計數器,計數器的值可在mapper或reducer 中增加。多個計數器由一個Java枚舉(enum)類型來定義,以便對計數器分組。一個作業可以定義的枚舉類型數量不限,各個枚舉類型所包含的字段數量也不限。枚 舉類型的名稱即為組的名稱,枚舉類型的字段就是計數器名稱。計數器是全局的。換言之,MapReduce框架將跨所有map和reduce聚集這些計數器,并在作業結束 時產生一個最終結果。
7.4 實驗步驟
7.4.1 實驗分析設計
該實驗要求學生自己實現一個計數器,統計輸入的無效數據。說明如下:
假如一個文件,規范的格式是3個字段,“\t”作為分隔符,其中有2條異常數據,一條數據是只有2個字段,一條數據是有4個字段。其內容如下所示:
jim 1 28 kate 0 26 tom 1 lily 0 29 22編寫代碼統計文檔中字段不為3個的異常數據個數。如果字段超過3個視為過長字段,字段少于3個視為過短字段。
7.4.2 編寫程序
完整代碼:
package mr?; import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Counter; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.Mapper; import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; import org.apache.hadoop.util.GenericOptionsParser;public class Counters {public static class MyCounterMap extends Mapper<LongWritable, Text, Text, Text> {public static Counter ct = null;protected void map(LongWritable key, Text value,org.apache.hadoop.mapreduce.Mapper<LongWritable, Text, Text, Text>.Context context)throws java.io.IOException, InterruptedException {String arr_value[] = value.toString().split("\t"); if (arr_value.length < 3) {ct = context.getCounter("ErrorCounter", "toolong"); // ErrorCounter為組名,toolong為組員名 ct.increment(1); // 計數器加一 } else if (arr_value.length>=3) {ct = context.getCounter("ErrorCounter", "tooshort");ct.increment(1);}} } public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {Configuration conf = new Configuration();String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();if (otherArgs.length != 2) {System.err.println("Usage: Counters <in> <out>");System.exit(2); } Job job = new Job(conf, "Counter");job.setJarByClass(Counters.class);job.setMapperClass(MyCounterMap.class);FileInputFormat.addInputPath(job, new Path(otherArgs[0]));FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));System.exit(job.waitForCompletion(true) ? 0 : 1);} }7.4.3 打包并提交
使用Eclipse開發工具將該代碼打包,選擇主類為mr.Counters。假定打包后的文件名為Counters.jar,主類Counters位于包mr下,則可使用如下命令向Hadoop集群提交本應用。
[root@master hadoop]# bin/hadoop jar Counters.jar mr.Counters /usr/counters/in/counters.txt /usr/counters/out其中“hadoop”為命令,“jar”為命令參數,后面緊跟打包。 “/usr/counts/in/counts.txt”為輸入文件在HDFS中的位置(如果沒有,自行上傳),“/usr/counts/out”為輸出文件在HDFS中的位置。
7.5 實驗結果
7.5.1 輸入數據
輸入數據如下:counters.txt(\t分割)(數據統一放在/root/data目錄下)。
jim 1 28 kate 0 26 tom 1 lily 0 29 227.5.2 輸出顯示
如圖7-1所示:
圖7-1
?
實驗操作:
步驟1?搭建Hadoop集群
首先在Hadoop下使用?sbin/start-all.sh 命令啟動集群
步驟2?上傳數據文件至HDFS
因為沒有HDFS中沒有 /usr/counters/in/ 目錄,所以要先創建數據輸入的路徑
之后將放在/root/data/7/counters.txt的數據文件上傳到剛剛創建好的路徑
步驟3
編寫計數器程序
步驟4
打包程序
步驟5?運行程序
此處應注意打包時的jar包名稱、主類名稱以及輸入輸出路徑,尤其注意大小寫,很容易出錯,博主多次入坑,需加倍留心。
步驟6?查看運行結果
總結
以上是生活随笔為你收集整理的实验七 MapReduce实验:计数器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OKR快速上手
- 下一篇: 第七章 目录监视 windows程序设计