- 通用的优化方式
1. 尽早fliter掉一些不需要的数据以及避免一些不必要的序列化。
2. 避免使用深层嵌套数据类型。
3. 对于数据倾斜使用调整并行度或者双层聚合的方式。
4. 一些基数较少的并且本身较长维度可以采用数据字典的方式减少网络传输及内存占用、gc开销。
- 数据类型和序列化 Flink支持java、scala基本数据类型,以及java Tuples、scala Case Class、Flink Value,对于这些数据类型,flink会采用自身的序列化反序列化器去做序列化操作,对于其他数据类型,flink会采用kyro方式序列化,kyro序列化方式效率会比flink自带的方式低很多。因此在数据序列化方面我们可以做如下工作
1. 尝试使用transient修饰不需要序列化的变量,或者修饰你可以在下游通过其他方式获取到变量,这个可以减少序列化流程和网络传输(但可能带来更多的内存占用用和gc消耗)
2. 对于一些特殊的数据你可以尝试重写writeObject() 和 readObject() 来自己控制一些序列化方式,如果更高效的话
3. 如果使用了lambda或者泛型的话,显式的指定类型信息让flink类型提取系统识别到以提升性能。
- 多组相同keyby可使用DataStreamUtils在多组keyby的场景可以采用DataStreamUtils.reinterpretAsKeyedStream的方式避免多次shuffle操作 - 尽量减少状态的大小
1. 设置合适的state TTL, 清洗过期状态,避免状态无限增大。
2. 减少状态字段数, 比如使用aggreteFunction 做窗口聚合时,可以只将要聚合的信息放入状态,其他keyBy字段以及窗口信息,可以通过processWindowFunction的方式获取,这样就是 aggregateFunction + ProcessWindowFunction,agg函数获取聚合信息,输出的结果到processwindowFunction中取获取窗口信息。
3. checkpoint频率不宜过高,超时时间不要太长,可以异步化的地方尽量异步化