上一篇我们使用keyby后发现数据严重倾斜
https://blog.youkuaiyun.com/xingdianp/article/details/109953419
大概看下问题所在,大量数据在一个subtask中运行
这里我们使用两阶段keyby 解决该问题
之前的问题如下图所示
我们期望的是
但我们的需要根据key进行聚合统计,那么把相同的key放在不同的subtask如何统计?
我们看下图(只画了主要部分)
1.首先将key打散,我们加入将key转化为 key-随机数 ,保证数据散列
2.对打散后的数据进行聚合统计,这时我们会得到数据比如 : (key1-12,1),(key1-13,19),(key1-1,20),(key2-123,11),(key2-123,10)
3.将散列key还原成我们之前传入的key,这时我们的到数据是聚合统计后的结果,不是最初的原数据
4.二次keyby进行结果统计,输出到addSink
直接看实现代码
在这里插import org.apache.flink.api.common.functions.AggregateFunction
import org.apache.flink.api.common.state.{
ValueState, ValueStateDescriptor}
import org.apache.flink.api.java.tuple.Tuple
import org.apache.flink.api.scala.typeutils.Types
import org.apache.flink.streaming.api.functions.KeyedProcessFunction
import org.apache.flink.streaming.api.functions.windowing.WindowFunction
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.windowing.time.Time
import org.apache.flink.streaming.api.windowing.windows.TimeWindow
import org.apache.flink.util.Collector
object ProcessFunctionScalaV2 {
def main(args: Array[String]): Unit = {
val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
env.enableCheckpointing(2000)
val stream: DataStream[String] = env.socketTextStream("localhost", 9999)
val typeAndData: DataStream[(String, Long)] = stream.map(x => (