我有一个简单的Spark作业,从一个5节点的Cassandra集群中读取500行,该集群总是运行6个任务,由于每个任务的大小而导致写入问题。我试过调整input_split_size,这似乎没有效果。目前我被迫重新分区表扫描,这是不理想的,因为它很昂贵。
阅读了几篇帖子后,我尝试在我的启动脚本(下面)中增加num-executors,虽然这没有效果。
如果没有办法在Cassandra表扫描中设置任务数量,那我可以做的很好......但我有这种不断的琐碎感觉,我在这里遗漏了一些东西。
Spark工作者住在C *节点上,这些节点是8核64GB服务器,每个服务器有2TB SSD。
...
val conf = new SparkConf(true).set("spark.cassandra.connection.host",
cassandraHost).setAppName("rowMigration")
conf.set("spark.shuffle.memoryFraction", "0.4")
conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
conf.set("spark.executor.memory", "15G")
conf.set("spark.cassandra.input.split.size_in_mb", "32") //default 64mb
conf.set("spark.cassandra.output.batch.size.bytes", "1000") //default
conf.set("spark.cassandra.output.concurrent.writes", "5") //default
val sc = new SparkContext(conf)
val rawEvents = sc.cassandraTable(cassandraKeyspace, eventTable)
.select("accountid", "userid", "eventname", "eventid", "eventproperties")
.filter(row=>row.getString("accountid").equals("someAccount"))
.repartition(100)
val object = rawEvents
.map(ele => (ele.getString("userid"),
UUID.randomUUID(),
UUID.randomUUID(),
ele.getUUID("eventid"),
ele.getString("eventname"),
"event type",
UUIDs.unixTimestamp(ele.getUUID("eventid")),
ele.getMap[String, String]("eventproperties"),
Map[String, String](),
Map[String, String](),
Map[String, String]()))
.map(row=>MyObject(row))
Object.saveToCassandra(targetCassandraKeyspace,eventTable)
启动脚本:
#!/bin/bash
export SHADED_JAR="Migrate.jar"
export SPARKHOME="${SPARKHOME:-/opt/spark}"
export SPARK_CLASSPATH="$SHADED_JAR:$SPARK_CLASSPATH"
export CLASS=com.migration.migrate
"${SPARKHOME}/bin/spark-submit" \
--class "${CLASS}" \
--jars $SHADED_JAR,$SHADED_JAR \
--master spark://cas-1-5:7077 \
--num-executors 15 \
--executor-memory 20g \
--executor-cores 4 "$SHADED_JAR" \
--worker-cores 20 \
-Dcassandra.connection.host=10.1.20.201 \
-Dzookeeper.host=10.1.20.211:2181 \
编辑 - 遵循Piotr的回答:
我已经在sc.cassandraTable上设置了ReadConf.splitCount,如下所示,但是这并没有改变生成的任务数量,这意味着我仍然需要重新分区表扫描。我开始认为我正在考虑这个错误,重新分配是必要的。目前这项工作大约需要1.5小时,并且将表扫描重新分区为1000个大约10MB的任务,这使得写入时间减少到几分钟。
val cassReadConfig = new ReadConf {
ReadConf.apply(splitCount = Option(1000)
)
}
val sc = new SparkContext(conf)
val rawEvents = sc.cassandraTable(cassandraKeyspace, eventTable)
.withReadConf(readConf = cassReadConfig)
答案 0 :(得分:3)
自Spark连接器1.3以来,基于Cassandra 2.1.5以来可用的system.size_estimates Cassandra表估算分割大小。此表由Cassandra定期刷新,在加载/删除新数据或加入新节点后不久,其内容可能不正确。检查那里的估算是否反映了您的数据量。这是一个相对较新的功能,因此很可能存在一些错误。
如果估算错误,或者您正在运行较旧的Cassandra,我们就可以覆盖自动拆分大小调整。 sc.cassandraTable采用ReadConf参数,您可以在其中设置splitCount,这会强制执行固定数量的拆分。
对于split_size_in_mb参数,确实在项目源中存在一段时间的错误,但在发布到发布到maven的任何版本之前已经修复了。因此,除非您从(旧)源代码编译连接器,否则不应该点击它。
答案 1 :(得分:0)
split.size_in_mb参数似乎存在错误。代码可能将其解释为字节而不是兆字节,因此请尝试将32更改为更大的内容。请参阅答案here中的示例。