Spark RDD详解(什么是RDD、创建RDD的几种方式)

什么是RDD?

RDD( resilient distributed dataset弹性分布式数据集RDD代表是一个不可变的、可分区的、支持并行计算的元素集合(类似于Scala中的不可变集合),RDD可以通过HDFS、Scala集合、RDD转换、外部的数据集(支持InputFormat)获得;并且我们可以通知Spark将RDD持久化在内存中,可以非常高效的重复利用或者在某些计算节点故障时自动数据恢复
RDD是Spark中最基本的数据抽象

创建RDD的几种方式:

scala集合创建
方法一
/**
  * scala集合构建
  */
object RDDCreatedByCollection {

  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("datasource").setMaster("local[*]")
    val sc = new SparkContext(conf)
    val range: Range = 1 to 100
    val rdd = sc.parallelize(range)

    // spark求和计算
    val sum = rdd.reduce((v1: Int, v2: Int) => v1 + v2)

    println(s"sum=$sum  | 分区数量=" + rdd.getNumPartitions)

    sc.stop()
  }
}
方法二
/**
  * 方法二
  */
def m2(): Unit = {
    val conf = new SparkConf().setAppName("datasource").setMaster("local[*]")
    val sc = new SparkContext(conf)
    val range: Range = 1 to 100
    val rdd = sc.makeRDD(range,2)

    // spark求和计算
    val sum = rdd.reduce((v1: Int, v2: Int) => v1 + v2)

    println(s"sum=$sum  | 分区数量=" + rdd.getNumPartitions)

    sc.stop()
}
通过外部数据集构建
文件系统
Local(本地文件系统)
/**
  * 本地文件构建RDD
  */
object RDDCreatedByLocalFS {

  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("datasource").setMaster("local[*]")
    val sc = new SparkContext(conf)

    // 方法一: 读取目录或者文件内容,将每一行数据作为RDD中的一个元素
    // val rdd = sc.textFile("file:///D://data", 5)
    // rdd.foreach((line: String) => println(line))

    // 方法二:读取目录或者文件内容,将文件路径作为K,将文件内容作为V
    // Tuple2(path,content)
    val rdd: RDD[(String, String)] = sc.wholeTextFiles("file:///D://data", 5)
    rdd
      .map(t2 => t2._2) // Tuple2 ---> content:String
      .flatMap((content: String) => content.split("\\n"))
      .flatMap((line: String) => line.split("\\s"))
      .map((_, 1L))
      .groupByKey()
      .map(t2 => (t2._1, t2._2.size))
      .foreach(println)

    sc.stop()
  }
}
HDFS
/**
  * 本地文件构建RDD
  */
object RDDCreatedByHDFS {

  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("datasource").setMaster("local[*]")
    val sc = new SparkContext(conf)

    // 方法一: 读取目录或者文件内容,将每一行数据作为RDD中的一个元素
    /*
    val rdd = sc.textFile("hdfs://SparkOnStandalone:9000/data.txt", 5)
    rdd.foreach((line: String) => println(line))
     */

    // 方法二:读取目录或者文件内容,将文件路径作为K,将文件内容作为V
    // Tuple2(path,content)
    val rdd: RDD[(String, String)] = sc.wholeTextFiles("hdfs://SparkOnStandalone:9000/data.txt", 5)
    rdd
      .map(t2 => t2._2) // Tuple2 ---> content:String
      .flatMap((content: String) => content.split("\\n"))
      .flatMap((line: String) => line.split("\\s"))
      .map((_, 1L))
      .groupByKey()
      .map(t2 => (t2._1, t2._2.size))
      .foreach(println)
    sc.stop()
  }
}
关系型数据库
比如MySQL:

先导入驱动jar包: 部署类未找到 远程依赖问题解决

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>
/**
  * DB构建RDD
  */
object RDDCreatedByDB {

  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("datasource").setMaster("local[*]")
    val sc = new SparkContext(conf)
    // m1(sc)
    m2(sc)

    sc.stop()
  }

  /**
    * Hadoop DBInputFormat
    *
    * @param sc
    */
  def m2(sc: SparkContext): Unit = {

    val conf = sc.hadoopConfiguration
    conf.set(DBConfiguration.DRIVER_CLASS_PROPERTY, "com.mysql.jdbc.Driver")
    conf.set(DBConfiguration.URL_PROPERTY, "jdbc:mysql://192.168.197.1:3306/test")
    conf.set(DBConfiguration.USERNAME_PROPERTY, "root")
    conf.set(DBConfiguration.PASSWORD_PROPERTY, "1234")
    conf.set(DBConfiguration.INPUT_QUERY, "select * from t_user")
    // 查询数据库表的记录数,用以计算分区
    conf.set(DBConfiguration.INPUT_COUNT_QUERY, "select count(*) from t_user")
    conf.set(DBConfiguration.INPUT_CLASS_PROPERTY, "com.netzhuo.datasource.User")


    val rdd = sc.newAPIHadoopRDD(conf, classOf[DBInputFormat[User]], classOf[LongWritable], classOf[User])
    rdd
      .foreach(t2 => {
        println("k=" + t2._1 + "    | v=" + t2._2)
      })
  }

  /**
    * 通过JDBCRDD构建  有比较大的局限性,原因是SQL语句中必须定义上下边界,否则无法使用
    *
    * @param sc
    */
  def m1(sc: SparkContext): Unit = {
    // 方法一
    val rdd = new JdbcRDD(
      sc,
      () => {
        Class.forName("com.mysql.jdbc.Driver")
        val connection = DriverManager.getConnection("jdbc:mysql://192.168.197.1:3306/test", "root", "1234")
        connection
      },
      "select * from t_user where id >= ? and id <= ?",
      1,  // 下边界
      4,  // 上边界
      2,  // 分区数量
      rs => {
        val id = rs.getInt(1)
        val name = rs.getString(2)
        val sex = rs.getString(3)
        (id, name, sex)
      }
    )

    rdd
      .foreach(t3 => println(t3._1 + "\t" + t3._2 + "\t" + t3._3))
  }
}
通过HBase创建
导入HBase第三方依赖
<dependency>
    <groupId>org.apache.hbase</groupId>
    <artifactId>hbase-server</artifactId>
    <version>1.4.10</version>
</dependency>

<dependency>
    <groupId>org.apache.hbase</groupId>
    <artifactId>hbase-client</artifactId>
    <version>1.4.10</version>
</dependency>

<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>2.5.0</version>
</dependency>

注意:请提前准备好Hbase数据 这里用的是一个t_user表 字段是id name sex

/**
  * HBase构建RDD
  */
object RDDCreatedByHBase {

  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("datasource").setMaster("local[*]")
    // val conf = new SparkConf().setAppName("datasource").setMaster("spark://SparkOnStandalone:7077")
    val sc = new SparkContext(conf)

    val configuration = sc.hadoopConfiguration
    configuration.set(HConstants.ZOOKEEPER_QUORUM, "HadoopNode00")
    configuration.set(HConstants.ZOOKEEPER_CLIENT_PORT, "2181")
    // hbase表名
    configuration.set(TableInputFormat.INPUT_TABLE, "netzhuo2:t_user")
    // 查询字段列表
    configuration.set(TableInputFormat.SCAN_COLUMNS, "cf1:name cf1:age")

    val rdd = sc.newAPIHadoopRDD(configuration, classOf[TableInputFormat], classOf[ImmutableBytesWritable], classOf[Result])

    rdd.foreach(t2 => {
      val rowkey = Bytes.toString(t2._1.get())
      val name = Bytes.toString(t2._2.getValue(Bytes.toBytes("cf1"), Bytes.toBytes("name")))
      val age = Bytes.toString(t2._2.getValue(Bytes.toBytes("cf1"), Bytes.toBytes("age")))
      println(rowkey + "\t" + name + "\t" + age)
    })

    sc.stop()
  }

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值