我的ElasticSearch集群中有一些与销售相关的JSON数据,我想使用Spark Streaming(使用Spark 1.4.1)从我的电子商务网站通过Kafka动态汇总传入的销售事件,以获得当前视图用户的总销售额(按收入和产品计算)。
我从我所阅读的文档中得到的不清楚的是我如何在Spark应用程序启动时从ElasticSearch加载历史数据,并计算每个用户的总体收入(基于历史,以及来自卡夫卡的收入)。
我有以下(工作)代码连接到我的Kafka实例并接收JSON文档:
import kafka.serializer.StringDecoder
import org.apache.spark.streaming._
import org.apache.spark.streaming.kafka._
import org.apache.spark.{SparkContext, SparkConf}
import org.apache.spark.sql.SQLContext
object ReadFromKafka {
def main(args: Array[String]) {
val checkpointDirectory = "/tmp"
val conf = new SparkConf().setAppName("Read Kafka JSONs").setMaster("local[2]")
val topicsSet = Array("tracking").toSet
val sc = new SparkContext(conf)
val ssc = new StreamingContext(sc, Seconds(10))
// Create direct kafka stream with brokers and topics
val kafkaParams = Map[String, String]("metadata.broker.list" -> "localhost:9092")
val messages = KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder](
ssc, kafkaParams, topicsSet)
//Iterate
messages.foreachRDD { rdd =>
//If data is present, continue
if (rdd.count() > 0) {
//Create SQLContect and parse JSON
val sqlContext = new SQLContext(sc)
val trackingEvents = sqlContext.read.json(rdd.values)
//Sample aggregation of incoming data
trackingEvents.groupBy("type").count().show()
}
}
// Start the computation
ssc.start()
ssc.awaitTermination()
}
}
我知道ElasticSearch(https://www.elastic.co/guide/en/elasticsearch/hadoop/master/spark.html#spark-read)有一个插件,但我不清楚如何在启动时集成读取,以及流式计算过程来汇总历史记录数据与流数据。
帮助非常紧张!提前谢谢。
答案 0 :(得分:1)
RDD是不可变的,因此在创建后,您无法向其添加数据,例如使用新事件更新收入。
您可以做的是将现有数据与新事件结合起来以创建新的RDD,然后您可以将其用作当前总数。例如......
var currentTotal: RDD[(Key, Value)] = ... //read from ElasticSearch
messages.foreachRDD { rdd =>
currentTotal = currentTotal.union(rdd)
}
在这种情况下,我们将currentTotal
设为var
,因为当它与传入数据联合时,它将替换为对新RDD的引用。
在联合之后,您可能需要执行一些进一步的操作,例如减少属于同一个键的值,但是您可以获得图片。
如果您使用此技术,请注意RDD的谱系将增长,因为每个新创建的RDD将引用其父级。这可能会导致堆栈溢出样式沿袭问题。要解决此问题,您可以定期在RDD上调用checkpoint()
。