In Sparkどのオブジェクトがドライバーでインスタンス化され、どのオブジェクトがexecutorでインスタンス化されるかをどのようにして知ることができますか。
オブジェクトをシリアル化するとは、その状態をバイトストリームに変換して、バイトストリームをオブジェクトのコピーに戻すことができるようにすることです。クラスまたはそのスーパークラスのいずれかがJava.io.SerializableインターフェースまたはそのサブインターフェースJava.io.Externalizableを実装している場合、Javaオブジェクトはシリアル化可能です。
クラスがシリアル化されることはありません。クラスのオブジェクトのみがシリアル化されます。オブジェクトをネットワーク上で永続化または送信する必要がある場合は、オブジェクトのシリアル化が必要です。
Class Component Serialization
instance variable yes
Static instance variable no
methods no
Static methods no
Static inner class no
local variables no
サンプルSpark=コードを取り、さまざまなシナリオを見てみましょう
public class SparkSample {
public int instanceVariable =10 ;
public static int staticInstanceVariable =20 ;
public int run(){
int localVariable =30;
// create Spark conf
final SparkConf sparkConf = new SparkConf().setAppName(config.get(JOB_NAME).set("spark.serializer", "org.Apache.spark.serializer.KryoSerializer");
// create spark context
final JavaSparkContext sparkContext = new JavaSparkContext(sparkConf);
// read DATA
JavaRDD<String> lines = spark.read().textFile(args[0]).javaRDD();
// Anonymous class used for lambda implementation
JavaRDD<String> words = lines.flatMap(new FlatMapFunction<String, String>() {
@Override
public Iterator<String> call(String s) {
// How will the listed varibles be accessed in RDD across driver and Executors
System.out.println("Output :" + instanceVariable + " " + staticInstanceVariable + " " + localVariable);
return Arrays.asList(SPACE.split(s)).iterator();
});
// SAVE OUTPUT
words.saveAsTextFile(OUTPUT_PATH));
}
// Inner Static class for the funactional interface which can replace the lambda implementation above
public static class MapClass extends FlatMapFunction<String, String>() {
@Override
public Iterator<String> call(String s) {
System.out.println("Output :" + instanceVariable + " " + staticInstanceVariable + " " + localVariable);
return Arrays.asList(SPACE.split(s)).iterator();
});
public static void main(String[] args) throws Exception {
JavaWordCount count = new JavaWordCount();
count.run();
}
}
内部クラスオブジェクト内の外部クラスからのインスタンス変数のアクセシビリティとシリアル化可能性
Inner class | Instance Variable (Outer class) | Static Instance Variable (Outer class) | Local Variable (Outer class)
Anonymous class | Accessible And Serialized | Accessible yet not Serialized | Accessible And Serialized
Inner Static class | Not Accessible | Accessible yet not Serialized | Not Accessible
理解しながらの経験則Spark job is:
RDD内に記述されたすべてのラムダ関数はドライバーでインスタンス化され、オブジェクトはシリアル化されてエグゼキューターに送信されます
外部クラスのインスタンス変数が内部クラス内でアクセスされる場合、コンパイラーはそれらにアクセスするために異なるロジックを適用します。したがって、外部クラスはシリアル化されるか、アクセスするかによって異なります。
Javaに関しては、全体の議論は外部クラスと内部クラスについてであり、外部クラスの参照と変数へのアクセスがシリアル化の問題にどのようにつながるかについてです。
さまざまなシナリオ:
コンパイラはデフォルトで、コンストラクタをバイトコードに挿入します
外部クラスオブジェクトを参照する匿名クラス。
外側のクラスオブジェクトは、インスタンス変数にアクセスするために使用されます
匿名クラス(){
final Outer-class reference;
Anonymous-class( Outer-class outer-reference){
reference = outer-reference;
}
}
外部クラスはシリアル化され、内部匿名クラスのシリアル化されたオブジェクトと共に送信されます
静的変数はシリアル化されないため、外部クラスオブジェクトは引き続き匿名クラスコンストラクターに挿入されます。
静的変数の値は、クラス状態から取得されます
そのexecutorに存在します。
コンパイラはデフォルトで、コンストラクタをバイトコードに挿入します
外部クラスオブジェクトとローカル変数の参照を参照する匿名クラス。
外側のクラスオブジェクトは、インスタンス変数にアクセスするために使用されます
匿名クラス(){
final Outer-class reference;
final Local-variable localRefrence ;
Anonymous-class( Outer-class outer-reference, Local-variable localRefrence){
reference = outer-reference;
this.localRefrence = localRefrence;
}
}
外部クラスはシリアル化され、ローカル変数オブジェクトも
シリアル化され、内部の匿名クラスのシリアル化されたオブジェクトと共に送信されます
ローカル変数が匿名クラス内のインスタンスメンバーになると、シリアル化する必要があります。外部クラスの観点からは、ローカル変数をシリアル化することはできません
アクセスできません
アクセスできません
静的変数はシリアル化されないため、外部クラスオブジェクトはシリアル化されません。
静的変数の値は、クラス状態から取得されます
そのexecutorに存在します。
外部クラスはシリアル化されず、シリアル化された静的内部クラスとともに送信されます
考慮すべき点:
Javaシリアル化ルールに従って、シリアル化する必要のあるクラスオブジェクトを選択します。
Javap -p -c "abc.class"を使用してバイトコードをアンラップし、コンパイラが生成したコードを確認します。
外部クラスの内部クラス内でアクセスしようとしているものに応じて、コンパイラは異なるバイトコードを生成します。
ドライバーでのみアクセスされるシリアル化を実装するクラスを作成する必要はありません。
RDD内で使用される匿名/静的クラス(すべてのラムダ関数は匿名クラスです)は、ドライバーでインスタンス化されます。
RDD内で使用されるクラス/変数は、ドライバーでインスタンス化され、エグゼキューターに送信されます。
Transientと宣言されたインスタンス変数は、ドライバーでシリアル化されません。
このような非常によく説明された非常によく書かれたブログがたくさんあります: spark serialization challenges 。
しかし、要するに、次のように結論付けることができます(一般的なJVMではなく、Sparkのみ)。
object
(aka、Scala singleton)への参照はシリアル化されません(mapPartitionおよびforeachPartitionのみ、UDFは常にserdeを取得しますエグゼキューターは、エグゼキューターJVM上に存在するシングルトンであるため、エグゼキューターはローカルJVMのオブジェクトを直接参照します。つまり、エグゼキューターからローカルobject
上のドライバーの変異は見られません。