Flink学习笔记

Flink

常见问题:分布式快照,savepoint,端到端一致性,背压。

分布式快照:定期生成checkpoint barrier将算子划分,同一barrier内的算子会进入同一个checkpoint内,保存这段的state/operate状态。分布式快照可以将同一时间点Task/Operator的状态数据全局统一快照处理。Flink会在输入的数据集上间隔性地生成checkpoint barrier,通过栅栏(barrier)将间隔时间段内的数据划分到相应的checkpoint中。当应用出现异常时,Operator就能够从上一次快照中恢复所有算子之前的状态,从而保证数据的一致性。
savepoint:是一种特殊的分布式快照,是手动将快照保存在HDFS上,主要用于系统维修停机后,恢复系统。Savepoints是用户以手工命令的方式触发Checkpoint,并将结果持久化到指定的存储路径中,其主要目的是帮助用户在升级和维护集群过程中保存系统中的状态数据,避免因为停机运维或者升级应用等正常终止应用的操作而导致系统无法恢复到原有的计算状态的情况。
端到端的一致性:只要靠两阶段提交,第一阶段将状态保存在临时文件中,第二节点将临时文件保存下载。两阶段提交+状态保存。
背压:一端的数据处理速度远小于数据的接收速度。导致数据的积压。较慢的接受者会降低发送者的发送速率。

执行流程

client向hdfs上传jar包和配置,向RM申请启动AM,AM启动后,加载jar包和配置环境,启动JM,AM向RM申请TM资源,RM返回可用的资源列表,AM启动对应的NM加载任务启动TM。TaskManager启动后向JobManager发送心跳包,并等待JobManager向其分配任务。

Flink编程模型

数据类型:有界数据集、无界数据集、统一数据处理。(一段时间的无界数据集就是有界数据,有界数据的流式处理就是无界数据)
编程接口:FLink SQL、Table API、DataStream/DataSet API、Stateful Stream Process API。
程序结构:Flink执行环境、创建和加载数据集、数据集指定转换逻辑、指定计算结果输出位置、调用execute方法触发程序执行。

DataStream

输入:文件数据源、Socket数据源、集合数据源、外部数据源

数据转换

Sing-dataStream:

  • Map[DataStream->DataStream]
  • FlatMap[DataStream->DataStream]
  • Filter[DataStream->DataStream]
  • KeyBy[DataStream->KeyedStream]
  • Reduce[KeyedStream->DataStream]
  • Aggregations[KeyedStream->DataStream]

Multi-DataStream:

  • Union[DataStream->DataStream]
  • Connect,CoMap,CoFlatMap[DataStream->DataStream]
  • Split[DataStream->SplitStream]
  • Select[SplitStream->DataStream]
  • Iterate[DataStream->Iterative->DataStream]

物理分区:(随机分区、平衡分区、按比例分区)

  • shuffle[DataStream->DataStream]
  • rebalance[DataStream->DataStream]
  • rescale[DataStream->DataStream]
  • broadcase[DataStream->DataStream]
  • 继承Partitioner自定义分区[DataStream->DataStream]

Watermark

时间时间、接入时间、处理时间
顺序事件的Watermarks:水位线和事件时间一致。
乱序事件的Watermarks:事件时间-时间间隔=Watermark。
并行数据的Watermarks:Flink会选择最小的水位线来更新。

  1. 在Source Function中指定timestamps和watermark:重写run方法、收集数据和指定事件时间、指定watermark

  2. 通过Timestamp Assigner指定timestamps和watermark:

  • assignAscendingTimestamps
  • assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(10))
    3 自定义:
  • Periodic Watermark:固定时间间隔
  • Punctuated Watermarks:根据某些特殊条件生成Punctuated Watermarks

Window窗口计算

创建:

  1. 对于Keyed类型:window()、根据不同的key并行计算,相同key放到同一个分区里。
  2. 对于Non-Keyed类型:windowAll()、全局统计,Global Windows

窗口类型:

  1. 基于时间的窗口:使用TimeWindow类来获取窗口的起始时间和终止时间。
  2. 基于数量的窗口:根据固定的数量定义窗口的大小。

基于时间窗口的有:

  1. 滚动窗口(Tumbling Windows):根据时间切分,窗口和窗口之间的元素互不重叠。
    • EventTime:TumblingEventTimeWindows.of()
    • ProcessTime:TumblingProcessingTimeWindows.of()
  2. 滑动窗口(Sliding Windows):在滚动窗口的基础上增加了窗口滑动时间,允许窗口数据发生重叠。滑动窗口大小和窗口大小一致时,就是滚动窗口。
    • EventTime:SlidingEventTimeWindows.of()
    • ProcessTime:SlidingProcessingTimeWindows.of()
  3. 会话窗口(Session Windows):窗口触发条件是Session Gap,在规定时间内如果没有数据活跃接入,则认为窗口结束,然后触发窗口计算。每进入一个数据就创建一个窗口。
    • EventTime:EventTimeSessionWindows.withGap()
    • ProcessTime:ProcessTimeSessionWindows.withGap()
  4. 全局窗口(Global Windows):将所有相同key的数据分配到单个窗口中计算结果,窗口没有起始和结束时间,窗口借助Trigger来触发计算。需要指定触发器,同时还需要指定相应的数据清理机制。
    • GlobalWindows.create()

Windows Function

增量聚合函数:性能高、内存占用少

  • ReduceFunction:将两个相同类型的数据聚合
  • AggregateFunction:聚合,更有通用性
  • FoldFunction:将窗口中的输入元素与外部的元素合并
    全量窗口函数:性能弱
  • ProcessWindowFunction:更加灵活的聚合函数。可以在reduce中先定义ReduceFunction函数,然后定义ProcessWindowFunction函数。ProcessWindowFunction也有状态操作。

RichFunction也有状态操作。

延迟数据处理:

val tag = Output[T]("late-data") // 标记late-data
...
.allowedLateness(<time>)	// 开启延迟处理
.sideOutputLateData(tag)	// 对迟到数据进行标记
...

val late = result.getSideOutput(tag)	// 获取迟到数据

Windows多流合并:
join之后的窗口关联,join为inner join。有四种多流合并的关联窗口,滚动窗口关联、滑动窗口关联、会话窗口关联、间隔关联。
滚动窗口关联:相同Key的两个DataStream数据集中的元素进行关联
滑动窗口关联:
会话窗口关联:
间隔关联:不依赖窗口划分,而是通过DataStream元素的时间加上或减去指定Interval作为关联窗口。关联的两个流都需要先转换成KeyStream,然后使用intervalJoin关联。

b.keyBy(_._1).intervalJoin(a.keyBy(_._1)).between(时间1,时间2) // 设置时间上下界

Slot资源组

如果所有input操作均来自相同的slot group,则该操作符会继承前面操作符的slot group,然后再同一个Slot中进行处理,如果不是则当前的操作符会选择默认的slot group。

状态管理和容错

有状态计算

状态类型:

  1. Keyed State
  2. Operator State(Non-key State)
  • 他们都具有两种形式:
    • Managed State托管状态
    • Raw State原生状态

托管状态:
Managed Keyed State:
- ValueState
- ListState
- ReducingState
- AggregatingState
- MapState
State的生命周期:

val stateConfig = StateTtlConfig.newBuilder(Time.seconds(10))
.setUpdateType(StateTtlConfig.UpdateType.OnCreateAndWrite)
.setStateVisibility(StateTtlConfig.StateVisibility.NeverReturnExpired)
.build

val stateDescriptor = new ValueStateDescriptor[String]("valueState",classOf[Long])
stateDescriptor.enableTimeToLive(stateTtlConfig)

StateTtlConfig.UpdateType.OnCreateAndWrite仅在创建和写入时更新TTL
StateTtlConfig.UpdateType.OnReadAndWrite所有读写操作都更新TTL
==只有被写入或者读取时才会更新,如果一致不被使用,就不会清理。==可设置以下参数。

StateTtlConfig.StateVisibility.NeverReturnExpired:状态数据过期就不会返回
StateTtlConfig.StateVisibility.ReturnExpiredIfNotCleanedUp:状态数据即使过期但没有被清理依然返回。

Managed Operator State:
通过CheckpointedFunction接口操作Opetator State
通过ListCheckpointed接口定义Opetator State

Checkpoints和Savepoints

Checkpoints机制:

  1. Checkpoints开启和时间间隔设定
  2. exactly-once和at-least-once语义选择
    • exactly-once可以保证端到端的数据一致性,这种情况比较适合数据要求比较高的,不允许丢失或者数据重复。
    • at-least-once更适合时延和吞吐量要求非常高但对数据的一致性要求不高的场景。
  3. Checkpoints超时时间
  4. 检查点之间最小时间间隔
  5. 最大并行执行的检查点数量
  6. 外部检查点
  7. failOnCheckpointingErrors

Savepoints机制:
手工触发Checkpoints的机制,并将结果持久化到指定存储路径。使用指定的Opetator ID可以恢复代码逻辑变化的情况。
使用命令
触发Savepoints
取消任务并触发Savepoints
通过Savepoints中恢复任务
释放Savepoints数据

状态管理器

MemoryStateBackend
FsStateBackend
RocksDBStateBackend

Querable State

DataSet

输入:文件类数据、集合类数据、通用数据接口、第三方文件系统

数据转换

数据处理:map、flatMap、mapPartition、filter
聚合操作:reduce、reduceGroup、Aggregate、distinct
多表关联:join、outerjoin、cogroup、cross
聚合操作:union、rebalance、hashPartition、rangePartition、sortPartition
排序操作:first、minby/maxby

迭代计算:全量迭代、增量迭代

广播变量与分布式缓存

广播变量:目的是对小数据集采用网络传输的方式,在每个并行计算的节点的实例内存中存储一份该数据集。
广播变量:withBroadcastSet(broadcaseData,“broadcaseSetName”)
分布式缓存:env.registerCachedFile(“hdfs:///path/file”,“hdfsFile”)/(“file:///path/file”,“localFile”,true)

语义注解

转发字段(Forwarded Fileds):指定字段不进行修改。
非转发字段(Non-Forwarded Fileds):指定不转发的字段。必须参与函数计算并产生新的结果,输入输出类型相同。
读取字段(Read Fileds):指定的字段全部参与计算。

Table

内部catalog:数据库和表的元数据信息存放在Flink CataLog内部目录结构中。
注册:
1.内部Table注册:tableEnv.registerTable(“projectedTable”,projTable),第一个参数是注册CataLog的表名,第二个参数是对应的Table对象。
2.TableSource注册:可以将外部的数据源直接注册成Table数据结构。tableEnv.registerTableSource(“CsvTable”,csvSource)
3.tableSink注册:将数据写到外部存储中,在TableAPI中有对应的Sink模块TableSink。
外部catalog:需要用户自定义实现。
3.DataStream、DataSet与Table相互转换
注册:
tableEnv.registerDataStream(“table1”,stream)
tableEnv.registerDataSet(“table1”,dataset)
转换:
tableEnv.fromDataStream(stream,‘field1’,‘field2’)
tableEnv.fromDataSet(dataSet,‘field1’,‘field2’)

table转DataStream:
Append Model:仅将Insert更新变化的数据写入DataStream中。tableEnv.toAppendStream(table)
Retract Model:通过一个标记判断是Insert操作更新还是Delete更新的数据。tableEnv.toRetractStream(table)

table转DataStream:tableEnv.toDataSet(table)
字段映射:位置映射和名称映射。

Flink Table API:
.scan:查询已经在Catalog中的表
.select:查询操作
.filter:条件过滤,三个等号。
.where:条件过滤
.window:滚动、滑动、会话、Over
多表关联
.join:
.leftOuterJoin:
.rightOuterJoin:
.FullOuterJoin:
集合操作
.union:
.unionall:
.intersect:
.intersectAll:
.minus:
.minusAll:
.in:
排序操作
orderBy:

使用:
sqlQuery:执行table查询并处理成新的Table
sqlUpdate:将结果写入注册表

CEP(复杂时间处理)

一个或多个由简单事件构成的事件流通过一定的规则匹配,然后输出用户想得到的数据,满足规则的复杂事件。
个体Pattern:通过begin定义。
.time()指定循环次数
.optional:要么不触发,要么触发指定次数。
.greedy:尽可能多的触发
.oneOrMore:触发一次或者多次
.timeOrMore:指定最少触发次数

模式序列:

  1. 严格邻近:所有事件都需要按照顺序满足模式.next
  2. 宽松邻近:会忽略没有成功的模式.followedBy
  3. 非确定宽松邻近:可以忽略已经匹配的条件.followedByAny

反压(Backpressure)

反压是流式系统非常重要的机制,主要作用是当系统中下游算子的处理速度下降,导致数据处理速率低于数据接入速率时,通过反向背压的方式让数据接入的速率下降,从而避免大量数据积压在Flink系统中。

优化

checkpoint优化:

  1. 最小时间间隔:
  2. 状态容量评估:
  3. 异步Snapshot
  4. 状态数据压缩

内存优化:
jobManager:堆大小
TaskManager:堆大小、内存溢出是否停止、内存大小、堆外内存、slot数量。

Flink CDC

CDC是(Change Data Capture 变更数据的获取。

核心思想:捕获数据库的变动(增删改),将这些变更按顺序记录下来,写到消息中间件中(例如kafka)以供其他服务订阅消费。

Flink可以直接从 MySQL、PostgreSQL 等数据库直接读取全量数据和增量变更数据

你可能感兴趣的:(flink,学习,java)