├── sqoop.txt
├── README.md
├── hadoop_learning
├── src
│ └── main
│ │ ├── resources
│ │ └── log4j2.properties
│ │ └── java
│ │ ├── outline_calcul
│ │ ├── StringUtils.java
│ │ └── AppDataClean.java
│ │ └── example
│ │ └── WordCount.java
└── pom.xml
├── createTable.sql
└── calculate.sh
/sqoop.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JRhuang-96/offline-hadoop/HEAD/sqoop.txt
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # offline-hadoop
2 | Hadoop离线计算 :模拟 使用hadoop MR 进行数据清洗,再使用shell 脚本执行hive 进行数据统计,维度分析
3 |
4 | ## 完整项目架构:
5 |
6 | #### 1.收集数据: 使用flume 收集 web logs 到 HDFS上;
7 | #### 2.清洗数据: 使用 Hadoop MR 清洗数据;
8 | #### 3.处理数据: 使用 HQL 分析数据, 求出日活、日活维度分析、日新、日新维度分析等;
9 | #### 4.导出数据: 使用sqoop将数据导出到mysql 中;
10 | #### 5.编写shell 脚本: 设置每天启动处理数据,重复以上流程.
11 |
12 | -------
13 |
本项目只实现
14 | 清洗数据-->处理数据-->shell脚本启动处理数据
15 |
--------------------------------------------------------------------------------
/hadoop_learning/src/main/resources/log4j2.properties:
--------------------------------------------------------------------------------
1 |
2 | # this is the basic properties
3 | #appender.console.type = Console
4 | #appender.console.blacklist = console
5 | #appender.console.layout.type = PatternLayout
6 | #
7 | #rootLogger.level = info
8 | #rootLogger.appenderRef.console.ref = console
9 |
10 | #-----------
11 |
12 | log4j.rootCategory=ERROR, console
13 | log4j.appender.console=org.apache.log4j.ConsoleAppender
14 | log4j.appender.console.target=System.err
15 | log4j.appender.console.layout=org.apache.log4j.PatternLayout
16 | log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n
17 |
18 | # Set the default spark-shell log level to WARN. When running the spark-shell, the
19 | # log level for this class is used to overwrite the root logger's log level, so that
20 | # the user can have different defaults for the shell and regular Spark apps.
21 | log4j.logger.org.apache.spark.repl.Main=WARN
22 |
23 | # Settings to quiet third party logs that are too verbose
24 | log4j.logger.org.spark_project.jetty=WARN
25 | log4j.logger.org.spark_project.jetty.util.component.AbstractLifeCycle=ERROR
26 | log4j.logger.org.apache.spark.repl.SparkIMain$exprTyper=ERROR
27 | log4j.logger.org.apache.spark.repl.SparkILoop$SparkILoopInterpreter=ERROR
28 | log4j.logger.org.apache.parquet=ERROR
29 | log4j.logger.parquet=ERROR
30 |
31 | # SPARK-9183: Settings to avoid annoying messages when looking up nonexistent UDFs in SparkSQL with Hive support
32 | log4j.logger.org.apache.hadoop.hive.metastore.RetryingHMSHandler=FATAL
33 | log4j.logger.org.apache.hadoop.hive.ql.exec.FunctionRegistry=ERROR
--------------------------------------------------------------------------------
/hadoop_learning/src/main/java/outline_calcul/StringUtils.java:
--------------------------------------------------------------------------------
1 | package outline_calcul;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 | import org.apache.commons.lang3.time.FastDateFormat;
5 |
6 | import java.text.SimpleDateFormat;
7 |
8 | public class StringUtils {
9 |
10 | public static String getStr(JSONObject json){
11 | StringBuffer buffer = new StringBuffer();
12 | buffer.append(json.getString("imei")).append(" ").append(json.getString("sdk_ver")).append(" ");
13 | buffer.append(json.getString("time_zone")).append(" ").append(json.getString("commit_id")).append(" ");
14 | buffer.append(json.getString("commit_time")).append(" ").append(json.getString("pid")).append(" ");
15 | buffer.append(json.getString("app_token")).append(" ").append(json.getString("app_id")).append(" ");
16 | buffer.append(json.getString("device_id")).append(" ").append(json.getString("device_id_type")).append(" ");
17 | buffer.append(json.getString("release_channel")).append(" ").append(json.getString("app_ver_name")).append(" ");
18 | buffer.append(json.getString("app_ver_code")).append(" ").append(json.getString("os_name")).append(" ");
19 | buffer.append(json.getString("os_ver")).append(" ").append(json.getString("language")).append(" ");
20 | buffer.append(json.getString("country")).append(" ").append(json.getString("manufacture")).append(" ");
21 | buffer.append(json.getString("device_model")).append(" ").append(json.getString("resolution")).append(" ");
22 | buffer.append(json.getString("net_type")).append(" ").append(json.getString("account")).append(" ");
23 | buffer.append(json.getString("app_device_id")).append(" ").append(json.getString("mac")).append(" ");
24 | buffer.append(json.getString("android_id")).append(" ").append(json.getString("user_id")).append(" ");
25 | buffer.append(json.getString("cid_sn")).append(" ").append(json.getString("build_num")).append(" ");
26 | buffer.append(json.getString("mobile_data_type")).append(" ").append(json.getString("promotion_channel")).append(" ");
27 | buffer.append(json.getString("carrier")).append(" ").append(json.getString("city"));
28 |
29 | return buffer.toString();
30 |
31 | }
32 |
33 | /**
34 | 获取当前的 年月日
35 | */
36 | public static String getFileName() {
37 | SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
38 | return format.format(System.currentTimeMillis());
39 | }
40 |
41 | public static String getTime(String oldTime){
42 | FastDateFormat fastDateFormat = FastDateFormat.getInstance("yyyyMMdd");
43 |
44 | return fastDateFormat.format(oldTime);
45 | }
46 |
47 |
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/hadoop_learning/src/main/java/example/WordCount.java:
--------------------------------------------------------------------------------
1 | package example;
2 |
3 | import org.apache.hadoop.conf.Configuration;
4 | import org.apache.hadoop.fs.Path;
5 | import org.apache.hadoop.io.IntWritable;
6 | import org.apache.hadoop.io.Text;
7 | import org.apache.hadoop.mapreduce.Job;
8 | import org.apache.hadoop.mapreduce.Mapper;
9 | import org.apache.hadoop.mapreduce.Reducer;
10 | import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
11 | import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
12 | import org.apache.hadoop.mapreduce.lib.output.LazyOutputFormat;
13 | import org.apache.hadoop.mapreduce.lib.output.MultipleOutputs;
14 | import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
15 | import outline_calcul.StringUtils;
16 |
17 | import java.io.IOException;
18 | import java.util.StringTokenizer;
19 |
20 | /**
21 | Hadoop最新版本的MapReduce Release 0.20.0的API包括了一个全新的Mapreduce JAVA API,有时候也称为上下文对象。
22 | 新的API类型上不兼容以前的API,所以,以前的应用程序需要重写才能使新的API发挥其作用 。
23 | 新的API和旧的API之间有下面几个明显的区别。
24 | 新的API倾向于使用抽象类,而不是接口,因为这更容易扩展。例如,你可以添加一个方法(用默认的实现)到一个抽象类而不需修改类之前的实现方法。在新的API中,Mapper和Reducer是抽象类。
25 | 新的API是在org.apache.hadoop.mapreduce包(和子包)中的。之前版本的API则是放在org.apache.hadoop.mapred中的。
26 | 新的API广泛使用context object(上下文对象),并允许用户代码与MapReduce系统进行通信。例如,MapContext基本上充当着JobConf的OutputCollector和Reporter的角色。
27 | 新的API同时支持"推"和"拉"式的迭代。在这两个新老API中,键/值记录对被推mapper中,但除此之外,新的API允许把记录从map()方法中拉出,这也适用于reducer。"拉"式的一个有用的例子是分批处理记录,而不是一个接一个。
28 | 新的API统一了配置。旧的API有一个特殊的JobConf对象用于作业配置,这是一个对于Hadoop通常的Configuration对象的扩展。
29 | 在新的API中,这种区别没有了,所以作业配置通过Configuration来完成。作业控制的执行由Job类来负责,而不是JobClient,它在新的API中已经荡然无存。
30 |
31 | */
32 | //这是新版API
33 | public class WordCount{
34 |
35 | public static class TokenizerMapper extends Mapper