史上最简单的spark教程
所有代码示例地址:https://github.com/Mydreamandreality/sparkResearch
(提前声明:文章由作者:张耀峰 结合自己生产中的使用经验整理,最终形成简单易懂的文章,写作不易,转载请注明)
(文章参考:Elasticsearch权威指南,Spark快速大数据分析文档,Elasticsearch官方文档,实际项目中的应用场景)
(帮到到您请点点关注,文章持续更新中!)
Git主页 https://github.com/Mydreamandreality
学完这章后,spark的核心基础概念我们就已经全部了解了,后续的话计划是深入数据分区,java开发spark,HDFS存储,yarn资源调度等进行案例文章编写
并行度调优
- 目前为止:我们已经了解了转化操作的分发方式,但并不知道spark是怎么样分割工作的
- 每个RDD都有固定数目的分区,分区数决定了在RDD上执行操作的并行度
- 在执行聚合或者分组操作的时候,可以要求spark使用指定的分区数,spark根据集群的大小 推断出一个有意义的默认值, 但是大部分情况下还是需要我们对并行度调优得到更好的表现
指定spark分区数案例
//创建pairRDD元素
JavaPairRDD<String,Integer> javaPairRDD = sparkContext.parallelizePairs(Arrays.asList(new Tuple2<>("alert",10)));
//使用默认的分区数
javaPairRDD.reduceByKey(new Function2<Integer, Integer, Integer>() {
@Override
public Integer call(Integer v1, Integer v2) throws Exception {
return null;
}
});
//使用自定义的的分区数
javaPairRDD.reduceByKey(new Function2<Integer, Integer, Integer>() {
@Override
public Integer call(Integer v1, Integer v2) throws Exception {
return null;
}
},10); //在这里追加参数即可
-
如果希望在除聚合分组之外的函数中也能定义rdd的分区,spark提供了repartition()函数.它会把数据通过网络进行混洗,并且创建新的分区集合
-
但是对数据重新分区是代价非常大的操作,spark在repartition上做了一些优化,叫做coalesce(),在此操作之前我们可以通过JavaRDD.partitions().size()查看RDD的分区数量,以确保分配到更少的分区数中
数据分组案例
- 我们目前操作的数据都是键值对数据,那么必然就少不了分组查询
- 比如查看某个资产的所有被攻击信息 -一对N的关系
- 如果数据已经以预期的方式提取键值,groupByKey()就会使用RDD中的键来对数据进行分组, 比如K V组成的RDD,最终得到的结果是 [K,Iterable[V]]
- groupByKey()可以用于未成对的数据上,也可以根据除键相同以外的条件进行分组,它可以接受一个函数,对源RDD中的每个元素使用这个函数,将返回结果作为键再进行分组
数据连接案例
- 连接可以理解为MySQL中的left join,inner join,right join
- 在spark中,将有键的数据和另一组有键的数据组合使用是计算常用方式之一
- 连接的方式太多了,左外连接,右外连接,交叉连接,内连接,
内连接案例:[这些代码在第六章中都有案例]
普通的join操作符表示内连接.只有在两个pairRDD中都存在的键才叫输出,当一个输入对应的某个键有多个值时,生成的pairRDD会包括来自两个输入RDD的每一组相对应的记录
左右连接案例:
有时候我们不希望结果中的键在两个RDD中都存在:leftOuterJoin()或者rightOuterJoin() 都会根据键连接RDD,但允许其中一个RDD的键缺省
数据排序
- 在正常开发中,数据排序应该是最常见的操作之一,如果我们的键是排好序的,那就很简单了,直接collect()获取前N条记录就可以了
- 如果此时需要进行倒序排序,我们便可以使用sortByKey()函数,这个函数可以接受一个boolean的参数,是否按照升序排列,默认是true
-
代码案例
JavaRDD<String> rdd = sparkContext.parallelize(Arrays.asList("test", "java", "python"));
JavaRDD<String> otherRDD = sparkContext.parallelize(Arrays.asList("golang", "php", "hadoop"));
PairFunction<String, String, String> pairFunction = new PairFunction<String, String, String>() {
@Override
public Tuple2<String, String> call(String s) {
return new Tuple2<>(s.split(" ")[0], s);
}
};
JavaPairRDD<String, String> pairRDD = rdd.mapToPair(pairFunction);
JavaPairRDD<String, String> pairRDDOther = otherRDD.mapToPair(pairFunction);
pairRDD.sortByKey(false);
class IntegerComparator implements Comparator<Integer> {
public int compare(Integer a, Integer b) {
return String.valueOf(a).compareTo(String.valueOf(b))
}
}
rdd.sortByKey(comp)
-
行动操作
- 和转化操作一样,所有基础RDD支持的传统行动操作也都在pairRDD上可用,PairRDD提供了一些额外的行动操作,可以让我们充分利用数据的键值对特性
- 操作数据:{(1, 2), (3, 4), (3, 6)}
- 函数示例如下:
函数 | 描述 | 示例 | 结果 |
---|---|---|---|
countByKey() | 对每个键的元素分别计数 | RDD.countBykey() | {(1, 1), (3, 2)} |
collectAsMap() | 把结果以映射表的方式返回,方便查询 | rdd.collectAsMap() | Map{(1, 2), (3, 4), (3, 6)} |
lookup(Key) | 通过键返回value | RDD,lookup(3) | [4,6] |
后续想到还会继续补充
目前的计划是对数据分区优化进行一个研究,之后会把研究的成果分享出来的
目前来看,spark基础的RDD案例以及核心概念已经大致了解
后续的目标就是从spark+HDFS数据存储这块入手,对案例做一个进阶编码.最后再深入研究下spark的原理
大家有任何问题一起留言交流–