この記事は、「新人クリエーションセレモニー」イベントに参加し、一緒にゴールドクリエーションの道を歩み始めました。
0.関連記事へのリンク
1.結合および接続演算子
API:
- union:union演算子は、同じタイプの複数のデータストリームを組み合わせて、同じタイプのデータストリームを生成できます。つまり、複数のDataStream[T]を新しいDataStream[T]に組み合わせることができます。データは、重複排除なしで先入れ先出し(先入れ先出し)モードでマージされます。
。
- 接続:
-
connectは、unionと同様の機能を提供して2つのデータストリームを接続します。unionとの違いは、connectは2つのデータストリームしか接続できないのに対し、unionは複数のデータストリームを接続できることです。
-
接続によって接続された2つのデータストリームのデータ型は一貫していない可能性があり、ユニオンによって接続された2つのデータストリームのデータ型は同じである必要があります。
-
接続後、2つのDataStreamはConnectedStreamsに変換されます。ConnectedStreamsは2つのストリームのデータに異なる処理方法を適用し、2つのストリーム間で状態を共有できます。
-
。
要件の例:
文字列型の2つのストリームを結合します
String型のストリームをLong型のストリームに接続します
コード:
import org.apache.flink.api.common.RuntimeExecutionMode;
import org.apache.flink.streaming.api.datastream.ConnectedStreams;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.co.CoMapFunction;
/**
* Author itcast
* Desc
*/
public class TransformationDemo02 {
public static void main(String[] args) throws Exception {
//1.env
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setRuntimeMode(RuntimeExecutionMode.AUTOMATIC);
//2.Source
DataStream<String> ds1 = env.fromElements("hadoop", "spark", "flink");
DataStream<String> ds2 = env.fromElements("hadoop", "spark", "flink");
DataStream<Long> ds3 = env.fromElements(1L, 2L, 3L);
//3.Transformation
DataStream<String> result1 = ds1.union(ds2);//合并但不去重 https://blog.csdn.net/valada/article/details/104367378
ConnectedStreams<String, Long> tempResult = ds1.connect(ds3);
//interface CoMapFunction<IN1, IN2, OUT>
DataStream<String> result2 = tempResult.map(new CoMapFunction<String, Long, String>() {
@Override
public String map1(String value) throws Exception {
return "String->String:" + value;
}
@Override
public String map2(Long value) throws Exception {
return "Long->String:" + value.toString();
}
});
//4.Sink
result1.print();
result2.print();
//5.execute
env.execute();
}
}
复制代码
2.分割し、サイド出力を選択します
API:
- 分割とは、ストリームを複数のストリームに分割することです。注:分割機能は期限切れになり、削除されました。
- 選択は、シャント後に対応するデータを取得することです
- サイド出力:プロセスメソッドを使用してストリーム内のデータを処理し、さまざまな処理結果のさまざまなOutputTagにデータを収集できます。
要件の例:
ストリーム内のデータを奇数と偶数で分割し、分割されたデータを取得します
コード:
import org.apache.flink.api.common.RuntimeExecutionMode;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.ProcessFunction;
import org.apache.flink.util.Collector;
import org.apache.flink.util.OutputTag;
/**
* Author itcast
* Desc
*/
public class TransformationDemo03 {
public static void main(String[] args) throws Exception {
//1.env
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setRuntimeMode(RuntimeExecutionMode.AUTOMATIC);
//2.Source
DataStreamSource<Integer> ds = env.fromElements(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
//3.Transformation
/*SplitStream<Integer> splitResult = ds.split(new OutputSelector<Integer>() {
@Override
public Iterable<String> select(Integer value) {
//value是进来的数字
if (value % 2 == 0) {
//偶数
ArrayList<String> list = new ArrayList<>();
list.add("偶数");
return list;
} else {
//奇数
ArrayList<String> list = new ArrayList<>();
list.add("奇数");
return list;
}
}
});
DataStream<Integer> evenResult = splitResult.select("偶数");
DataStream<Integer> oddResult = splitResult.select("奇数");*/
//定义两个输出标签
OutputTag<Integer> tag_even = new OutputTag<Integer>("偶数", TypeInformation.of(Integer.class));
OutputTag<Integer> tag_odd = new OutputTag<Integer>("奇数"){};
//对ds中的数据进行处理
SingleOutputStreamOperator<Integer> tagResult = ds.process(new ProcessFunction<Integer, Integer>() {
@Override
public void processElement(Integer value, Context ctx, Collector<Integer> out) throws Exception {
if (value % 2 == 0) {
//偶数
ctx.output(tag_even, value);
} else {
//奇数
ctx.output(tag_odd, value);
}
}
});
//取出标记好的数据
DataStream<Integer> evenResult = tagResult.getSideOutput(tag_even);
DataStream<Integer> oddResult = tagResult.getSideOutput(tag_odd);
//4.Sink
evenResult.print("偶数");
oddResult.print("奇数");
//5.execute
env.execute();
}
}
复制代码
3.リバランスリバランスパーティション
機能概要:
- Sparkの再パーティション化に似ていますが、より強力で、データの偏りを直接解決できます。
- Flinkにもデータスキューがあります。たとえば、現在約10億個のデータを処理する必要があります。処理プロセス中に、図に示すような状況が発生する可能性があります。データがスキューされている場合、他の3台のマシンはマシン1が実行を完了するのを待ちます。実行が完了すると、タスクは全体として完了したと見なされます。
。
- したがって、実際の作業では、この状況に対するより良い解決策はリバランスです(ラウンドロビン方式は、データを均等に分散するために内部的に使用されます)。
。
コードデモ:
import org.apache.flink.api.common.RuntimeExecutionMode;
import org.apache.flink.api.common.functions.FilterFunction;
import org.apache.flink.api.common.functions.RichMapFunction;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
/**
* Author itcast
* Desc
*/
public class TransformationDemo04 {
public static void main(String[] args) throws Exception {
//1.env
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setRuntimeMode(RuntimeExecutionMode.AUTOMATIC).setParallelism(3);
//2.source
DataStream<Long> longDS = env.fromSequence(0, 100);
//3.Transformation
//下面的操作相当于将数据随机分配一下,有可能出现数据倾斜
DataStream<Long> filterDS = longDS.filter(new FilterFunction<Long>() {
@Override
public boolean filter(Long num) throws Exception {
return num > 10;
}
});
//接下来使用map操作,将数据转为(分区编号/子任务编号, 数据)
//Rich表示多功能的,比MapFunction要多一些API可以供我们使用
DataStream<Tuple2<Integer, Integer>> result1 = filterDS
.map(new RichMapFunction<Long, Tuple2<Integer, Integer>>() {
@Override
public Tuple2<Integer, Integer> map(Long value) throws Exception {
//获取分区编号/子任务编号
int id = getRuntimeContext().getIndexOfThisSubtask();
return Tuple2.of(id, 1);
}
}).keyBy(t -> t.f0).sum(1);
DataStream<Tuple2<Integer, Integer>> result2 = filterDS.rebalance()
.map(new RichMapFunction<Long, Tuple2<Integer, Integer>>() {
@Override
public Tuple2<Integer, Integer> map(Long value) throws Exception {
//获取分区编号/子任务编号
int id = getRuntimeContext().getIndexOfThisSubtask();
return Tuple2.of(id, 1);
}
}).keyBy(t -> t.f0).sum(1);
//4.sink
//result1.print();//有可能出现数据倾斜
result2.print();//在输出前进行了rebalance重分区平衡,解决了数据倾斜
//5.execute
env.execute();
}
}
复制代码
4.その他のパーティション演算子
API:
。
説明:
パーティションを再販します。アップストリーム演算子とダウンストリーム演算子の並列処理に基づいて、レコードはラウンドロビン方式でダウンストリーム演算子の各インスタンスに出力されます。
例:
アップストリーム並列処理は2、ダウンストリームは4です。次に、1つのアップストリーム並列処理が2つのダウンストリーム並列処理に循環的にレコードを出力し、他のアップストリーム並列処理が他の2つのダウンストリーム並列処理に循環的にレコードを出力します。アップストリーム並列処理が4で、ダウンストリーム並列処理が2の場合、2つのアップストリーム並列処理は1つのダウンストリーム並列処理にレコードを出力し、他の2つのアップストリーム並列処理は他のダウンストリーム並列処理にレコードを出力します。
コードデモ:
import org.apache.flink.api.common.RuntimeExecutionMode;
import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.common.functions.Partitioner;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.util.Collector;
/**
* Author itcast
* Desc
*/
public class TransformationDemo05 {
public static void main(String[] args) throws Exception {
//1.env
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setRuntimeMode(RuntimeExecutionMode.AUTOMATIC);
//2.Source
DataStream<String> linesDS = env.readTextFile("data/input/words.txt");
SingleOutputStreamOperator<Tuple2<String, Integer>> tupleDS = linesDS.flatMap(new FlatMapFunction<String, Tuple2<String, Integer>>() {
@Override
public void flatMap(String value, Collector<Tuple2<String, Integer>> out) throws Exception {
String[] words = value.split(" ");
for (String word : words) {
out.collect(Tuple2.of(word, 1));
}
}
});
//3.Transformation
DataStream<Tuple2<String, Integer>> result1 = tupleDS.global();
DataStream<Tuple2<String, Integer>> result2 = tupleDS.broadcast();
DataStream<Tuple2<String, Integer>> result3 = tupleDS.forward();
DataStream<Tuple2<String, Integer>> result4 = tupleDS.shuffle();
DataStream<Tuple2<String, Integer>> result5 = tupleDS.rebalance();
DataStream<Tuple2<String, Integer>> result6 = tupleDS.rescale();
DataStream<Tuple2<String, Integer>> result7 = tupleDS.partitionCustom(new Partitioner<String>() {
@Override
public int partition(String key, int numPartitions) {
return key.equals("hello") ? 0 : 1;
}
}, t -> t.f0);
//4.sink
//result1.print();
//result2.print();
//result3.print();
//result4.print();
//result5.print();
//result6.print();
result7.print();
//5.execute
env.execute();
}
}
复制代码
このブログは、特定の馬の2020年の新年のビデオを基にしています。[ワイルドビッグデータ] Flink1.12エントリから熟練した#2021#ストリームバッチ統合#ダークホースプログラマー#ビッグデータ_bilibili_bilibili
注:他の関連記事へのリンクはこちら-> Flink Article Summary