我正在使用calliope即spark插件来连接cassandra。我创建了两个看起来像
的RDD class A
val persistLevel = org.apache.spark.storage.StorageLevel.MEMORY_AND_DISK
val cas1 = CasBuilder.cql3.withColumnFamily("cassandra_keyspace", "cassandra_coulmn_family 1")
val sc1 = new SparkContext("local", "name it any thing ")
var rdd1 = sc.cql3Cassandra[SCALACLASS_1](cas1)
var rddResult1 = rdd1.persist(persistLevel)
class B
val cas2 = CasBuilder.cql3.withColumnFamily("cassandra_keyspace", "cassandra_coulmn_family 2")
var rdd2 = sc1.cql3Cassandra[SCALACLASS_2](cas2)
var rddResult2 = rdd2.persist(persistLevel)
以某种方式跟随使用其他2创建新RDD的代码库不起作用。是否有可能我们不能一起迭代2个RDD?
以下是无效的代码段 -
case class Report(id: Long, anotherId: Long)
var reportRDD = rddResult2.flatMap(f => {
val buf = List[Report]()
**rddResult1.collect().toList**.foldLeft(buf)((k, v) => {
val buf1 = new ListBuffer[Report]
buf ++ v.INSTANCE_VAR_FROM_SCALACLASS_1.foldLeft(buf1)((ik, iv) => {
buf1 += Report(f.INSTANCE_VAR_FROM_SCALACLASS_1, iv.INSTANCE_VAR_FROM_SCALACLASS_2)
})
})
})
如果我替换粗体并初始化它就像 -
val collection = rddResult1.collect().toList
var reportRDD = rddResult2.flatMap(f => {
val buf = List[Report]()
**collection**.foldLeft(buf)((k, v) => {
val buf1 = new ListBuffer[Report]
buf ++ v.INSTANCE_VAR_FROM_SCALACLASS_1.foldLeft(buf1)((ik, iv) => {
buf1 += Report(f.INSTANCE_VAR_FROM_SCALACLASS_1, iv.INSTANCE_VAR_FROM_SCALACLASS_2)
})
})
})
它有效,有没有解释?
答案 0 :(得分:5)
您正在将转化与动作混合。 rdd2.flatMap
的关闭是在工作人员身上执行的,而rdd1.collect
是一个'行动'}在Spark lingo中,将数据传递给驱动程序。所以,非正式地说,当你尝试对它进行flatMap时,你可以说数据不存在。 (我不太了解内部因素 - 确定根本原因)
如果你想在两个RDD上分布式操作,你应该使用其中一个连接函数(join,leftOuterJoin,rightOuterJoin,cogroup)加入它们。
E.g。
val mappedRdd1 = rdd1.map(x=> (x.id,x))
val mappedRdd2 = rdd2.map(x=> (x.customerId, x))
val joined = mappedRdd1.join(mappedRdd2)
joined.flatMap(...reporting logic..).collect
答案 1 :(得分:2)
您可以在应用程序中操作RDD。但是您无法在执行程序(工作节点)中操作RDD。执行程序无法提供驱动集群的命令。 flatMap
内的代码在执行程序上运行。
在第一种情况下,您尝试在执行程序中操作RDD。我估计你会得到NotSerializableException
,因为你甚至无法将RDD对象发送给执行者。在第二种情况下,将RDD内容拉到应用程序,然后将此简单List
发送给执行程序。 (Lambda捕获会自动序列化。)