flink

flink

1、概述

flink是一个计算框架和分布式处理引擎,用于对有界流和无界流进行有状态计算

  • dataset API

    • 对静态数据进行批处理操作,将静态数据抽象成分布式的数据集,用户可以方便地使用Flink提供的各种操作符对分布式数据集进行处理,支持Java、Scala和Python1
  • datastream api

    • 对数据流进行流处理操作,将流式的数据抽象成分布式的数据流,用户可以方便地对分布式数据流进行各种操作,支持Java和Scala
  • table api

    • 对结构化数据进行查询操作,将结构化数据抽象成关系表,并通过类SQL的DSL对关系表进行各种查询操作,支持Java和Scala

2、优点

1、支持高吞吐、低延迟、高性能的流处理

2、支持带有事件时间的窗口(Window)操作

3、支持有状态计算的Exactly-once语义

4、支持高度灵活的窗口(Window)操作,支持基于time、count、session,以及data-driven的窗口操作

  • 八种窗口

    • 时间滑动滚动
    • 会话滑动滚动
    • count滑动滚动

5、支持具有反压功能的持续流模型

6、支持基于轻量级分布式快照(Snapshot)实现的容错

7、一个运行时同时支持Batch on Streaming处理和Streaming处理

8、Flink在JVM内部实现了自己的内存管理,避免了出现oom

9、支持迭代计算

10、支持程序自动优化:避免特定情况下Shuffle、排序等昂贵操作,中间结果有必要进行缓存

3、系统架构

JobManager

  • master进程,负责job的管理和资源调度,包括任务调度、检查点管理、失败恢复等,也支持HA,多个master进程,一个作为leader,其余的是standby,当leader失败时,会选出一个standby的master作为新的leader(通过zookeeper实现leader选举)。

    • actor系统

      Flink内部使用Akka模型作为JobManager和TaskManager之间的通信机制。
      Actor系统是个容器,包含许多不同的Actor,这些Actor扮演者不同的角色。Actor系统提供类似于调度、配置、日志等服务,同时包含了所有actors初始化时的线程池。
      所有的Actors存在着层级的关系。新加入的Actor会被分配一个父类的Actor。Actors之间的通信采用一个消息系统,每个Actor都有一个“邮箱”,用于读取消息。如果Actors是本地的,则消息在共享内存中共享;如果Actors是远程的,则消息通过RPC远程调用。

      每个父类的Actor都负责监控其子类Actor,当子类Actor出现错误时,自己先尝试重启并修复错误;如果子类Actor不能修复,则将问题升级并由父类Actor处理。

      在Flink中,actor是一个有状态和行为的容器。Actor的线程持续的处理从“邮箱”中接收到的消息。Actor中的状态和行为则由收到的消息决定。

    • 调度器

      Flink中的Executors被定义为task slots(线程槽位)。每个Task Manager需要管理一个或多个task slots。

      Flink通过SlotSharingGroup和CoLocationGroup来决定哪些task需要被共享,哪些task需要被单独的slot使用。

    • 检查点

      Flink的检查点机制是保证其一致性容错功能的骨架。它持续的为分布式的数据流和有状态的operator生成一致性的快照。其改良自Chandy-Lamport算法,叫做ABS(轻量级异步Barrier快照),具体参见论文:
      Lightweight Asynchronous Snapshots for Distributed Dataflows

      Flink的容错机制持续的构建轻量级的分布式快照,因此负载非常低。通常这些有状态的快照都被放在HDFS中存储(state backend)。程序一旦失败,Flink将停止executor并从最近的完成了的检查点开始恢复(依赖可重发的数据源+快照)。
      Barrier作为一种Event,是Flink快照中最主要的元素。它会随着data record一起被注入到流数据中,而且不会超越data record。每个barrier都有一个唯一的ID,将data record分到不同的检查点的范围中
      每个快照中的状态都会报告给Job Manager的检查点协调器;快照发生时,flink会在某些有状态的operator上对data record进行对齐操作(alignment),目的是避免失败恢复时重复消费数据。这个过程也是exactly once的保证。通常对齐操作的时间仅是毫秒级的。但是对于某些极端的应用,在每个operator上产生的毫秒级延迟也不能允许的话,则可以选择降级到at least once,即跳过对齐操作,当失败恢复时可能发生重复消费数据的情况。Flink默认采用exactly once意义的处理。

TaskManager

  • Task Managers是具体执行tasks的worker节点,执行发生在一个JVM中的一个或多个线程中。Task的并行度是由运行在Task Manager中的task slots的数量决定。如果一个Task Manager有4个slots,那么JVM的内存将分配给每个task slot 25%的内存。一个Task slot中可以运行1个或多个线程,同一个slot中的线程又可以共享相同的JVM。在相同的JVM中的tasks,会共享TCP连接和心跳消息

client

  • Job Client并不是Flink程序执行中的内部组件,而是程序执行的入口。Job Client负责接收用户提交的程序,并创建一个data flow,然后将生成的data flow提交给Job Manager。一旦执行完成,Job Client将返回给用户结果。

    • Data flow就是执行计划,当用户将程序提交时,Job Client负责接收此程序,并根据operator生成一个data flow。默认情况下,Flink的data flow都是分布式并行处理的,对于数据的并行处理,flink将operators和数据流进行partition。Operator partitions叫做sub-tasks。数据流又可以分为一对一的传输与重分布的情况。

4、Flink 原理与实现:数据流上的类型和操作,Datastream为主

DataStream 是 Flink 流处理 API 中最核心的数据结构。它代表了一个运行在多个分区上的并行流。一个 DataStream 可以从 StreamExecutionEnvironment 通过env.addSource(SourceFunction) 获得。

DataStream 上的转换操作都是逐条的,比如 map(),flatMap(),filter()。DataStream 也可以执行 rebalance(再平衡,用来减轻数据倾斜)和 broadcaseted(广播)等分区转换。

val stream: DataStream[MyType] = env.addSource(new FlinkKafkaConsumer08String)
val str1: DataStream[(String, MyType)] = stream.flatMap { … }
val str2: DataStream[(String, MyType)] = stream.rebalance()
val str3: DataStream[AnotherType] = stream.map { … }

上述 DataStream 上的转换在运行时会转换成如下的执行图:


如上图的执行图所示,DataStream 各个算子会并行运行,算子之间是数据流分区。如 Source 的第一个并行实例(S1)和 flatMap() 的第一个并行实例(m1)之间就是一个数据流分区。而在 flatMap() 和 map() 之间由于加了 rebalance(),它们之间的数据流分区就有3个子分区(m1的数据流向3个map()实例)。这与 Apache Kafka 是很类似的,把流想象成 Kafka Topic,而一个流分区就表示一个 Topic Partition,流的目标并行算子实例就是 Kafka Consumers。

http://wuchong.me/blog/2016/05/20/flink-internals-streams-and-operations-on-streams

5、实时计算

资源申请

  • 粗粒度资源申请
  • 和spark一样

任务调度

  • spark streaming每一个batch做一次任务调度
  • flink 只做一次任务调度,在启动开的时候,task只部署一次
  • 这是flink比spark快的重要原因

6、程序结构

source

  • 整个stream的入口

    • 1、基于本地集合

    • 2、基于文件

    • 3、读取socket

    • 4、自定义source

      • 实现sourcefunction接口

        • SourceFunction 单线程
        • richsourcefunction 多了open 方法,可以在open 方法中打开链接,使用flink的状态
        • ParallelSourceFunction 并行source
        • RichParallelSourceFunction
      • 读取kafka中的数据

        • flinkkafkaconsumer
      • 自定义读取mysql

      • 自定义读取hbase

transformation

  • map
  • filter
  • flatMap
  • keyBy
  • sum
  • max maxBy min MinBy
  • window
  • join (难点)
  • union

sink

  • 1、打印

  • 2、写入文件

  • 3、写入socket

  • 4、自定义,实现sinkFunction 或者rickSinkFunction

    • sink到kafka

      • TwoPhaseCommitSinkFunction 两步提交的sink

7、集群搭建

独立集群

  • 和hadoop没有关系,独立搭建一个flink集群,

fink on yarn

  • yarn -session

    • 在yarn 上启动一个jobmanager 所有job共享一个jobmanager
  • per-job cluster

    • 直接提交任务到yarn集群,每一个job独享一个jobmanager

提交方式

  • 1、通过网页提交
  • 2、通过命令好提交 flink run
  • 3、rpc

8、时间

1、事件时间

  • 数据中必须自带时间才可以使用

  • 数据乱序问题

    • 通过将水位线后移解决乱序问题

2、接收时间

3、处理时间 默认

9、窗口

时间窗口

  • 事件时间的滚动窗口
  • 事件时间的滑动窗口
  • 处理时间的滚动窗口
  • 处理时间的滑动窗口

会话窗口

  • 每隔一段时间没有数据进行计算
  • 事件时间和处理时间

统计窗口

  • 滚动和滑动

10、状态

flink可以将程序中间计算结果以状态的形式保存起来 (单词的数量,消费偏移量)

状态会随着checkpoint保存到hdfs中,保证数据不丢失

分类

  • valueState
  • listState
  • ReduingState
  • MapState

针对每一个key都会保存一个状态

11、checkpoint

分布式快照,将状态持久化到hdfs中

流程

  • 1、jobmanager定时发送checkpoint, 向sourcetask发送触发器
  • 2、sourcetask会在数据中安插标记,同时自己进行checkpiint 将数据保存到hdfs中
  • 3、下游算子收到标记后异步进行快照
  • 4、当所有的算子处理完同一个标记后代表一次checkpoint成功

状态后端

  • MemoryStateBackend

    • 将状态保存到jobmanager的内存中
  • FsStateBackend

    • 首先将状态保存在taskmamager的内存中,
    • 当进行checkpoint的时候将状态保存到hdfs中
  • RocksDBStateBackend

    • 首先将状态保存在taskmanager本地的RocksDS中
    • 当进行checkpoint的时候将状态保存到hdfs中
    • 可以支持增量快照

12、table api

基于flink runtime层构建的sql 层 ,将批处理和流处理统一,将批处理看作是流处理的特例

读取数据处理数据都可以通过sql 来实现

动态表

  • flink 实时数据流 在flink 的代码中抽象成一张表

  • 基于动态表可以进行连续查询(查询不结束,一致会产生结果)

  • 根据查询的不同又分为两种查询结果

    • append 流

      • 可以写入任何接收器中
    • 更新 流

      • 可以写入mysql
      • 如果想要写入kafka 需要使用阿里云提供的 changelog-json 在flink 1.13之后可以直接写入kafka

flinK cdc

  • mysql -cdc

    • 先进行批量读取
    • 再实时监控binlog日志,实时读取数据
    • 一般用在维表关联

表关联

  • 维表关联

    • 维表再mysql中使用jdbc读取mysql数据进行关联

      • 如果维表数据更新了,再flink中没办法发现
    • 维表再mysql中,使用mysql-cdc 读取数据,可以实时发现数据更新

  • Regular Joins (全局管理)

    • 需要将两个表所有的数据保存再flink的状态中
    • 当程序运行很久之后状态会很大,checkpoint的时间会很长
  • Interval Joins

    • 指定一个时间范围进行关联
    • a 表关联b 表一段时间内的数据 ,状态中不需要保存所有数据

sql-client

  • 再sql客户端中可以直接写sql, 可以创建表,查询数据
  • 默认元数据是放在内存中的,可以整合hive将元数据保存到hive中
  • flink 可以直接读取hive中的表进行查询
  • hive不可以使用flink创建表动态表

13、Exactly once

1、消息生产者

  • 1、acks

    • acks=0 生产者发送出去就代表成功
    • acks=1 当分区的leader接收到数据并保存到磁盘上代表成功
    • acks=all 当分区的所有副本都保存成功才代表成功
  • 2、事务

    • 多次发送数据要么都成功要么都失败
  • 3、幂等性

    • 如果在发送数据的时候超时重新发送不会出现重复数据

2、flink消费端

  • 通过flink的状态和checkpoint保存消费的偏移量以及计算的中结果,保证数据不重复

3、flink生产端

  • 1、依赖flink两步提交的sink
  • 2、依赖kafka事务支持
  • 在checkpoint之前开启事务
  • 在checkpoint成功之后提交i事务
  • 会导致数据输出延迟
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值