Apache spark streaming-用于加入的缓存数据集

Apache spark streaming-用于加入的缓存数据集,streaming,apache-spark,Streaming,Apache Spark,我正在考虑使用ApacheSpark streaming进行一些实时工作,但我不确定如何缓存数据集以用于连接/查找 主要输入是来自Kafka的json记录,其中包含一个Id,我想使用查找数据集将该Id转换为名称。查找数据集驻留在Mongo Db中,但我希望能够将其缓存在spark进程中,因为数据集很少更改(每两小时更改一次),因此我不希望针对每个输入记录点击Mongo或重新加载每个spark批中的所有记录,但我需要能够定期(例如每2小时)更新spark中保存的数据 最好的方法是什么 谢谢。我自己

我正在考虑使用ApacheSpark streaming进行一些实时工作,但我不确定如何缓存数据集以用于连接/查找

主要输入是来自Kafka的json记录,其中包含一个Id,我想使用查找数据集将该Id转换为名称。查找数据集驻留在Mongo Db中,但我希望能够将其缓存在spark进程中,因为数据集很少更改(每两小时更改一次),因此我不希望针对每个输入记录点击Mongo或重新加载每个spark批中的所有记录,但我需要能够定期(例如每2小时)更新spark中保存的数据

最好的方法是什么


谢谢。

我自己也想过很久了。我特别想知道,是否有可能在Spark中实现数据库DB

答案是肯定的。首先,您需要一个程序,首先将主数据集缓存到内存中,然后每隔几个小时与tiny进行一次优化连接,以更新主数据集。现在,Spark显然有了一个方法,可以与tiny进行连接(可能它已经在1.0.0中发布了-我的堆栈在CDH5.1.0发布之前一直停留在0.9.0中)

无论如何,您可以使用tiny手动实现连接,方法是将周期性的每两小时数据集转换为HashMap,然后将其作为广播变量广播。这意味着HashMap将被复制,但每个节点只复制一次(与仅引用映射相比,它将在每个任务中被复制一次,成本要高得多)。然后,获取主数据集并使用广播地图添加新记录。然后可以定期(每晚)保存到hdfs或其他文件

下面是一些粗糙的伪代码来说明:

var mainDataSet: RDD[KeyType, DataType] = sc.textFile("/path/to/main/dataset")
  .map(parseJsonAndGetTheKey).cache()

everyTwoHoursDo {
  val newData: Map[KeyType, DataType] = sc.textFile("/path/to/last/two/hours")
    .map(parseJsonAndGetTheKey).toarray().toMap

  broadcast(newData)

  val mainDataSetNew = 
    mainDataSet.map((key, oldValue) => (key, 
      newData.get(key).map(newDataValue => 
        update(oldValue, newDataValue))
      .getOrElse(oldValue)))
    .cache()

  mainDataSetNew.someAction() // to force execution

  mainDataSet.unpersist()
  mainDataSet = mainDataSetNew
}
我还认为您可以非常聪明,使用自定义分区器和您自己的自定义索引,然后使用自定义方式更新分区,以便每个分区本身都拥有一个子映射。然后,您可以跳过更新您知道不会保存newData中出现的任何键的分区,并优化更新过程

我个人认为这是一个非常酷的想法,值得高兴的是,您的数据集已经在内存中准备好进行一些分析/机器学习。不利的一面是你有点重新发明轮子。考虑使用Cassandra可能是一个更好的主意,因为Datastax正在与Databricks(制造Spark的人)合作,并且可能最终支持像这样开箱即用的东西

进一步阅读:


以下是一个相当简单的工作流程:

对于每批数据:

  • 将批JSON数据转换为数据帧(b_df)
  • 将MongoDB中的查找数据集作为数据帧(m_df)读取。然后缓存,m_df.cache()
  • 使用b_df.Join(m_df,“Join_字段”)连接数据
  • 执行所需的聚合,然后写入数据源
    使用可累加的哈希映射怎么样?获取累加的局部值可能很有用,特别是如果相似的数据最终出现在同一分区中,那么更是如此。