データクリーニングはすべてのビジネスに不可欠な部分です。コアビジネスのMapReduceプログラムを実行する前に、データは将来クリーンアップされます。多くの場合、データクリーニングのプロセスでは、Reducerプログラムではなく、Mapperプログラムを実行するだけで済みます。この記事では、主にデータクリーニングの簡単なアプリケーションを紹介します。「壊れた繭と蝶のハドゥープになる」のコラムをたどって、関連する一連の記事をご覧ください〜
目次
1.始まり
単純なアプリケーションであるため、この記事では主に例を使用してデータのETLクリーニングを紹介します。企業では、ほとんどの場合、特殊なデータクリーニングツールがあり、この記事で説明する方法はあまり使用されない可能性があることに注意してください。あまり意味がないので、簡単なアプリケーションの例を見てみましょう。
2.要件とデータ
以前のNginxログデータを引き続き使用します。データ形式は次のとおりです。
フィールドは、時間、バージョン、クライアントIP、アクセスパス、ステータス、ドメイン名、サーバーIP、サイズ、応答時間です。次に、データをクリーンアップし、200以外のアクセス要求を除外し、各行のログフィールドを5未満、フィールド数を5未満で除外する必要があります。これは私たちにとって役に立たないデータだと思います。
3、Beanクラスを定義します
package com.xzw.hadoop.mapreduce.etl;
/**
* @author: xzw
* @create_date: 2020/8/18 13:38
* @desc:
* @modifier:
* @modified_date:
* @desc:
*/
public class ETLLogBean {
private String date;
private String version;
private String clientIP;
private String url;
private String status;
private String domainName;
private String serverIP;
private String size;
private String responseDate;
private boolean valid = true;//判断数据是否合法
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(this.valid);
sb.append("\001").append(this.date);
sb.append("\001").append(this.version);
sb.append("\001").append(this.clientIP);
sb.append("\001").append(this.url);
sb.append("\001").append(this.status);
sb.append("\001").append(this.domainName);
sb.append("\001").append(this.serverIP);
sb.append("\001").append(this.size);
sb.append("\001").append(this.responseDate);
return sb.toString();
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getClientIP() {
return clientIP;
}
public void setClientIP(String clientIP) {
this.clientIP = clientIP;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getDomainName() {
return domainName;
}
public void setDomainName(String domainName) {
this.domainName = domainName;
}
public String getServerIP() {
return serverIP;
}
public void setServerIP(String serverIP) {
this.serverIP = serverIP;
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
public String getResponseDate() {
return responseDate;
}
public void setResponseDate(String responseDate) {
this.responseDate = responseDate;
}
public boolean isValid() {
return valid;
}
public void setValid(boolean valid) {
this.valid = valid;
}
}
ここで説明するために、上記のコードのtoStringメソッドでは次の区切り文字が使用されています。
sb.append("\001").append(this.date);
この\ 001セパレーターは、Hiveのデフォルトのセパレーターです。Hiveは後のコースで説明します。これを最初に知っておいてください。
第四に、マッパークラスを書く
package com.xzw.hadoop.mapreduce.etl;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException;
/**
* @author: xzw
* @create_date: 2020/8/18 13:44
* @desc:
* @modifier:
* @modified_date:
* @desc:
*/
public class ETLLogMapper02 extends Mapper<LongWritable, Text, Text, NullWritable> {
Text k = new Text();
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String line = value.toString();
//解析日志是否合法
ETLLogBean bean = parseLog(line);
if (!bean.isValid())
return;
k.set(bean.toString());
//输出
context.write(k, NullWritable.get());
}
/**
* 解析日志
* @param line
* @return
*/
private ETLLogBean parseLog(String line) {
ETLLogBean logBean = new ETLLogBean();
String[] fields = line.split("\t");
if (fields.length > 5) {
logBean.setDate(fields[0]);
logBean.setVersion(fields[1]);
logBean.setClientIP(fields[2]);
logBean.setUrl(fields[3]);
logBean.setStatus(fields[4]);
logBean.setDomainName(fields[5]);
logBean.setServerIP(fields[6]);
logBean.setSize(fields[7]);
logBean.setResponseDate(fields[8]);
if (Integer.parseInt(logBean.getStatus()) >= 400) {
logBean.setValid(false);
}
} else {
logBean.setValid(false);
}
return logBean;
}
}
5、ドライバードライバークラスを書く
package com.xzw.hadoop.mapreduce.etl;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import java.io.IOException;
/**
* @author: xzw
* @create_date: 2020/8/17 9:31
* @desc:
* @modifier:
* @modified_date:
* @desc:
*/
public class ETLLogDriver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
args = new String[]{"e:/input/nginx_log", "e:/output"};
Job job = Job.getInstance(new Configuration());
job.setJarByClass(ETLLogDriver.class);
job.setMapperClass(ETLLogMapper02.class);
job.setNumReduceTasks(0);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(NullWritable.class);
FileInputFormat.setInputPaths(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
boolean b = job.waitForCompletion(true);
System.exit(b ? 0 : 1);
}
}
6、テスト
実行して効果を確認します。
これは私たちがクリーンアップしたデータです。もう一文、バックグラウンドで実行されているログに、そのような段落があります
これはHadoopに組み込まれているカウンターであり、これらのデータを使用して複数のインジケーターを記述することができます。例:処理された入力データと出力データの量などを監視できます。
この記事は比較的単純です。このプロセスでどのような問題が発生しましたか。メッセージを残して、どのような問題が発生したかを確認させてください。