转载自:http://blog.csdn.net/jiangpeng59/article/details/53318761

foreachRDD通常用来把SparkStream运行得到的结果保存到外部系统比如HDFS、Mysql、Redis等等。了解下面的知识可以帮助我们避免很多误区

误区1:实例化外部连接对象的位置不正确,比如下面代码


  1. dstream.foreachRDD { rdd =>
  2. val connection = createNewConnection()  // executed at the driver
  3. rdd.foreach { record =>
  4. connection.send(record) // executed at the worker
  5. }
  6. }  ​

其实例化的连接对象在driver中,然后通过序列化的方式发送到各个Worker,但实际上Connection的序列化通常是无法正确序列化的

误区2:为每条记录都创建一个连接对象


  1. dstream.foreachRDD { rdd =>
  2. rdd.foreach { record =>
  3. val connection = createNewConnection()
  4. connection.send(record)
  5. connection.close()
  6. }
  7. }  ​

虽然误区1的问题得到了解决,但通常情况下,外部系统如mysql,其连接对象是非常可贵的,如果一条记录就申请一个连接资源,系统性能会非常糟糕

然后,给出了一个比较好的方法,为每一个分区创建一个连接对象,其具体代码如下

 

  1. dstream.foreachRDD { rdd =>
  2. rdd.foreachPartition { partitionOfRecords =>
  3. val connection = createNewConnection()
  4. partitionOfRecords.foreach(record => connection.send(record))
  5. connection.close()
  6. }
  7. }  ​

最后给出一个较优的方案,使用一个连接池来维护连接对象

 

  1. dstream.foreachRDD { rdd =>
  2. rdd.foreachPartition { partitionOfRecords =>
  3. // ConnectionPool is a static, lazily initialized pool of connections
  4. val connection = ConnectionPool.getConnection()
  5. partitionOfRecords.foreach(record => connection.send(record))
  6. ConnectionPool.returnConnection(connection)  // return to the pool for future reuse
  7. }
  8. }  ​

正如上面代码阐述的,连接对象推荐是使用lazy关键字来修饰,用到的时候才去实例化

下面给出网上一段把SparkStream的结果保存到Mysql中的代码示例


  1. package spark.examples.streaming
  2. import java.sql.{PreparedStatement, Connection, DriverManager}
  3. import java.util.concurrent.atomic.AtomicInteger
  4. import org.apache.spark.SparkConf
  5. import org.apache.spark.streaming.{Seconds, StreamingContext}
  6. import org.apache.spark.streaming._
  7. import org.apache.spark.streaming.StreamingContext._
  8. object SparkStreamingForPartition {
  9. def main(args: Array[String]) {
  10. val conf = new SparkConf().setAppName("NetCatWordCount")
  11. conf.setMaster("local[3]")
  12. val ssc = new StreamingContext(conf, Seconds(5))
  13. //The DStream is a collection of RDD, which makes the method foreachRDD reasonable
  14. val dstream = ssc.socketTextStream("192.168.26.140", 9999)
  15. dstream.foreachRDD(rdd => {
  16. //embedded function
  17. def func(records: Iterator[String]) {
  18. var conn: Connection = null
  19. var stmt: PreparedStatement = null
  20. try {
  21. val url = "jdbc:mysql://192.168.26.140:3306/person";
  22. val user = "root";
  23. val password = ""
  24. conn = DriverManager.getConnection(url, user, password)
  25. records.flatMap(_.split(" ")).foreach(word => {
  26. val sql = "insert into TBL_WORDS(word) values (?)";
  27. stmt = conn.prepareStatement(sql);
  28. stmt.setString(1, word)
  29. stmt.executeUpdate();
  30. })
  31. } catch {
  32. case e: Exception => e.printStackTrace()
  33. } finally {
  34. if (stmt != null) {
  35. stmt.close()
  36. }
  37. if (conn != null) {
  38. conn.close()
  39. }
  40. }
  41. }
  42. val repartitionedRDD = rdd.repartition(3)
  43. repartitionedRDD.foreachPartition(func)
  44. })
  45. ssc.start()
  46. ssc.awaitTermination()
  47. }
  48. }  ​

注意的细节:

Dstream和RDD一样是延迟执行,只有遇到action操作才会真正去计算。因此在Dstream的内部RDD必须包含Action操作才能是接受到的数据得到处理。即使代码中包含foreachRDD,但在内部却没有action的RDD,SparkStream只会简单地接受数据数据而不进行处理

 

SparkStream:4)foreachRDD详解的更多相关文章

  1. 58、Spark Streaming: DStream的output操作以及foreachRDD详解

    一.output操作 1.output操作 DStream中的所有计算,都是由output操作触发的,比如print().如果没有任何output操作,那么,压根儿就不会执行定义的计算逻辑. 此外,即 ...

  2. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  3. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  4. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  5. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  6. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

  7. Android Notification 详解——基本操作

    Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...

  8. Git初探--笔记整理和Git命令详解

    几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...

  9. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

随机推荐

  1. java面向对象编程--Josephu问题(丢手帕问题)

    Josephu问题为:设编号为1,2,...n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推 ...

  2. python学习-python入门

    开始学习python,开始记录. 第一个小程序:登陆系统 功能:1.通过文件名和密码导入用户名和密码~ 2.用户输入用户名和密码 3.将用户输入的用户名进行比对,先判断用户名是否在黑名单里面,如果在黑 ...

  3. JavaScript作用域[[scope]]

    [[scope]] : 隐式的属性 每个JavaScript函数都是一个对象,对象中有些属性可以访问,而有些属性是不可以访问的,这些属性仅供JavaScript引擎存取, [[scope]]就是其中一 ...

  4. Datediff的使用(统计本日,昨日,本周,本月)

    //统计本日,昨日,本周,本月添加的产品总数 //日期            DateTime DT = DateTime.Now;            string day=DT.Date.ToS ...

  5. jQuery 追加元素、拼接元素的方法总结(append、html、insertBefore、before等)

    1. append & appendTo 的功能均为:在被选元素结尾(仍在元素内部)插入指定内容,但是内容和选择器的位置不同 (1) append()方法: $("#test&quo ...

  6. Linux压缩和解压缩

    1.tar.gz tar.gz这种格式是Linux下使用得最多的压缩格式.它在压缩时不会占用太多CPU的,而且可以得到一个非常理想的压缩率. tar -zcvf archive_name.tar.gz ...

  7. Python学习笔记,day2

    Python学习第二天 一.模块 使用模块前需在代码最前声明(import) 二.数据类型 1.数字 int(整型) 在32位机器上,整数的位数为32位,取值范围为-2**31-2**31-1,即-2 ...

  8. Mabatis面试题

    Mybatis面试题 1请写出Mybatis核心配置文件MyBatis-config.xml的内容? <?xml version="1.0" encoding="U ...

  9. hdu 4506 快速幂

    小明自从告别了ACM/ICPC之后,就开始潜心研究数学问题了,一则可以为接下来的考研做准备,再者可以借此机会帮助一些同学,尤其是漂亮的师妹.这不,班里唯一的女生又拿一道数学题来请教小明,小明当然很高兴 ...

  10. HQL包含中文查询失败

    jdbc:mysql://172.16.9.6:3306/school?useUnicode=true&characterEncoding=UTF-8配置文件中的url加上编码,一般mysql ...