Apache spark apachespark流媒体中的周期广播

Apache spark apachespark流媒体中的周期广播,apache-spark,spark-streaming,Apache Spark,Spark Streaming,我正在实现一个用于文本分类的流学习器。在我的实现中,有一些单值参数需要在新的流项目到达时更新。例如,我想在做出新的预测时改变学习速率。然而,我怀疑在最初的广播之后是否有广播变量的方法。那么,如果每次更新时都需要广播一个变量,会发生什么呢。如果有一种方法可以做到这一点,或者有一种解决办法可以让我在Spark Streaming中实现,我很乐意听到 提前感谢。我的理解是,一旦广播变量最初发出,它就是“只读”的。我相信您可以在本地节点上更新广播变量,但不能在远程节点上更新 也许你需要考虑这样做“外部火

我正在实现一个用于文本分类的流学习器。在我的实现中,有一些单值参数需要在新的流项目到达时更新。例如,我想在做出新的预测时改变学习速率。然而,我怀疑在最初的广播之后是否有广播变量的方法。那么,如果每次更新时都需要广播一个变量,会发生什么呢。如果有一种方法可以做到这一点,或者有一种解决办法可以让我在Spark Streaming中实现,我很乐意听到


提前感谢。

我的理解是,一旦广播变量最初发出,它就是“只读”的。我相信您可以在本地节点上更新广播变量,但不能在远程节点上更新


也许你需要考虑这样做“外部火花”。使用noSQL存储(Cassandra等)甚至Memcache怎么样?然后,您可以从一个任务更新变量,并从其他任务定期检查此存储?

最好将数据收集到驱动程序,然后将其广播到所有节点

用于在驱动程序处收集计算出的RDD,一旦知道何时需要更改学习速率,然后使用SparkContext#广播(值)将新值发送到所有节点

我希望代码看起来如下所示:

dStreamContainingBroadcastValue.foreachRDD{ rdd => 
      val valueToBroadcast = rdd.collect()
      sc.broadcast(valueToBroadcast)
}

您还可以从spark用户邮件列表中找到有用的信息。让我知道这是否有效。

我得到了一个丑陋的剧本,但它奏效了! 我们可以找到如何从广播对象获取广播值。 就凭广播id

val broadcastFactory = new TorrentBroadcastFactory()
broadcastFactory.unbroadcast(BroadcastId, true, true)
// append some ids to initIds
val broadcastcontent = broadcastFactory.newBroadcast[.Set[String]](initIds, false, BroadcastId)
所以我定期通过相同的广播id重播

val broadcastFactory = new TorrentBroadcastFactory()
broadcastFactory.unbroadcast(BroadcastId, true, true)
// append some ids to initIds
val broadcastcontent = broadcastFactory.newBroadcast[.Set[String]](initIds, false, BroadcastId)
我可以从第一个广播值中获取BroadcastId

val ids = ssc.sparkContext.broadcast(initIds)
// broadcast id
val BroadcastId = broadcastIds.id
然后,工人像正常情况一样使用ID作为广播类型

def func(record: Array[Byte], bc: Broadcast[Set[String]]) = ???

您可以试试这个,我不能保证是否有效,我是通过在广播变量上创建包装器类来实现的。包装类的updateAndGet方法返回刷新的广播变量。根据Spark文档,我在dStream.transform->中调用此函数

变换操作状态: 在每个批处理间隔内调用提供的函数。这允许您执行随时间变化的RDD操作,即RDD操作、分区数、广播变量等。可以在批处理之间更改

BroadcastWrapper类将如下所示:

public class BroadcastWrapper {
private Broadcast<ReferenceData> broadcastVar;
private Date lastUpdatedAt = Calendar.getInstance().getTime();

private static BroadcastWrapper obj = new BroadcastWrapper();

private BroadcastWrapper(){}

public static BroadcastWrapper getInstance() {
       return obj;
}

public JavaSparkContext getSparkContext(SparkContext sc) {
      JavaSparkContext jsc = JavaSparkContext.fromSparkContext(sc);
      return jsc;
}

public Broadcast<ReferenceData> updateAndGet(SparkContext sparkContext){
       Date currentDate = Calendar.getInstance().getTime();
       long diff = currentDate.getTime()-lastUpdatedAt.getTime();
       if (var == null || diff > 60000) { //Lets say we want to refresh every 1 min = 60000 ms
           if (var != null)
              var.unpersist();
           lastUpdatedAt = new Date(System.currentTimeMillis());

           //Your logic to refresh
           ReferenceData data = getRefData();

           var = getSparkContext(sparkContext).broadcast(data);
      }
      return var;
}
}
公共类包装器{
私人广播;
private Date lastUpdatedAt=Calendar.getInstance().getTime();
私有静态BroadcastWrapper obj=新的BroadcastWrapper();
私有广播包装器(){}
公共静态广播包装器getInstance(){
返回obj;
}
公共JavaSparkContext获取SparkContext(SparkContext sc){
JavaSparkContext jsc=JavaSparkContext.fromSparkContext(sc);
返回jsc;
}
公共广播更新网页(SparkContext SparkContext){
Date currentDate=Calendar.getInstance().getTime();
long diff=currentDate.getTime()-lastUpdatedAt.getTime();
如果(var==null | | diff>60000){//,假设我们希望每1分钟刷新一次=60000毫秒
如果(var!=null)
变量unpersist();
lastUpdatedAt=新日期(System.currentTimeMillis());
//你的逻辑需要更新
ReferenceData=getRefData();
var=getSparkContext(sparkContext).broadcast(数据);
}
收益var;
}
}
您可以在允许RDD-RDD转换的stream.transform方法中使用此广播变量updateAndGet函数

objectStream.transform(stream -> {

  Broadcast<Object> var = BroadcastWrapper.getInstance().updateAndGet(stream.context());

/**Your code to manipulate stream **/
});
objectStream.transform(流->{
Broadcast var=BroadcastWrapper.getInstance().updateAndGet(stream.context());
/**操作流的代码**/
});
请参阅我在此pos中的完整答案:


希望能有所帮助

那么,您认为他如何从该片段中读取广播变量?返回
单元
有点违背了它的目的。本地节点和远程节点之间有什么区别?