您的位置:首页 > 其它

Spark学习笔记:在瞎搞RDD中得到的收获和一些疑问

2017-12-25 12:23 302 查看
工作中常遇到的一个让人头疼的问题就是对大量数据的收集与处理,比如在建立用户画像的时候,需要跑一个月活数据,原始策略是直接用hive去查询,但随着用户规模的扩张和计算资源分配不足等问题,后期常常跑一天也无法从app的原始日志中得到这些数据。

因此某一天我开始了瞎搞,作为一个java程序员,被java限制了一些思维,在接触scala时有点手足无措,也是直接硬去写spark,反复调整,算是勉强写出了一个能跑的版本,数据生成过程的原理类似滑动窗口,每天只要生成前一天的数据然后和之前的历史数据做一下合并去重就可以了。

一开始不是特别懂,所以常常导致作业跑着跑着就挂了,体会最深的几点错误:1.想要获得前30天的所有数据,运用了以下方式生成:

SparkContext.getOrCreate().parallelize(1.to(days))
.map(x => {//以下生成文件名并读取文件,做处理
val calendar = Calendar.getInstance()
calendar.setTime(new Date)
calendar.add(Calendar.DATE, -x)
val path = FilePathConstant.baseApiPath + pathDateFormatter.format(
calendar.getTime)
getSingleFileData(SparkContext.getOrCreate().sequenceFile[BytesWritable, BytesWritable](path))
})
.flatMap(identity[Array[String]])
.map(id => (id, 1))
.reduceByKey(_ + _)
.keys
.saveAsTextFile(outPath)
感觉并没啥问题,但其实犯了两个大错。1.通过parallelize生成的RDD,内存资源会受到Driver程序的限制,也就是说,并不适合存放数据量非常大的数据集,比如我的原始日志 2.RDD是会分发到节点上去操作的,不能出现嵌套操作,而在我的代码中则会出现RDD[RDD[String]]这一类的东西,(我贴的这一版可能是改掉了,但我确实犯过这个错。

以上改掉之后,运行基本没什么问题,但当时困扰了我很久的一个问题是,我可以对一大坨RDD,sorry说错了,不是一大坨,我可以对很多个RDD做操作,但是怎么把这些RDD全部union起来?确实有一些,对RDD的操作,比如union,substract之类,但当时脑子确实转不过弯,感觉就是合不起来。。最后我搞成了下面这样子,也不知道对不对,反正it works...

var rdd = SparkContext
.getOrCreate()
.sequenceFile[String, String](getFilePath(baseHistoryPath, 1))
if (days > 1)
2.to(days)
.foreach(x => {
rdd = rdd.union(
SparkContext
.getOrCreate()
.sequenceFile[String, String](getFilePath(baseHistoryPath, x)))
})
然后就有个很奇怪的问题,不知道该怎么查,就是,RDD本身是一个不可变的,那么我定义一个var,之后不断对它做union操作,是不是每次操作的时候,都生成了一个新的RDD赋值给这个变量(恩,这样打出来我猜应该是,不知道以上用法是不是符合规范。

再就是,由于数据源的不同,有一些RDD我会reduceByKey之后再save,有一些只需要取distinct再save就可以了,但distinct是transformation,并不是action,我猜是因为这样没有做action操作所以在save的时候就挂了,因为并不需要做多余的操作,所以本想可以直接用collect(返回所有元素,但 但是为啥collect返回了个Array[String],想要的是RDD[String]...

从能跑的数据来看效果还是很不错的,利用了历史数据后每次只需要5分钟就能跑出月活数据,即使清空所有数据全部重新生成也只需要一个多小时,比以前一天跑不出来也算是进步了一些了。目前替换掉了所有的hive数据源,但还有一部分hbase的数据源是使用mr跑的,打算在version2中统一把所有的都整理成spark,并且不用对数据进行排序,就可以整理出用户特征。完成v2后之后会来详细记录。

总结完毕,2个问题待解,之后如果有新的认识或者有了确切答案会来补充。

=====================================填坑分割线======================================

以上坑已填~~ 合并一个list中所有的RDD十分简单,只需要list.reduce(_ union _)即可~

然后 挂了的那个玩意跟transformation还是action木有关系,纯粹是写挫了 哈哈哈
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: