CountOnce(spark)

    假设HDFS都每份数据一共存储两份,其中以一块数据有错,那么收集所有块数据的ID,则如下:
    5 5 6 6 7 7 8 8 9 
    在大数据下如何找到9这块数据是错误的。
    
    可以利用异或的数据,求出答案9
    异或性质:
     1、交换律 a^b=b^a
    2、结合律(即(a^b)^c == a^(b^c)) 
    3、对于任何数x,都有x^x=0,x^0=x 
    4、自反性 A XOR B XOR B = A xor  0 = A

    假如spark的任务分区有三个:
    分区1:
    5 ^ 6 ^ 7
    1 0 1           5
    1 1 0           6
     1 1 1           7
    1 0 0           4

    分区2:
    5 ^ 6 ^ 8
       1 0 1           5
       1 1 0           6
     1 0 0 0           8
    1 0 1 1          11
    
    分区3:
    7 ^ 8 ^ 9
       1 1 1           5
    1 0 0 0           6
     1 0 0 1           7
    0 1 1 0           6

    计算结果:
    将4,11,6再次进行异或运算
    4 ^ 11 ^ 6
       1 0 0           4
    1 0 1 1           11
        1 1 0           6
    1 0 0 1           9
     
    模拟spark计算,结果能得到正确的答案9,这是由于满足结合律和交换律。

spark程序(1):
package com.dt.spark.cores.scala
import org.apache.spark.{SparkContext, SparkConf}

object CountOnce {
def main (args: Array[String]) {
val conf = new SparkConf().setAppName("CountOnce").setMaster("local")
val sc = new SparkContext(conf)
val data = sc.textFile("E:\\workspases\\data\\CountOnce.txt")
val word = data.map(line => line.toInt)
val result =word.reduce(_^_)
println(result)
}
}
spark程序(2):
    val conf = new SparkConf()
     .setAppName("count once")
      .set("spark.executor.memory", args(1))
      val sc = new SparkContext(conf)
      val data = sc.textFile(args(0))
      val result = data.mapPartitions( iter => {
        var tmp = iter.next().toInt
        while (iter.hasNext) {
          tmp ^= iter.next().toInt
        }
        Seq((1, tmp)).iterator//每个分区的数据都是key,都是1,最后收集到一块
      }).reduceByKey(_ ^ _).collect
      println(result(0))

//备注:mapPartitions函数解释

def mapPartitions[U](f: (Iterator[T]) => Iterator[U], preservesPartitioning: Boolean = false)(implicit arg0: ClassTag[U]): RDD[U]

该函数和map函数类似,只不过映射函数的参数由RDD中的每一个元素变成了RDD中每一个分区的迭代器。如果在映射的过程中需要频繁创建额外的对象,使用mapPartitions要比map高效的过。

比如,将RDD中的所有数据通过JDBC连接写入数据库,如果使用map函数,可能要为每一个元素都创建一个connection,这样开销很大,如果使用mapPartitions,那么只需要针对每一个分区建立一个connection。

参数preservesPartitioning表示是否保留父RDD的partitioner分区信息。




   
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值