在我们的Spark Pipeline中,我们读取了来自kafka的消息。
JavaPairDStream<byte[],byte[]> = messagesKafkaUtils.createStream(streamingContext, byte[].class, byte[].class,DefaultDecoder.class,DefaultDecoder.class,
configMap,topic,StorageLevel.MEMORY_ONLY_SER());
我们使用地图功能转换这些消息。
JavaDStream<ProcessedData> lines=messages.map(new Function<Tuple2<byte[],byte[]>, ProcessedData>()
{
public ProcessedData call(Tuple2<byte[],byte[]> tuple2)
{
}
});
//这里ProcessedData是我的消息bean类。
在此之后,我们使用foreachRDD函数将此消息保存到Cassandra中。然后我们使用foreachRDD函数在ElasticSearch中索引相同的消息。我们要求的是首先将消息存储在cassandra中并且它成功执行然后仅将其编入索引ElasticSearch。要实现这一点,我们需要顺序执行Cassandra和弹性搜索功能。
我们无法在Cassandra的foreachRDD函数中生成JavaDStream作为ElasticSearch Function的输入。
如果我们在其中使用map函数,我们可以成功执行Cassandra和Elastic Search函数的顺序执行。但是我们的Spark Pipeline中没有Action并且它没有被执行。
非常感谢任何帮助。
答案 0 :(得分:0)
实现此排序的一种方法是将Cassandra插入和ElasticSearch索引放在同一任务中。 粗略地像这样(*):
val kafkaDStream = ???
val processedData = kafkaDStream.map(elem => ProcessData(elem))
val cassandraConnector = CassandraConnector(sparkConf)
processData.forEachRDD{rdd =>
rdd.forEachPartition{partition =>
val elasClient = ??? elasticSearch client instance
partition.foreach{elem =>
cassandraConnector.withSessionDo(session =>
session.execute("INSERT ....")
}
elasClient.index(elem) // whatever the client method is called
}
}
}
我们牺牲了批处理操作的能力(例如,通过Cassandra-spark连接器在内部完成)以实现排序。
(*)这段代码的Java版本结构非常相似,只是更详细。