Java 在ApacheSpark上为每个工作者创建一个单例
假设我想使用一个创建起来代价高昂的对象来映射RDD。我希望每个工作者/线程有一个这样的对象,并且必须在处理每个工作者上的RDD分区项之前创建它 我的解决办法是:Java 在ApacheSpark上为每个工作者创建一个单例,java,apache-spark,singleton,Java,Apache Spark,Singleton,假设我想使用一个创建起来代价高昂的对象来映射RDD。我希望每个工作者/线程有一个这样的对象,并且必须在处理每个工作者上的RDD分区项之前创建它 我的解决办法是: final Function0<ModelEvaluator> f = () -> { if (ModelEvaluator.getInstance() == null) { ModelEvaluator m = new ModelEvaluator(script);
final Function0<ModelEvaluator> f = () -> {
if (ModelEvaluator.getInstance() == null) {
ModelEvaluator m = new ModelEvaluator(script);
ModelEvaluator.setInstance(m);
}
return ModelEvaluator.getInstance();
};
JavaPairRDD<Double, List<Service>> results = cartesian.mapToPair(
(t) -> {
try {
double val = f.call().evaluateModel(t);
return new Tuple2<>(val, t);
} catch (Exception ex) {
return null;
}
}
);
public class ModelEvaluator {
private static ModelEvaluator instance;
public static void setInstance(ModelEvaluator instance) {
ModelEvaluator.instance = instance;
}
public static ModelEvaluator getInstance() {
return instance;
}
...
final function 0 f=()->{
if(modeleEvaluator.getInstance()==null){
ModelEvaluator m=新的ModelEvaluator(脚本);
modeleevaluator.setInstance(m);
}
返回modeleEvaluator.getInstance();
};
JavaPairRDD结果=cartesian.mapToPair(
(t) ->{
试一试{
double val=f.call().evaluateModel(t);
返回新的Tuple2(val,t);
}捕获(例外情况除外){
返回null;
}
}
);
公共类ModelEvaluator{
私有静态ModelEvaluator实例;
公共静态void setInstance(ModelEvaluator实例){
modeleevaluator.instance=实例;
}
公共静态ModelEvaluator getInstance(){
返回实例;
}
...
在本例中,“ModelEvaluator”对象解析脚本,然后使用“服务”对象列表来配置模型参数,以便计算该参数配置的相关响应度量。但我不希望每次处理RDD行时都解析脚本
我还将集群配置为为为每个集群创建一个进程,每个进程将只生成一个工作进程,因为在同一个进程中,多个工作进程同时访问状态可变的单实例会有问题
对于我的问题,有更优雅的解决方案吗?这可以通过
广播变量来实现。这将允许您在驱动程序上创建一个对象,并根据需要为每个工作人员发送一次
final Broadcast<ModelEvaluator> model = jsc.broadcast(new ModelEvaluator(script));
JavaPairRDD<Double, List<Service>> results = cartesian.mapToPair(
(t) -> {
try {
double val = model.value().evaluateModel(t);
return new Tuple2<>(val, t);
} catch (Exception ex) {
return null;
}
}
);
final Broadcast model=jsc.Broadcast(新的modeleevaluator(脚本));
JavaPairRDD结果=cartesian.mapToPair(
(t) ->{
试一试{
double val=model.value().evaluateModel(t);
返回新的Tuple2(val,t);
}捕获(例外情况除外){
返回null;
}
}
);
这可以通过广播
变量来完成。这将允许您在驱动程序上创建对象,并根据需要为每个工作人员发送一次
final Broadcast<ModelEvaluator> model = jsc.broadcast(new ModelEvaluator(script));
JavaPairRDD<Double, List<Service>> results = cartesian.mapToPair(
(t) -> {
try {
double val = model.value().evaluateModel(t);
return new Tuple2<>(val, t);
} catch (Exception ex) {
return null;
}
}
);
final Broadcast model=jsc.Broadcast(新的modeleevaluator(脚本));
JavaPairRDD结果=cartesian.mapToPair(
(t) ->{
试一试{
double val=model.value().evaluateModel(t);
返回新的Tuple2(val,t);
}捕获(例外情况除外){
返回null;
}
}
);
非常感谢,它非常有效。我需要制作“ModelEvaluator”类可序列化,并将某些字段配置为临时字段以避免出现问题。我需要使用一些逻辑来执行对象的延迟初始化,而不是在构造函数上初始化它。@DaniloM.Oliveira您能分享您的代码的最终版本吗?非常感谢,它非常有效。我需要“ModelEvaluator”类可序列化,并将一些字段配置为临时字段以避免问题。我需要使用一些逻辑来执行对象的延迟初始化,而不是在构造函数上初始化它。@DaniloM.Oliveira能否请您共享代码的最终版本?