Apache spark 如何有效地使用spark读取具有分区热点的cassandra数据?

Apache spark 如何有效地使用spark读取具有分区热点的cassandra数据?,apache-spark,cassandra,spark-cassandra-connector,Apache Spark,Cassandra,Spark Cassandra Connector,据我所知,spark在读取cassandra时,每个cassandra分区最多使用一个任务。不幸的是,我在cassandra中有几个分区极不平衡(初始表设计糟糕)。我需要将这些数据读入一个新的表中,该表的设计将更好地处理热点,但使用普通spark Avenue这样做的任何尝试都不会有效;我只剩下一些任务(10+)永远在运行,处理那些巨大的分区键 为了让您了解规模,这是一个大约1.5TB大小的表,分布在5台服务器上,复制系数为3;~每个节点500GB 其他想法是受欢迎的,尽管仅仅转储到CSV可能不

据我所知,spark在读取cassandra时,每个cassandra分区最多使用一个任务。不幸的是,我在cassandra中有几个分区极不平衡(初始表设计糟糕)。我需要将这些数据读入一个新的表中,该表的设计将更好地处理热点,但使用普通spark Avenue这样做的任何尝试都不会有效;我只剩下一些任务(10+)永远在运行,处理那些巨大的分区键

为了让您了解规模,这是一个大约1.5TB大小的表,分布在5台服务器上,复制系数为3;~每个节点500GB

其他想法是受欢迎的,尽管仅仅转储到CSV可能不是一个现实的选择


到目前为止,物化视图的创建也是不可能的;这花费的时间太长,至少在3.0.8版本中,在创建过程中几乎没有监控。

这是一个无法自动解决的难题,但如果您知道数据如何分布在真正庞大的文件中,我可以给您一个选择

不要使用单个RDD/DataFrame来表示表,而是将其拆分为多个联合调用

基本上你想这样做

考虑到我们最大的分区是这样设置的

Key1 -> C1, C2, C3, ..., C5000000
我们知道,一般来说,C是这样分布的

Min C = 0
Max C = 5000000
Average C = 250000
我们可以猜测,通过每100kC值做一次范围下推,我们可以很好地分割这些大分区

val interval = 100000
val maxValue = 500000
sc.union(
 (0 until maxValue by interval).map{ lowerBound => 
   sc.cassandraTable("ks", "tab")
     .where(s"c > $lowerBound AND c < ${lowerBound + interval}")
  }
)
val间隔=100000
val最大值=500000
理学士联合会(
(0,直到按间隔最大值)。映射{lowerBound=>
sc.cassandraTable(“ks”、“tab”)
。其中(s“c>$lowerBound和c<${lowerBound+interval}”)
}
)
我们最终得到了更多更小的分区(可能还有很多空分区),但这应该能让我们成功地减少那些巨大的分区。但是,只有当您能够计算出分区中的值的分布时,才能做到这一点


注意:使用联合数据帧也可以实现同样的效果,正如我所知,每个分区中的最大范围是确定的,这可能是一个选项。我还可以做一个spark DF.groupBy('partitionKey).count.description,它应该会给出分布。分区键实际上是第一个集群键的前缀,这使得这种方法更加容易。我仍然认为这是spark cassandra连接器中的一个缺陷,找到一个解决这个问题的标准方法是很有趣的。问题是,如果不知道c的分布,就无法知道在哪里建立截止点。在Cassandra中有近似列统计之前,没有多少可以自动完成的。。但关键是你在阅读整本书之前先做切片和合并。