(大数据)MapReduce开发,一个没有隐私的世界!
安全数据重新解析MR开发,接到MR开发任务。也会做一些互
移除点击此处添加图片说明文字
拿到新需求,小路乱撞。
首先拿到数据示例文档:
然后从svn上检出代码,工程如下:
需求,我们要将头文件添加到每个ac列表中。
然后在apk_list继续追加记录,也就是说,一个日志文件发过来,我们要根据这两个json格式数据要变成一个3维度变成一个表的转换,可能只立方增长,但是只要数据可以操作,就是有意义的转换。我们需要重写MapReduce程序。可能之前已经说了一些概念、wordcount等简单的介绍,现在要真正的做处理了。
写几个要经常用到的hadoop命令,
1.首先删除output文件夹:
./hdfs dfs -rmr /data/output
删除文件:
./hdfs dfs -rm /data/part-3
2.创建output文件:
./hdfs dfs -mkdir /data/output
3.改变目录权限:
./hdfs dfs -chmod 777 /data/output
4.放置文件:
./hdfs dfs -put input路径文件夹 output目标文件夹
./hdfs dfs -put /file/part-3 /data/input/
5.跑mapreduce程序:
./yarn jar /file/MapReduce_program/MR-0.0.4-SNAPSHOT.jar com.mr.DataCollection_02 /data/input/part-3 /data/output utf-8
这个是跑一个包路径下所有的文件,跑成mr的
./yarn jar /file/MapReduce_program/MR-0.0.1-SNAPSHOT.jar com.mr.DataCollection_02 /data/input/ /data/output utf-8
6.取回hdfs文件
./hdfs dfs -get /data/output/00000000apklist-r-00000 /file/output/apklist
取回所有文件,即取出文件夹:./hdfs dfs -get /data/output /file/output
关于MapReduce的介绍和搭建在前文都已经说过了,这里就不在赘述了,这篇以需求开发和解决问题为主,虽然还不知道前路到底有多少坑。
先大致看一眼源数据格式:
然后数据量贼大,我们挑一个少一点的来开发测试就好了。
然后我们看一些具体操作:
将我们的mr程序maven install
然后扔到服务器上:
然后跑mr程序:
./yarn jar /file/MapReduce_program/MR-0.0.1-SNAPSHOT.jar com.mr.DataCollection_02 /data/input/part-3 /data/output utf-8
mr跑完之后:
然后进入本地,我们看看数据:
然后我们把结果发给老大(需求方)看一下,咨询是否可用,
得到指令,就是这样,然后紧接着,新的需求全部来了:
我们一步一步做:
下面一个需求,将文件名规范化,本来
我们想将其规范化,那么我们改代码名称之后发现:
会出现错误:
那么可以说明,是不是这里不成功?那么不禁会问,这个文件名到底是怎么来的,别着急,我们继续深入其中。
可以看到,mapper函数中,已经对日期做了处理,
如果获取不到时间,会将dt格式化成这个玩意。然后在输出key时乃至后文中出现的filename中也都将这个时间作为了文件名或者key,并且将“-”格式化成“”。所以,我们调试。失败,那就去main方法里面调试。
(搜寻main方法)
到目前为止,因为拿到前期2000多行MapReducer,对于我们java程序猿来说,其实也是可以在3小时之内看懂的,然后做出正确的调试和修改:
很显然,我门道的filename了,然后在这里我们要做出更改。
然后我们改成这样:
// String fileName = (dt + ac).replace("_", "").replace("-", "");
//修改,将文件名更新,不需要那么多的0,
String fileName = ac.replace("_", "").replace("-", "");
但是,
17/06/25 17:38:28 INFO mapreduce.Job: Task Id : attempt_1498327717919_0011_r_000000_0, Status : FAILED
Error: java.lang.IllegalArgumentException: Named output '00000000apkdef' not defined
很尴尬啊,那么孤注一掷,接下来,我们干一票大的。首先将我们combiner阶段的方法输出文件名改为:
// String keyString = (dt + ac).replace("_", "").replace("-", "");
String keyString = ac.replace("_", "").replace("-", "");
接着,我们将其他无用的方法注释,全部注释,统统注释,否则会报错的:
然后执行完了,变成了我们需要的样子的一半,嘿嘿嘿:
还不错,也还算完美了。嘎嘎,一半完成,接下里想办法解决下面这一个。后面的我不想管了,我觉得代码里并没写到,所以应该是hadoop框架自己加的,所以,我们继续改写剩下的18个类的方法吧。go on。
随着我们深化修改,已经改好了这么多了:
down到本地linux环境看一下:
看一看文件内容:
那接下来,我们要处理一个痛点,就是经纬度信息的时候,我们发现了他的数据是科学计数法,并不能识别使用,需要转换。
那么,首先百度一下解决办法,写个test测试类:
显然,很好使,那我们别等了,赶紧写吧。
我们需要拿到,经纬度信息里面的la和lo两个字符串。
//科学计数法转换为字符串数字
String la = jsonObject.getString("la");
BigDecimal la_dic = new BigDecimal(la);
String la_str = la_dic.toPlainString();
String lo = jsonObject.getString("lo");
BigDecimal lo_dic = new BigDecimal(lo);
String lo_str = lo_dic.toPlainString();
result = String.format("%s|%s|%s|%s|%s|%s", baseInfo[0],
baseInfo[1], baseInfo[2], la_str, lo_str, dt);
好了,这个搞定了。我们测试一下吧。
很显然,转好了,但是。
目前看来,经纬度出现4.9E-324 这个科学计数法,出现这个问题说明定位失败了,定位失败返回的就是这个值,定位失败的原因就是库加载失败。
所以,这是一个经验,以后不用再查了,就是定位失败的意思,以后遇到这个问题,直接字符串匹配一下0.0,所以mr程序还需要改进。
所以只举一个例子:
String lo_str;
String lo = jsonObject.getString("lo");
if("4.9E-324".equals(lo)){
lo_str="0.0";
}else{
BigDecimal lo_dic = new BigDecimal(lo);
lo_str = lo_dic.toPlainString();
}
String lo_string=lo_str;
完整处理代码。
然后可以来看一下效果:
好了,这个问题解决,继续下一个。
可以,接下来,我们程序写下去,到了第八个,出现了需求模糊的地方:
针对这种数据,需要做,行列转换。早就听闻,自己写处理json格式很烦,现在果然是这样啊,想以三个维度转换为一条记录很烦啊。
初步设计就是变成这样吧,
第一条记录:
ac:"apk_f"
dt:14344564632
dt_f:"20150101"
apk:"com.baidu.BaiduMap"
n:"百度地图"
hour:0
w:0
g:0
第二条记录:
ac:"apk_f"
dt:14344564632
dt_f:"20150101"
apk:"com.baidu.BaiduMap"
n:"百度地图"
hour:0
w:10
g:0
我应该解释清楚了吧,就是加了三个字段,将这两个数组给拉出来降维,对的,终于想起来这个名词了,降维。
让我们来编码,
进入方法, result = apk_f_CL(baseInfo, jsonObject);
好吧,看我们的写法,完整帖一次代码:
private List<String> apk_f_CL(String[] baseInfo, JSONObject jsonObject)
throws JSONException {
List<String> resultList = new ArrayList<String>();
String result = null;
try {
String dt = jsonObject.getString("dt");
if (dt != null) {
dt = stampToDate(dt);
}
String dt_f = jsonObject.getString("dt_f");
result = String.format("%s|%s|%s|%s|%s", baseInfo[0],
baseInfo[1], baseInfo[2], dt, dt_f);
JSONArray apk_f = jsonObject.getJSONArray("apk_f");
String arrayString = "";
for (int i = 0; i < apk_f.length(); i++) {
JSONObject jsonObject2 = apk_f.getJSONObject(i);
String apk = jsonObject2.getString("apk");
String n = jsonObject2.getString("n");
//先将这两个字符串组合,已提供给下面24小时使用
String structString = String.format("%s|%s",apk, n);
String w = jsonObject2.getString("w");
String g = jsonObject2.getString("g");
String g3 = jsonObject2.getString("g3");
String g4 = jsonObject2.getString("g4");
String[] w_arr = w.split(",");
String[] g_arr = g.split(",");
String[] g3_arr = g3.split(",");
String[] g4_arr = g4.split(",");
//从这里开始进入循环,为24小时数组降维
//首先让我们创建一个24小时的数组
String[] hour=new String[24];
for(int j=0;j<24;j++){
hour[j]= String.valueOf(j);
//依次拿到24小时时间
String h=hour[j];
String wStr=w_arr[j];
String gStr = g_arr[j];
String g3Str = g3_arr[j];
String g4Str = g4_arr[j];
//拼接24小时时间
String tailString = String.format("%s|%s|%s|%s|%s",h,wStr, gStr, g3Str, g4Str);
//apk循环内拼接
arrayString = structString+"|"+tailString;
//总回复字符串拼接
String resultRow = result+"|"+arrayString;
resultList.add(resultRow);
}
}
if (arrayString.endsWith(",")) {
arrayString = arrayString.substring(0,
arrayString.length() - 1);
}
// result += "\t" + arrayString;
} catch (Exception e) {
log.error("apk_f_CL_err: " + e.getMessage());
e.printStackTrace();
}
// return result;
return resultList;
}
然后发布服务器跑,看看结果:
其实,你们知道这是什么吧?总不能写到现在没解释这样做到底什么意义吧?这么做的意义是,我想知道,这个手机用户,每天玩哪些app,比方说我这个截图,这个用户玩王者荣耀每天玩多少时间,用wifi在哪些时间段,还是用流量,这样的数据有利于我们后期的用户画像!不只是王者荣耀啊,我们看看别的app,
看到了吧,这个人几乎不用我们系统的浏览器,但是,他玩微信,而且都是用流量,几乎也都在晚上,凌晨时候玩微信比较猛。
短信需求更改,本来短信总是只能发送一条的,后来被新元重新开发了,那到我这里,就又得重新开发了,这任务还算不轻,还得开发。
我们将短信一条一条取出,然后追加到前缀字符串中。
这些有的是测试数据,你不要真的打啊。
再说几个业务吧,我就不写具体开发统计信息了,主要都是重复的代码,但是代码是死的,人是活的,我们几乎可以知道你所有的信息,当然这些数据非常的隐私,只有数据部门可以解除到这些核心的数据,并且由于数据量极大,所以也请放心,我们并没有时间来查找你。。。
那看到短信了,没错,手机里所有的短信记录打点马赛克吧:
说到这里,先到了小黄车、mobike,因为我们现在的大数据架构师,就是从mobike出来的,那套后台数据仓库就是他搭建的,他来了也给我们开放了他项目的源码和思路,所以,感觉还是有资格说一说的,那些你想不还钱骑车的,你已经被统计了啊,“羊毛党”标签都打在后台里了啊,当然那个源码是不可以粘贴的,有隐私协议的哈。
我感觉不用解释了吧,如果你看到这篇文章,也许你已经知道了,其实,你没有任何隐私可言,无论你使用苹果或者安卓,在大数据程序猿这里,你只是众多数据中的一个,你的所有的手机信息,被简历,明白了吗。另外,如果app想访问你的通讯录,那就会知道你的交际圈、短信、电话的情况,可以形成连接。
明白了吧?还有之前做的哪些,切换经纬度,可以知道,这个用户在哪里上班,在哪里住,晓得了不?哎,这么做的意义其实很巨大,为了后期的进一步画像做准备的,兄弟。
好了,走到这里也克服了。我们把剩下的完成了吧,开发到这里,就距离成功只有30%的路没有走了,接下来没有什么难点了,都是一些重复做的事情,让我们把他做完,开发完,接着,就要放到服务器上,跑所有全量的数据。
可能一篇文章,3-5分钟就可以看完,但是,一步步走过来,确实花了几天的努力,但还是那句话,文档一旦形成了,往后在遇到,那就是1-2分钟的事情了,可见文档的重要性。
拿到新需求,小路乱撞。
首先拿到数据示例文档:
然后从svn上检出代码,工程如下:
需求,我们要将头文件添加到每个ac列表中。
然后在apk_list继续追加记录,也就是说,一个日志文件发过来,我们要根据这两个json格式数据要变成一个3维度变成一个表的转换,可能只立方增长,但是只要数据可以操作,就是有意义的转换。我们需要重写MapReduce程序。可能之前已经说了一些概念、wordcount等简单的介绍,现在要真正的做处理了。
写几个要经常用到的hadoop命令,
1.首先删除output文件夹:
./hdfs dfs -rmr /data/output
删除文件:
./hdfs dfs -rm /data/part-3
2.创建output文件:
./hdfs dfs -mkdir /data/output
3.改变目录权限:
./hdfs dfs -chmod 777 /data/output
4.放置文件:
./hdfs dfs -put input路径文件夹 output目标文件夹
./hdfs dfs -put /file/part-3 /data/input/
5.跑mapreduce程序:
./yarn jar /file/MapReduce_program/MR-0.0.4-SNAPSHOT.jar com.mr.DataCollection_02 /data/input/part-3 /data/output utf-8
这个是跑一个包路径下所有的文件,跑成mr的
./yarn jar /file/MapReduce_program/MR-0.0.1-SNAPSHOT.jar com.mr.DataCollection_02 /data/input/ /data/output utf-8
6.取回hdfs文件
./hdfs dfs -get /data/output/00000000apklist-r-00000 /file/output/apklist
取回所有文件,即取出文件夹:./hdfs dfs -get /data/output /file/output
关于MapReduce的介绍和搭建在前文都已经说过了,这里就不在赘述了,这篇以需求开发和解决问题为主,虽然还不知道前路到底有多少坑。
先大致看一眼源数据格式:
然后数据量贼大,我们挑一个少一点的来开发测试就好了。
然后我们看一些具体操作:
将我们的mr程序maven install
然后扔到服务器上:
然后跑mr程序:
./yarn jar /file/MapReduce_program/MR-0.0.1-SNAPSHOT.jar com.mr.DataCollection_02 /data/input/part-3 /data/output utf-8
mr跑完之后:
然后进入本地,我们看看数据:
然后我们把结果发给老大(需求方)看一下,咨询是否可用,
得到指令,就是这样,然后紧接着,新的需求全部来了:
我们一步一步做:
下面一个需求,将文件名规范化,本来
我们想将其规范化,那么我们改代码名称之后发现:
会出现错误:
那么可以说明,是不是这里不成功?那么不禁会问,这个文件名到底是怎么来的,别着急,我们继续深入其中。
可以看到,mapper函数中,已经对日期做了处理,
如果获取不到时间,会将dt格式化成这个玩意。然后在输出key时乃至后文中出现的filename中也都将这个时间作为了文件名或者key,并且将“-”格式化成“”。所以,我们调试。失败,那就去main方法里面调试。
(搜寻main方法)
到目前为止,因为拿到前期2000多行MapReducer,对于我们java程序猿来说,其实也是可以在3小时之内看懂的,然后做出正确的调试和修改:
很显然,我门道的filename了,然后在这里我们要做出更改。
然后我们改成这样:
// String fileName = (dt + ac).replace("_", "").replace("-", "");
//修改,将文件名更新,不需要那么多的0,
String fileName = ac.replace("_", "").replace("-", "");
但是,
17/06/25 17:38:28 INFO mapreduce.Job: Task Id : attempt_1498327717919_0011_r_000000_0, Status : FAILED
Error: java.lang.IllegalArgumentException: Named output '00000000apkdef' not defined
很尴尬啊,那么孤注一掷,接下来,我们干一票大的。首先将我们combiner阶段的方法输出文件名改为:
// String keyString = (dt + ac).replace("_", "").replace("-", "");
String keyString = ac.replace("_", "").replace("-", "");
接着,我们将其他无用的方法注释,全部注释,统统注释,否则会报错的:
然后执行完了,变成了我们需要的样子的一半,嘿嘿嘿:
还不错,也还算完美了。嘎嘎,一半完成,接下里想办法解决下面这一个。后面的我不想管了,我觉得代码里并没写到,所以应该是hadoop框架自己加的,所以,我们继续改写剩下的18个类的方法吧。go on。
随着我们深化修改,已经改好了这么多了:
down到本地linux环境看一下:
看一看文件内容:
那接下来,我们要处理一个痛点,就是经纬度信息的时候,我们发现了他的数据是科学计数法,并不能识别使用,需要转换。
那么,首先百度一下解决办法,写个test测试类:
显然,很好使,那我们别等了,赶紧写吧。
我们需要拿到,经纬度信息里面的la和lo两个字符串。
//科学计数法转换为字符串数字
String la = jsonObject.getString("la");
BigDecimal la_dic = new BigDecimal(la);
String la_str = la_dic.toPlainString();
String lo = jsonObject.getString("lo");
BigDecimal lo_dic = new BigDecimal(lo);
String lo_str = lo_dic.toPlainString();
result = String.format("%s|%s|%s|%s|%s|%s", baseInfo[0],
baseInfo[1], baseInfo[2], la_str, lo_str, dt);
好了,这个搞定了。我们测试一下吧。
很显然,转好了,但是。
目前看来,经纬度出现4.9E-324 这个科学计数法,出现这个问题说明定位失败了,定位失败返回的就是这个值,定位失败的原因就是库加载失败。
所以,这是一个经验,以后不用再查了,就是定位失败的意思,以后遇到这个问题,直接字符串匹配一下0.0,所以mr程序还需要改进。
所以只举一个例子:
String lo_str;
String lo = jsonObject.getString("lo");
if("4.9E-324".equals(lo)){
lo_str="0.0";
}else{
BigDecimal lo_dic = new BigDecimal(lo);
lo_str = lo_dic.toPlainString();
}
String lo_string=lo_str;
完整处理代码。
然后可以来看一下效果:
好了,这个问题解决,继续下一个。
可以,接下来,我们程序写下去,到了第八个,出现了需求模糊的地方:
针对这种数据,需要做,行列转换。早就听闻,自己写处理json格式很烦,现在果然是这样啊,想以三个维度转换为一条记录很烦啊。
初步设计就是变成这样吧,
第一条记录:
ac:"apk_f"
dt:14344564632
dt_f:"20150101"
apk:"com.baidu.BaiduMap"
n:"百度地图"
hour:0
w:0
g:0
第二条记录:
ac:"apk_f"
dt:14344564632
dt_f:"20150101"
apk:"com.baidu.BaiduMap"
n:"百度地图"
hour:0
w:10
g:0
我应该解释清楚了吧,就是加了三个字段,将这两个数组给拉出来降维,对的,终于想起来这个名词了,降维。
让我们来编码,
进入方法, result = apk_f_CL(baseInfo, jsonObject);
好吧,看我们的写法,完整帖一次代码:
private List<String> apk_f_CL(String[] baseInfo, JSONObject jsonObject)
throws JSONException {
List<String> resultList = new ArrayList<String>();
String result = null;
try {
String dt = jsonObject.getString("dt");
if (dt != null) {
dt = stampToDate(dt);
}
String dt_f = jsonObject.getString("dt_f");
result = String.format("%s|%s|%s|%s|%s", baseInfo[0],
baseInfo[1], baseInfo[2], dt, dt_f);
JSONArray apk_f = jsonObject.getJSONArray("apk_f");
String arrayString = "";
for (int i = 0; i < apk_f.length(); i++) {
JSONObject jsonObject2 = apk_f.getJSONObject(i);
String apk = jsonObject2.getString("apk");
String n = jsonObject2.getString("n");
//先将这两个字符串组合,已提供给下面24小时使用
String structString = String.format("%s|%s",apk, n);
String w = jsonObject2.getString("w");
String g = jsonObject2.getString("g");
String g3 = jsonObject2.getString("g3");
String g4 = jsonObject2.getString("g4");
String[] w_arr = w.split(",");
String[] g_arr = g.split(",");
String[] g3_arr = g3.split(",");
String[] g4_arr = g4.split(",");
//从这里开始进入循环,为24小时数组降维
//首先让我们创建一个24小时的数组
String[] hour=new String[24];
for(int j=0;j<24;j++){
hour[j]= String.valueOf(j);
//依次拿到24小时时间
String h=hour[j];
String wStr=w_arr[j];
String gStr = g_arr[j];
String g3Str = g3_arr[j];
String g4Str = g4_arr[j];
//拼接24小时时间
String tailString = String.format("%s|%s|%s|%s|%s",h,wStr, gStr, g3Str, g4Str);
//apk循环内拼接
arrayString = structString+"|"+tailString;
//总回复字符串拼接
String resultRow = result+"|"+arrayString;
resultList.add(resultRow);
}
}
if (arrayString.endsWith(",")) {
arrayString = arrayString.substring(0,
arrayString.length() - 1);
}
// result += "\t" + arrayString;
} catch (Exception e) {
log.error("apk_f_CL_err: " + e.getMessage());
e.printStackTrace();
}
// return result;
return resultList;
}
然后发布服务器跑,看看结果:
其实,你们知道这是什么吧?总不能写到现在没解释这样做到底什么意义吧?这么做的意义是,我想知道,这个手机用户,每天玩哪些app,比方说我这个截图,这个用户玩王者荣耀每天玩多少时间,用wifi在哪些时间段,还是用流量,这样的数据有利于我们后期的用户画像!不只是王者荣耀啊,我们看看别的app,
看到了吧,这个人几乎不用我们系统的浏览器,但是,他玩微信,而且都是用流量,几乎也都在晚上,凌晨时候玩微信比较猛。
短信需求更改,本来短信总是只能发送一条的,后来被新元重新开发了,那到我这里,就又得重新开发了,这任务还算不轻,还得开发。
我们将短信一条一条取出,然后追加到前缀字符串中。
这些有的是测试数据,你不要真的打啊。
再说几个业务吧,我就不写具体开发统计信息了,主要都是重复的代码,但是代码是死的,人是活的,我们几乎可以知道你所有的信息,当然这些数据非常的隐私,只有数据部门可以解除到这些核心的数据,并且由于数据量极大,所以也请放心,我们并没有时间来查找你。。。
那看到短信了,没错,手机里所有的短信记录打点马赛克吧:
说到这里,先到了小黄车、mobike,因为我们现在的大数据架构师,就是从mobike出来的,那套后台数据仓库就是他搭建的,他来了也给我们开放了他项目的源码和思路,所以,感觉还是有资格说一说的,那些你想不还钱骑车的,你已经被统计了啊,“羊毛党”标签都打在后台里了啊,当然那个源码是不可以粘贴的,有隐私协议的哈。
我感觉不用解释了吧,如果你看到这篇文章,也许你已经知道了,其实,你没有任何隐私可言,无论你使用苹果或者安卓,在大数据程序猿这里,你只是众多数据中的一个,你的所有的手机信息,被简历,明白了吗。另外,如果app想访问你的通讯录,那就会知道你的交际圈、短信、电话的情况,可以形成连接。
明白了吧?还有之前做的哪些,切换经纬度,可以知道,这个用户在哪里上班,在哪里住,晓得了不?哎,这么做的意义其实很巨大,为了后期的进一步画像做准备的,兄弟。
好了,走到这里也克服了。我们把剩下的完成了吧,开发到这里,就距离成功只有30%的路没有走了,接下来没有什么难点了,都是一些重复做的事情,让我们把他做完,开发完,接着,就要放到服务器上,跑所有全量的数据。
可能一篇文章,3-5分钟就可以看完,但是,一步步走过来,确实花了几天的努力,但还是那句话,文档一旦形成了,往后在遇到,那就是1-2分钟的事情了,可见文档的重要性。