I.はじめに
いくつかの一般的な統計と情報の管理を容易にするために、スパークは、2つの共有変数--Broadcast(放送変数)とアキュムレータ、あなたは簡単にクラスタ内の各ノードに変数または一部のデータを共有することができます(アキュムレータ)を定義し、今日を見てみましょうアキュムレータ。
アキュムレータドライバーの終わりまでに全体的なメンテナンスは、ドライバーは、アキュムレータ変数の維持にも、それぞれのタスクエグゼキュータに、現在の値は終わりです読み込むが、唯一の地元の累積演算、蓄積した結果をマージするためにドライバーへの完全なエンドを実行します。アキュムレータは、2つのプロパティを持っています:
1、だけ蓄積することができる、即ち、累積合成。
図2は、場合にアキュムレータにトリガーアクション値を操作することなく実行レイジースパーク、即ちの動作特性を変更することなく、初期値のジョブが存在してもよいです。
二、アキュムレータの分類(Spark2.x):
1、スパークは、アキュムレータの種類が付属しています
(1)LongAccumulator(整数を蓄積するロングタイプ)
(2)DoubleAccumulator(ダブルfloat型を蓄積)
(3)CollectionAccumulator(コレクション型は、コレクション要素を蓄積します)
次のように作成:
LongAccumulator = sc.sc LongAccumulator()longAccumulator( "longAccumulator");. // ここでのWeb UI上の名前のためのlongAccumulatorアキュムレータ
2、カスタムアキュムレータ - アキュムレータ抽象クラスを継承ニーズAccumulatorV2へ
前記add()メソッド、マージ()メソッドは、値()メソッドと必要など必ずしもメソッドを実装する必要があります。
私は、カスタムアキュムレータの文字列連結を実装している下:
パッケージcom.renyang.sparkproject.spark.session。 輸入com.renyang.sparkproject.constant.Constants。 輸入com.renyang.sparkproject.util.StringUtils。 輸入org.apache.spark.util.AccumulatorV2; パブリック クラス SessionAggrStatAccumulatorV2が延び AccumulatorV2 <文字列、文字列> { プライベート 静的 最終 長いのserialVersionUID = 6311074555136039130L 。 プライベート文字列データ=「session_count = 0 | 1s_3s = 0 | 4s_6s = 3 | 7s_9s = 0 | 10s_30s = 0 | 30s_60s = 0 | 1m_3m = 0 | 3m_10m = 0 | 10m_30m = 0 | 30メートル= 0 | 1_3 = 0 | 4_6 = 1 | 7_9 = 0 | = 0 10_30 | = 0 30_60 | = 0" 60 ; プライベート文字列のゼロ=データ; @Override パブリック ブールisZero(){ 戻りdata.equals(ゼロ)。 } @Override 公共 AccumulatorV2 <文字列、文字列> コピー(){ 戻り 新しい)(SessionAggrStatAccumulatorV2します。 } @Override 公共 ボイドリセット(){ データ = ゼロ。 } 公共 ボイド追加(文字列V){ データ = (データ、V)を加えます。 } @Override 公共 ボイドマージ(AccumulatorV2 <文字列、文字列> その他){ O SessionAggrStatAccumulatorV2 = 他の(SessionAggrStatAccumulatorV2)。 String []型の言葉 = data.split( "\\ |" ); String []型owords = o.data.split( "\\ |" ); 以下のために(INT ; I <words.length; iが0 = I ++ ){ ため(INT ; J <owords.length J ++ J = 0 ){ 場合(単語[I] .split( "=")[0] .equals (owords [J] .split( "=")[0 ])){ int型値= Integer.valueOf(単語[I] .split( "=")[1])+ Integer.valueOf(owords [J]。スプリット( "=")[1 ])。StringUtils.setFieldInConcatString =(データ、 "\\ |"、owords [J] .split( "=")[0 ]、String.valueOf(値)); // マージするたびに、更新STR データ= NSを; } } } } @Override 公共の文字列値(){ 戻りデータ; } / ** セッション用*統計計算ロジック * @paramのV1接続文字列 * @paramの範囲間隔V2 * @return 将来の更新の接続文字列 * / プライベート文字列の追加(文字列V1、V2の文字列){ // チェック:v1は空で、リターンを直接V2 IF (StringUtils.isEmpty(V1)){ 戻りV2; } // 使用のStringUtilsツール、抽出された値、及び蓄積に対応するV1、V2内から1 列OLDVALUE StringUtils.getFieldFromConcatString =(V1、 "\\ |" 、V2 ); IF(OLDVALUE!= NULL ){ // 元の間隔の値の範囲、蓄積1。 INT newValueに= Integer.valueOf(OLDVALUE)+ 1 ; // 使用のStringUtilsツール、V1、V2対応する値で、累積の新しい値に設定 戻り StringUtils.setFieldInConcatString(V1、 "\\ |" 、V2、String.valueOf(newValueに)); } 戻りV1; } }
三、アキュムレータのオペレーティングロジック
1、ドライバ側は、アキュムレータを定義し、登録するための責任があります
ドライバアキュムレータは、最後に定義され、初期化され、SparkContextを登録する必要があり、クラスタ内の各ノードにアキュムレータ変数を分配するために、各タスクの完了は、合併の回復アキュムレータドライバ結果の最後まで実行された後、合併処理が基づいていますタスク実行の場合であれば、タスクアキュムレータ変数の完了が更新されるようにしてもよいです。
2、エグゼキュータ終了
RDDはデシリアライズと機能だけでなく、また、アキュムレータをデシリアライズ、エグゼキュータはタスクの後に実行され執行タスクを受信した後、その結果は、アキュムレータ端部に沿ってドライバーに一緒に戻されます。