flink开源组件熟悉(各方面的笔记整理)

flink开源组件熟悉

(将网上的关于flink的资料整理了一下,也加上了一点自己的看法,整理不易,希望能有个赞就行)

一、flink对比其他流式处理框架的区别及其优势

flink的优点
  1. 高吞吐、低延迟、纯流式架构
  2. 支持对乱序事件的处理
  3. 有状态、提供exactly-once计算
  4. 高度灵活的窗口机制
  5. 失败恢复、故障转移、水平扩展
  6. 批处理、流处理统一的API
flink VS spark

相关资料:

Spark 和 Flink 全方面对比(谁是下一代大数据流计算引擎?)

Spark、Strom、Flink和Beam的技术选型


相同点:

  • 都基于内存计算;
  • 都有统一的批处理和流处理APl,都支持类似SQL的编程接口;
  • 都支持很多相同的转换操作,编程都是用类似于Scala Collection APl的函数式编程模式;
  • 都有完善的错误恢复机制;
  • 都支持Exactly once的语义一致性。

不同点:

  • 从流处理的角度来讲,Spark基于微批量处理,把流数据看成是一个个小的批处理数据块分别处理,所以延迟性只能做到秒级。而Flink基于每个事件处理,每当有新的数据输入都会立刻处理,是真正的流式计算,支持毫秒级计算。由于相同的原因,Spark只支持基于时间的窗口操作(处理时间或者事件时间),而Flink支持的窗口操作则非常灵活,不仅支持时间窗口,还支持基于数据本身的窗口,开发者可以自由定义想要的窗口操作。
  • 从SQL 功能的角度来讲,Spark和Flink分别提供SparkSQL和Table APl提供SQL交互支持。两者相比较,Spark对SQL支持更好,相应的优化、扩展和性能更好,而Flink在SQL支持方面还有很大提升空间。
  • 从迭代计算的角度来讲,Spark对机器学习的支持很好,因为可以在内存中缓存中间计算结果来加速机器学习算法的运行。但是大部分机器学习算法其实是一个有环的数据流,在Spark中,却是用无环图来表示。而Flink支持在运行时间中的有环数据流,从而可以更有效的对机器学习算法进行运算。
  • 从相应的生态系统角度来讲,Spark 的社区无疑更加活跃。Spark可以说有着Apache旗下最多的开源贡献者,而且有很多不同的库来用在不同场景。而Flink由于较新,现阶段的开源社区不如Spark活跃,各种库的功能也不如Spark全面。但是Flink还在不断发展,各种功能也在逐渐完善。

二、flink的相关特性

相关资料

Flink CheckPoint机制 学习 测试 使用FsStateBackend状态后端 将checkpoint恢复到中断处

flink状态与checkpoint机制

Flink 状态管理:算子状态、键值分区状态、状态后端、有状态算子的扩缩容

Flink checkpoint实现原理

Flink的Checkpoint和Savepoint介绍


Flink的失败恢复依赖于 检查点机制+ 可部分重发的数据源。

检查点机制机制:

checkpoint定期触发,产生快照,快照中记录了:当前检查点开始时数据源(例如Kafka)中消息的offset。

记录了所有有状态的operator当前的状态信息(例如sum中的数值)。

可部分重发的数据源:

Flink选择最近完成的检查点K,然后系统重放整个分布式的数据流,

然后给予每个operator他们在检查点k快照中的状态。数据源被设置为从位置Sk开始重新读取流。例如在Kafka中那意味着告诉消费者从偏移量Sk开始重新消费

checkpoint的机制

Flink分布式快照的核心在于stream barrier,barrier是一种特殊标记的消息,它会作为数据流的一部分和数据一起向下流动。**barrier不会干扰正常的数据,数据流严格有序。**一个barrier把数据流分割成两部分;一部分进入当前的快照,另一部分进入下一个快照。每一个barrier都带有快照ID,并且barrier之前的数据都进入了此快照。barrier不会干扰数据流处理,所以很轻量。多个不同快照的多个barrier会在流中同时出现。即多个快照可能同时创建。而当一个operator从它所有的input channel中都收到barrier,则会触发当前operator的快照操作,并且向其下游channel中发射barrier。当所有的sink都反馈完成快照之后,Checkpoint coordinator认为检查点创建完毕。

   接下来将对Checkpoint的执行流程逐步拆解进行讲解,其主要触发为JobMaster中的Checkpoint Coordinator,其是整个Checkpoint的发起者,之后便是source算子,经过一系列的transformation算子最终到达sink至外部持久化存储,其主要执行步骤如下:

第一步,Checkpoint Coordinator向所有source节点trigger Checkpoint;
第二步,source节点向下游广播barrier,这个barrier就是实现Chandy-Lamport分布式快照算法的核心,下游的task只有收到所有input的barrier才会执行相应的Checkpoint。
第三步,当task完成state备份后,会将备份数据的地址(state handle)通知给Checkpoint coordinator。
第四步,下游的transformation节点算子收集齐上游多个input的barrier之后,会异步执行本地的算子状态快照。并将barrier继续向下游传递。
同样的,sink节点在完成自己的Checkpoint之后,会将state handle返回通知给Coordinator。
最后,当Checkpoint coordinator收集齐所有task的state handle,就认为这一次的Checkpoint全局完成了,向持久化存储中再备份一个Checkpoint meta文件。

PS:

  • 与spark的checkpoint相比较

spark streaming 的 checkpoint 仅仅是针对 driver 的故障恢复做了数据和元数据的 checkpoint。而 flink 的 checkpoint 机制 要复杂了很多,它采用的是轻量级的分布式快照,实现了每个算子的快照,及流动中的数据的快照。

  • 由于Flink 中的Checkpoint机制默认是不开启的,需要用户通过调用以下方法开启检查点机制:
env.enableCheckpointing(1000);
  • 为了控制检查点执行的⼀些细节,Flink⽀持用户定制Checkpoiont的⼀些行为:
 //间隔5s执⾏⼀次checkpoint 精准⼀次
 env.enableCheckpointing(5000,CheckpointingMode.EXACTLY_ONCE)
 //设置检查点超时 4s
 env.getCheckpointConfig.setCheckpointTimeout(4000)
 //开启本次检查点 与上⼀次完成的检查点时间间隔不得⼩于 2s 优先级⾼于 checkpoint interval
 env.getCheckpointConfig.setMinPauseBetweenCheckpoints(2000)
 //如果检查点失败,任务宣告退出 setFailOnCheckpointingErrors(true)
 env.getCheckpointConfig.setTolerableCheckpointFailureNumber(0)
 //设置如果任务取消,系统该如何处理检查点数据
 //RETAIN_ON_CANCELLATION:如果取消任务的时候,没有加--savepoint,系统会保留检查点数据
 //DELETE_ON_CANCELLATION:取消任务,⾃动是删除检查点(不建议使⽤)
 env.getCheckpointConfig.enableExternalizedCheckpoints(ExternalizedCheckpointCleanup.
RETAIN_ON_CANCELLATION)
  • 检查点协调器
    Flink的checkpoint是通过定时器周期性触发的,checkpoint触发最关键的类是CheckpointCoordinator,称它为检查点协调器。
    CheckpointCoordinator主要作用是协调operators和state的分布式快照。
    它通过向相关的tasks发送触发消息和从各tasks收集确认消息(Ack)来完成checkpoint。
    同时,它还收集和维护各个tasks上报的状态句柄/状态引用(state handles)。
savepoint的机制

Savepoint是通过Flink的检查点机制创建的流作业执行状态的一致图像。
可以使用Savepoints来停止和恢复,分叉或更新Flink作业。

保存点由两部分组成:
稳定存储(例如HDFS,S3,…)上的(通常是大的) 二进制文件
和(相对较小的) 元数据文件的目录。

Savepoint是⼿动触发的Checkpoint,Savepoint为程序创建快照并将其写到State Backend。Savepoint依靠常规的Checkpoint机制。所谓的Checkpoint指的是程序在执⾏期间,程序会定期在⼯作节点上快照并产⽣Checkpoint。为了进⾏恢复,仅需要获取最后⼀次完成的Checkpoint即可,并且可以在新的Checkpoint完成后⽴即安全地丢弃较旧的Checkpoint。

Savepoint与这些定期Checkpoint类似,Savepoint由⽤户触发并且更新的Checkpoint完成时不会⾃动过期。⽤户可以使⽤命令⾏或通过REST API取消作业时创建Savepoint。

状态机制

Flink 内置的很多算子,包括源 source,数据存储 sink 都是有状态的。在
Flink 中,状态始终与特定算子相关联。Flink 会以 checkpoint 的形式对各个任务的
状态进行快照,用于保证故障恢复时的状态一致性。Flink 通过状态后端来管理状态
和 checkpoint 的存储,状态后端可以有不同的配置选择。

flink有两个基本状态

operator state(算子状态)和keyed state(键控状态,键值分区状态)

算子状态目前支持的存储类型只有以下三种:

  • ListState:将状态表示为一组数据的列表。(每一个并行的子任务共享一个状态)
  • UnionListState:同样将状态表示为数据的列表,但在进行故障恢复或者从某个保存点(savepoint)启动应用的时候,状态恢复的方式和普通的列表状态有所不同:如果并行度发生变化,ListState 会将该算子的所有并发的状态实例进行汇总,然后均分给新的 Task;而 UnionListState 只是将所有并发的状态实例汇总起来,具体的划分行为则由用户进行定义。(每一个并行的子任务共享一个状态)
  • BroadcastState:用于广播的算子状态。专门为那些需要保证算子的每个任务状态都相同的场景而设计。如果一个算子有多项任务,而它的每项任务状态又都相同,那么这种特殊情况最适合应 用广播状态。(把同一个状态广播给所有算子子任务)

算子状态的作用域是某个算子任务,这意味着所有在同一个并行任务之内的记录都能访问到相同的状态(每一个并行的子任务都共享一个状态)。算子状态不能通过其他任务访问,无论该任务是否来自相同算子(相同算子的不同任务之间也不能访问)。

键控状态:

  • ValueState:存储单值类型的状态。可以使用 update(T) 进行更新,并通过 T value() 进行检索。
  • ListState:存储列表类型的状态。可以使用 add(T) 或 addAll(List) 添加元素;并通过 get() 获得整个列表。
  • ReducingState:用于存储经过 ReduceFunction 计算后的结果,使用 add(T) 增加元素。
  • AggregatingState:用于存储经过 AggregatingState 计算后的结果,使用 add(IN) 添加元素。
  • FoldingState:已被标识为废弃,会在未来版本中移除,官方推荐使用 AggregatingState 代替。
  • MapState:维护 Map 类型的状态。

键值分区状态会按照算子输入记录所定义的键值来进行维护或访问。Flink为每个键值都维护了一个状态实例,该实例总是位于那个处理对应键值记录的算子任务上。当任务在处理一个记录时,会自动把状态的访问范围限制为当前记录的键值,因此所有键值相同的记录都能访问到一样的状态。

状态后端

默认情况下,所有的状态都存储在 JVM 的堆内存中,在状态数据过多的情况下,这种方式很有可能导致内存溢出,因此 Flink 该提供了其它方式来存储状态数据,这些存储方式统一称为状态后端 (或状态管理器)。

主要有以下三种:

  • MemoryStateBackend

默认的方式,即基于 JVM 的堆内存进行存储,主要适用于本地开发和调试。(内存级的状态后端,会将键控状态作为内存中的对象进行管理,将它们存储在TaskManager的JVM堆上;而将checkpoint存储在JobManager的内存中)

  • FsStateBackend

基于文件系统进行存储,可以是本地文件系统,也可以是 HDFS 等分布式文件系统。需要注意而是虽然选择使用了 FsStateBackend ,但正在进行的数据仍然是存储在 TaskManager 的内存中的,只有在 checkpoint 时,才会将状态快照写入到指定文件系统上。

  • RocksDBStateBackend

RocksDBStateBackend 是 Flink 内置的第三方状态管理器,采用嵌入式的 key-value 型数据库 RocksDB 来存储正在进行的数据。等到 checkpoint 时,再将其中的数据持久化到指定的文件系统中,所以采用 RocksDBStateBackend 时也需要配置持久化存储的文件系统。之所以这样做是因为 RocksDB 作为嵌入式数据库安全性比较低,但比起全文件系统的方式,其读取速率更快;比起全内存的方式,其存储空间更大,因此它是一种比较均衡的方案。

Flink 支持使用两种方式来配置后端管理器:

第一种方式:基于代码方式进行配置,只对当前作业生效:

 // 配置 FsStateBackend
env.setStateBackend(newFsStateBackend("hdfs://namenode:40010/flink/checkpoints"));
// 配置 RocksDBStateBackend
env.setStateBackend(newRocksDBStateBackend("hdfs://namenode:40010/flink/checkpoints"));
<!--配置RocksDBStateBackend时需要引入以下jar包-->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-statebackend-rocksdb_2.11</artifactId>
<version>1.9.0</version>
</dependency>

第二种方式:基于 flink-conf.yaml 配置文件的方式进行配置,对所有部署在该集群上的作业都生效:

state.backend: filesystem
state.checkpoints.dir: hdfs://namenode:40010/flink/checkpoints
有状态算子的扩缩容

流式应用的一项基本需求是根据输入数据到达速率的变化调整算子的并行度。对于无状态的算子扩缩容很容易,但是对于有状态算子来说,这就变的复杂了很多。因为我们需要把状态重新分组,分配到与之前数量不等的并行任务上。

针对不同类型状态的算子,Flink提供了四种扩缩容模式

  1. 键值分区状态
  2. 算子列表状态
  3. 算子联合列表状态
  4. 算子广播状态

键值分区状态

带有键值分区状态的算子在扩缩容时会根据新的任务数量对键值重新分区,但为了降低状态在不同任务之间迁移的必要成本,Flink不会对单独的键值实施再分配,而是会把所有键值分为不同的键值组(Key group)。每个键值组都包含了部分键值,Flink以此为单位把键值分配给不同任务。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R7NX8lNJ-1613653350079)(/Users/bytedance/Desktop/rBAADF-_dVyARBfaAAI4ZKnvSic298.png)]

算子列表状态

带有算子列表状态的算子在扩缩容时会对列表中的条目进行重新分配。理论上,所有并行算子任务的列表条目会被统一收集起来,随后均匀分配到更少或更多的任务之上。如果列表条目的数量小于算子新设置的并行度,部分任务在启动时的状态就可能为空。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NDdDgpiX-1613653350081)(/Users/bytedance/Desktop/rBAADF-_dV6AeeSFAAFN4Si0uh4879.png)]

算子联合列表状态

带有算子联合列表状态的算子会在扩缩容时把状态列表的全部条目广播到全部任务上,随后由任务自己决定哪些条目应该保留,哪些应该丢弃。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EoUw8gxR-1613653350082)(/Users/bytedance/Desktop/rBAADF-_dWGALj4yAAFgBFBZfxU566.png)]

算子广播状态

带有算子广播状态的算子在扩缩容时会把状态拷贝到全部新任务上,这样做的原因是广播状态能确保所有任务的状态相同。在缩容的情况下,由于状态经过复制不会丢失,我们可以简单的停掉多出的任务。

img

端到端的一致性保证

flink和kafka端到端状态一致性的保证?

内部(checkpoint,状态存盘) — source(故障,重置偏移量,重新消费数据) — sink (2PC)

  1. 内部 – 利用checkpoint机制,把状态存盘,发生故障的时候可以恢复,保证内部的状态一致性
  2. source – kafka consumer作为source,可以将偏移量保存下来,如果后续任务出现了故障,恢复的时候可以由连接器重置偏移量,重新消费数据,保证一致性
  3. sink-- kafka producer作为sink,采用两阶段提交sink,需要实现一个TwoPhaseCommitSinkFunction

PS:

什么是2PC(两阶段提交)?
就是两阶段提交(Two-Phase-Commit)

对于每个checkpoint, sink 任务会启动一个事务,并将接下来所有接收的数据添加到事务里

然后将这些数据写入外部sink系统,但不提交它们–这时只是"预提交")

当它收到checkpoint完成的通知时,它才正式提交事务,实现结果的真正写入

这种方式真正实现了exactly-once,它需要一个提供事 务支持的外部sink系统。Flink 提供了TwoPhaseCommitSinkFunction接口。

状态一致性:

AT-MOST-ONCE 最多一次

AT-LEAST-ONCE 至少一次

EXACTLY-ONCE 精确一次

如果下级存储不支持事务,Flink 怎么保证 exactly-once?
端到端的 exactly-once 对 sink 要求比较高,具体实现主要有幂等写入和事务性写入两种方式。幂等写入的场景依赖于业务逻辑,更常见的是用事务性写入。而事务性写入又有预写日志(WAL)和两阶段提交(2PC)两种方式。如果外部系统不支持事务,那么可以用预写日志的方式,把结果数据先当成状态保存,然后在收到 checkpoint 完成的通知时,一次性写入 sink 系统。

flink的window类型
  1. tumbling window(滚动窗口):窗口间的元素无重复

    一个翻滚窗口分配器的每个数据元分配给指定的窗口的窗口大小。
    翻滚窗具有固定的尺寸,不重叠。
    例如,如果指定大小为5分钟的翻滚窗口,则将评估当前窗口,
    并且每五分钟将启动一个新窗口

  2. sliding window(滑动窗口):窗口间的元素可能重复

    该滑动窗口分配器分配元件以固定长度的窗口。与翻滚窗口分配器类似,
    窗口大小由窗口大小参数配置。附加的窗口滑动参数控制滑动窗口的启动频率。
    因此,如果幻灯片小于窗口大小,则滑动窗口可以重叠。
    在这种情况下,数据元被分配给多个窗口。
    例如,您可以将大小为10分钟的窗口滑动5分钟。
    有了这个,你每隔5分钟就会得到一个窗口,其中包含过去10分钟内到达的事件

  3. session window(会话窗口)

    在会话窗口中按活动会话分配器组中的数据元。
    与翻滚窗口和滑动窗口相比,会话窗口不重叠并且没有固定的开始和结束时间
    相反,当会话窗口在一段时间内没有接收到数据元时,即当发生不活动的间隙时,会关闭会话窗口。
    会话窗口分配器可以配置静态会话间隙或 会话间隙提取器函数,该函数定义不活动时间段的长度。
    当此期限到期时,当前会话将关闭,后续数据元将分配给新的会话窗口。

  4. global window(全局窗口)

    一个全局性的窗口分配器分配使用相同的Keys相同的单个的所有数据元全局窗口。此窗口方案仅在您还指定自定义触发器时才有用。否则,将不执行任何计算,因为全局窗口没有我们可以处理聚合数据元的自然结束。

PS:window处出现数据倾斜的解决方案

window产生数据倾斜指的是数据在不同的窗口内堆积的数据量相差过多。本质上产生这种情况的原因是数据源头发送的数据量速度不同导致的。出现这种情况一般通过两种方式来解决:

  • 在数据进入窗口前做预聚合
  • 重新设计窗口聚合的key
flink的Time类型
  • Event-Time :事件时间是每个事件在其生产设备上发生的时间。此时间通常在进入Flink之前嵌入记录中,
    并且 可以从每个记录中提取该事件时间戳。
  • Ingestion-Time :摄取时间是事件进入Flink的时间。在源算子处,
    每个记录将源的当前时间作为时间戳,并且基于时间的 算子操作(如时间窗口)引用该时间戳。
  • Processing-Time : 处理时间是指执行相应算子操作的机器的系统时间。

PS:watermark 机制

什么是Watermark?

Watermark是Apache Flink为了处理EventTime 窗口计算提出的一种机制,本质上也是一种时间戳,由Apache Flink Source或者自定义的Watermark生成器按照需求Punctuated或者Periodic两种方式生成的一种系统Event,与普通数据流Event一样流转到对应的下游算子,接收到Watermark Event的算子以此不断调整自己管理的EventTime clock。

Watermark 本质是 Flink 中衡量 EventTime 进展的一个机制,主要用来处
理乱序数据。

怎么保证基于 event-time 的窗口在销毁的时候,已经处理完了所有的数据呢?
这就是 watermark 的功能所在。watermark 会携带一个单调递增的时间戳 t,
watermark(t) 表示所有时间戳不大于 t 的数据都已经到来了,未来不会再来,
因此可以放心的触发和销毁窗口了。

flink的序列化

Java本身自带的序列化和反序列化的功能,但是辅助信息占用空间比较大,在序列化对象时记录了过多的类信息。

Apache Flink摒弃了Java原生的序列化方法,以独特的方式处理数据类型和序列化,包含自己的类型描述符,泛型类型提取和类型序列化框架。

TypeInformation 是所有类型描述符的基类。它揭示了该类型的一些基本属性,并且可以生成序列化器。TypeInformation 支持以下几种类型:

  • BasicTypeInfo: 任意Java 基本类型或 String 类型
  • BasicArrayTypeInfo: 任意Java基本类型数组或 String 数组
  • WritableTypeInfo: 任意 Hadoop Writable 接口的实现类
  • TupleTypeInfo: 任意的 Flink Tuple 类型(支持Tuple1 to Tuple25)。Flink tuples 是固定长度固定类型的Java Tuple实现
  • CaseClassTypeInfo: 任意的 Scala CaseClass(包括 Scala tuples)
  • PojoTypeInfo: 任意的 POJO (Java or Scala),例如,Java对象的所有成员变量,要么是 public 修饰符定义,要么有 getter/setter 方法
  • GenericTypeInfo: 任意无法匹配之前几种类型的类

针对前六种类型数据集,Flink皆可以自动生成对应的TypeSerializer,能非常高效地对数据集进行序列化和反序列化。

flink的重启策略
  • 固定延迟重启策略(Fixed Delay Restart Strategy)
  • 故障率重启策略(Failure Rate Restart Strategy)
  • 没有重启策略(No Restart Strategy)
  • Fallback重启策略(Fallback Restart Strategy)

三、flink实战

参考资料:

flink入门实战(上)

flink入门实战(中)

flink入门实战(下)

四、flink调优

问题定位

“一压二查三指标,延迟吞吐是核心。时刻关注资源量,排查首先看GC”

一压是指背压,遇到问题先看背压的情况,二查就是指 checkpoint ,对齐数据的时间是否很长,state 是否很大,这些都是和系统吞吐密切相关的,三指标就是指 Flink UI 那块的一些展示,我们的主要关注点其实就是延迟和吞吐,系统资源,还有就是 GC logs。

  • 看反压:通常最后一个被压高的 subTask 的下游就是 job 的瓶颈之一。

  • 看 Checkpoint 时长:Checkpoint 时长能在一定程度影响 job 的整体吞吐。

  • 看核心指标:指标是对一个任务性能精准判断的依据,延迟指标和吞吐则是其中最为关键的指标。

  • 资源的使用率:提高资源的利用率是最终的目的。

常见的性能问题

图片

简单解释一下:

  1. 在关注背压的时候大家往往忽略了数据的序列化和反序列化过程所造成的性能问题。
  2. 一些数据结构,比如 HashMap 和 HashSet 这种 key 需要经过 hash 计算的数据结构,在数据量大的时候使用 keyby 进行操作, 造成的性能影响是非常大的。
  3. 数据倾斜是我们的经典问题,后面再进行展开。
  4. 如果我们的下游是 MySQL,HBase 这种,我们都会进行一个批处理的操作,就是让数据存储到一个 buffer 里面,在达到某些条件的时候再进行发送,这样做的目的就是减少和外部系统的交互,降低网络开销的成本。
  5. 频繁 GC ,无论是 CMS 也好,G1 也好,在进行 GC 的时候,都会停止整个作业的运行,GC 时间较长还会导致 JobManager 和 TaskManager 没有办法准时发送心跳,此时 JobManager 就会认为此 TaskManager 失联,它就会另外开启一个新的 TaskManager
  6. 窗口是一种可以把无限数据切割为有限数据块的手段。比如我们知道,使用滑动窗口的时候数据的重叠问题,size = 5min 虽然不属于大窗口的范畴,可是 step = 1s 代表1秒就要进行一次数据的处理,这样就会造成数据的重叠很高,数据量很大的问题。
作业调优

参考资料

谈谈三种海量数据实时去重方案(w/ Flink)

7种垃圾回收器介绍

JVM垃圾回收器介绍

Flink作业问题分析和调优实践

数据去重

1、布隆过滤器

2、内嵌RocksDB状态后端去重

3、引入外部K-V存储去重

PS:不建议用Set,Map等数据结构结合flink的state实现去重,这些去重方案会随着数据量不断增大,从而导致性能的急剧下降,比如 hash 冲突带来的写入性能问题,内存过大导致的 GC 问题,TaskManger 的失联问题。

数据倾斜

图片

倾斜-源头

数据源的消费不均匀:调整并发度

对于数据源消费不均匀,比如kafka数据源,常是通过调整数据源算子的并发度实现

原则:通常情况下是source的并发度和kafka的分区数一致或是kafka分区数是source并发度的正整数倍

第一种场景是当我们的并发度设置的比分区数要低时,就会造成上面所说的消费不均匀的情况。

图片

第二种提到的就是 key 分布不均匀的情况,可以通过添加随机前缀打散它们的分布,使得数据不会集中在几个 Task 中。

图片

在每个节点本地对相同的 key 进行一次聚合操作,类似于 MapReduce 中的本地 combiner。map-side 预聚合之后,每个节点本地就只会有一条相同的 key,因为多条相同的 key 都被聚合起来了。其他节点在拉取所有节点上的相同 key 时,就会大大减少需要拉取的数据数量,从而也就减少了磁盘 IO 以及网络传输开销。

内存调优

调优的方面主要是针对 非堆内存 Network buffer ,manager pool 和堆内存的调优,这些基本都是通过参数来进行控制的。

图片

这些参数我们都需要结合自身的情况去进行调整,这里只给出一些建议。而且对于 ManagerBuffer 来说,Flink 的流式作业现在并没有过多使用到这部分的内存,所以我们都会设置得比较小,不超过0.3。

图片

堆内存的调优是关于 JVM 方面的,主要就是将默认使用的垃圾回收器改为 G1 ,因为默认使用的 Parallel Scavenge 对于老年代的 GC 存在一个串行化的问题,它的 Full GC 耗时较长,下面是关于 G1 的一些介绍,网上资料也非常多,这里就不展开说明了。

图片

图片

图片
Network buffer ,manager pool 和堆内存的调优,这些基本都是通过参数来进行控制的。

[外链图片转存中...(img-6kPMWcJx-1629862468029)]

这些参数我们都需要结合自身的情况去进行调整,这里只给出一些建议。而且对于 ManagerBuffer 来说,Flink 的流式作业现在并没有过多使用到这部分的内存,所以我们都会设置得比较小,不超过0.3。

[外链图片转存中...(img-lBHiawY2-1629862468030)]

堆内存的调优是关于 JVM 方面的,主要就是将默认使用的垃圾回收器改为 G1 ,因为默认使用的 Parallel Scavenge 对于老年代的 GC 存在一个串行化的问题,它的 Full GC 耗时较长,下面是关于 G1 的一些介绍,网上资料也非常多,这里就不展开说明了。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值