【发布时间】:2014-11-25 01:08:39
【问题描述】:
假设我们有一个 RF = N 的 Cassandra 集群和一个包含宽行的表。
我们的表可能有一个类似这样的索引:pk / ck1 / ck2 / ....
如果我们从表中的一行创建一个RDD如下:
val wide_row = sc.cassandraTable(KS, TABLE).select("c1", "c2").where("pk = ?", PK)
我注意到一个 Spark 节点拥有 100% 的数据,而其他节点则没有。我认为这是因为 spark-cassandra-connector 无法将查询令牌范围分解为更小的子范围,因为它实际上不是一个范围——它只是 PK 的哈希。
此时,我们可以简单地调用redistribute(N),在处理之前将数据分散到 Spark 集群中,但这会导致将数据通过网络移动到 Cassandra 本地已经拥有数据的节点(记住 RF = N )
我们真正想要的是让每个 Spark 节点从 Cassandra 本地加载行的子集(切片)。
想到的一种方法是在 pk = PK 时生成一个包含第一个集群键 (ck1) 的不同值列表的 RDD。然后,我们可以使用mapPartitions() 根据 ck1 的每个值加载宽行的切片。
假设我们已经有了 ck1 的列表值,我们可以这样写:
val ck1_list = .... // RDD
ck1_list.repartition(ck1_list.count().toInt) // create a partition for each value of ck1
val wide_row = ck1_list.mapPartitions(f)
在分区迭代器 f() 中,我们想调用另一个函数 g(pk, ck1),它从 Cassandra 加载行切片,用于分区键 pk 和集群键 ck1。然后我们可以将flatMap 应用到ck1_list,从而创建一个完全分布式的宽行RDD,而无需任何洗牌。
那么问题来了:
是否可以从 Spark 任务中进行 CQL 调用?应该使用什么驱动程序?是否只能设置一次以重复用于后续任务?
任何帮助将不胜感激,谢谢。
【问题讨论】:
标签: scala cassandra apache-spark