早上好,
我刚刚开始调查Apache Spark和Apache Cassandra。第一步是一个真正简单的用例:获取包含例如文件的文件。客户+得分。
Cassandra表的客户为PrimaryKey。 Cassandra只是在本地运行(所以根本没有集群!)。
所以SparkJob(Standalone local [2])正在解析JSON文件,然后将整个内容写入Cassandra。
第一个解决方案是
val conf = new SparkConf().setAppName("Application").setMaster("local[2]")
val sc = new SparkContext(conf)
val cass = CassandraConnector(conf)
val customerScores = sc.textFile(file).cache()
val customerScoreRDD = customerScores.mapPartitions(lines => {
val mapper = new ObjectMapper with ScalaObjectMapper
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
mapper.registerModule(DefaultScalaModule)
lines
.map(line => {
mapper.readValue(line, classOf[CustomerScore])
})
//Filter corrupt ones: empty values
.filter(customerScore => customerScore.customer != null && customerScore.score != null)
})
customerScoreRDD.foreachPartition(rows => cass.withSessionDo(session => {
val statement: PreparedStatement = session.prepare("INSERT INTO playground.customer_score (customer,score) VALUES (:customer,:score)")
rows.foreach(row => {
session.executeAsync(statement.bind(row.customer.asInstanceOf[Object], row.score))
})
}))
sc.stop()
表示手动完成所有操作,解析行然后插入Cassandra。
对于10000000条记录,总共需要 714020 ms (包括创建SparkContext等等)。
然后我读到了spark-cassandra-connector并做了以下事情:
val conf = new SparkConf().setAppName("Application").setMaster("local[2]")
val sc = new SparkContext(conf)
var sql = new SQLContext(sc)
val customerScores = sql.read.json(file)
val customerScoresCorrected = customerScores
//Filter corrupt ones: empty values
.filter("customer is not null and score is not null")
//Filter corrupt ones: invalid properties
.select("customer", "score")
customerScoresCorrected.write
.format("org.apache.spark.sql.cassandra")
.mode(SaveMode.Append)
.options(Map("keyspace" -> "playground", "table" -> "customer_score"))
.save()
sc.stop()
在所需代码和使用给定API的意义上更简单。
对于10000000条记录,此解决方案大致需要 1232871 ms (同样全部,所以相同的测量点)。
(还有第三个解决方案,手动解析加saveToCassandra
1530877 ms )
现在我的问题:
哪种方式是"正确"实现这个用例的方法,哪一个是最佳实践" (现在,在一个真实场景中,聚集的cassandra和spark,表现最好的一个)如今?
由于我的结果,我会使用"手册"而不是SQLContext.read
+ SQLContext.write
。
感谢您的意见和提示。
答案 0 :(得分:0)
实际上在玩了很长时间之后,必须考虑以下事项。
我的UseCase玩
def initSparkContext: SparkContext = {
val conf = new SparkConf().setAppName("Application").setMaster("local[2]")
// since we have nearly totally different PartitionKeys, default: 1000
.set("spark.cassandra.output.batch.grouping.buffer.size", "1")
// write as much concurrently, default: 5
.set("spark.cassandra.output.concurrent.writes", "1024")
// batch same replica, default: partition
.set("spark.cassandra.output.batch.grouping.key", "replica_set")
val sc = new SparkContext(conf)
sc
}
在我的本地跑步中确实提高了速度。
所以非常需要尝试各种参数来获得最佳方式。至少这是我得到的结论。