这是我参与「第四届青训营 」笔记创作活动的第4天。
本节课程主要分为 4 个方面:
1.数据流和动态表 如何在数据流上执行SQL语句,说明流式处理中状态的概念
2.Exactly-Once 和Checkpoint 当故障发生时,Flink自身如何从故障中恢复,保证数据消费的不丢不重
3.端到端Exactly-Once实现 Flink本身的Checkpiont机制如何和外部存储结合,实现端到端的不丢不重语义
4.Flink案例讲解 介绍Flink如何解决和实现账单计费服务
课程预习
动态表: 和动态表对应的是静态表——常规的数据库中的表或批处理中的表等,其在查询时数据不再变化。动态表是随时间变化的,即使是在查询的时候。怎么理解了?流上的数据是源源不断的,一条数据的到来会触发一次查询,这次查询在执行时还有下一条数据到来,对表本身数据是在变化的。
对动态表的查询是连续的,即连续查询(Continuous Query)。实质上, 动态表上的连续查询与定义物理视图(Materialized View)的查询很相似。物理视图定义为SQL查询,就像常规的虚拟视图一样,不同的是物理视图会缓存查询结果,这样在访问时不需要重新计算,而缓存带来的挑战是有可能提供过时的结果,Eager View Maintenance则是用于及时跟新物理视图的技术,这里就不展开了。
用一句话概括是:流被转换为动态表,对动态表的连续查询生成新的动态表(结果表),然后结果表被转换为流。
2.流上定义表
2.1 定义表 为了在流上使用关系型查询,需要将流转换成表。下面的分析过程均采用官网(Ref[2])中的例子进行说明。
1)点击事件流的schema如下:
[
user: VARCHAR, // the name of the user
cTime: TIMESTAMP, // the time when the URL was accessed
url: VARCHAR // the URL that was accessed by the user
]
2)从概念上来说,流上的每天记录都是动态表进行INSERT修改。从本质上讲,是从一个INSERT-Only(仅插入)的ChangeLog流上构建一个表。点击事件流上构建表如下图所示,且随着更多点击流记录的插入,生成的表不断增长:
Note:定义在流上的表在内部是没有实现的。
连续查询
连续查询不会中止,会根据输入表来更新结果表,下面介绍两种查询的例子。
1)简单的GROUP-BY Count聚合查询
下图中,左边是输入表click,是随着时间updata增加的,右边是查询的结果表。开始clicks表中只有一条数据[Mary, ./home]时其结果表是表-1,当clicks表中新增一条数据[Bob, ./cart]时,其结果表是表-2,依次下推。每一条新数据的到来会对之前表行进update或INSERT操作,SQL语句就会根据现有数据更新的结果表。
2)带有窗口(window)的聚合查询
窗口的时间间隔是1个小时,窗口-1对应的时表-1,窗口-2对应的时表-2,依次类推。和第一种查询不一样的是,每一张时表只是统计对应窗口的数据,之前窗口的数据对其没有影响,对不同窗口的查询结果是以追加的形式写入result表中的。
2.3 Update和Append查询
2.2中的两种例子分别对应的两种查询方式,
1)例子1对应着Update查询,这种方式需要更新之前已经发出的结果,包括INSERT和UPDATE两种改变。改变之前已经发出的结果意味着,这种查询需要维护更多的状态(state)数据;
2)例子2对应着Append查询,这种方式查询的结果都是以追加的形式加入到result表中,仅包含INSERT操作。这种方式生成的表和update生成的表转换成流的方式不一样(见下文)。
3、Table到流的转换
可以通过INSERT、UPDATE、DELETE像修改常规表一样去改变动态表。将动态表转换为流或将其写入外部系统时,需要对这些更改进行encode。 Flink的Table API和SQL支持三种encode改变动态表的方法:
1)Append-only Stream(仅追加流):仅通过INSERT操作得到的动态表可以发射插入行来转换为流(联想2.2中例2),这种方式转换的流中数据都是片段性的,一个片段代表一个窗口;
2)Retract Stream(回溯流):restract stream有两种消息:添加(add)消息和回溯(retract)消息。将动态表转换为回溯(retract)流,通过将INSERT更改encode为添加消息,将DELETE更改encode为回溯消息,将UPDATE更改endcode为更新(上一个)行的回溯消息以及添加消息更新新的行 。 下图显示了动态表到回溯流的转换。
流上每条消息都有一个标识位,其中+标识INSERT操作,-标识DELETE操作。在clicks表中第一、二行消息[Mary, ./home]和[Bob, ./cat]被转换为流中1第、2条消息,当clicks表中第三行[Mary, ./prod?id=1]转换时,会先将已发出的第1条信息标记为DELETE告诉下游,然后第4条消息重新插入user为Mary的消息,依次类推,这样可以保证输出结果的正确性。
3)Upsert Stream(上插流):Upsert流包括upsert消息和删除消息。 动态表要转换为upsert流需要(可能是复合的)唯一键。 通过将INSERT和UPDATE 操作encode为upsert消息,并将DELETE更改encode为删除消息,可以是具有唯一键的动态表转换为流。 流运算需要知道唯一键属性才能正确应用消息。 与回溯流的主要区别在于UPDATE使用单个消息((主键))进行编码,因此更有效。
ref:nightlies.apache.org/flink/flink…
正文
1.数据流和动态表
Flink处理的是实时流
传统SQL和流处理
概述 数据流和动态表转换
我们了解到Flink是处理数据流的,所以sql请求以流的形式不断输入到Flink中,由Flink将其使用ETL转化为适合处理的数据形式,JM将这些数据进行逻辑计划处理,将这些数据转化为DAG,分配到TM中,TM将这些算子进行物理计划变为物理计划图,之后执行。
数据流转化为动态表:
连续查询:
例子:
统计某一个窗口在一小时内的点击次数
两个操作的区别:
Retract消息的产生
当我们要接收到同一个字段的有一条信息,需要在统计信息上加一时,我们需要先回溯,发送一条回溯消息,之后在更新统计消息,这样就告诉下游(之前的算子结点)我更新了。
状态
我们需要跟踪获得的动态表的数据的统计信息,以了解这些数据的状态。
不同数据处理保证的语义
2.Exactly-Once 和Checkpoint
Exactly-Once如何在Flink中实现,checkpoint起的作用
状态快照与恢复
3个算子:source:读数据流,sum_even:偶数累加器,sum_odd:奇数累加器
想要在某时刻做备份,要保存所有算子的状态在一个存储中,如图中,从1开始在输入5是进行备份,存储在当前的所有算子的状态,存入存储中。继续读取加入在处理7时,偶数累加器出错了,我们需要恢复,我们可以恢复到输入是5的状态,从5之后开始执行。
如何制造快照的时间点
状态回复的时间点:需要等待所有处理逻辑消费完成source保留状态以及之前的数据。
该方法需要在保存状态时停止输入流的操作
Chandy-Lamport算法
JM向输入流源下发checkpoint Barrier,通知状态制作开始
各个source保存自己的状态后,向素由链接的下游 继续发送Checkpoint Barrier,同时通知JM自己状态已经制作完成。
算子会等待所有上游的到达后才开始快照的制作。 已经制作完的的上游算房子会继续处理数据,并不会背下来有算子制作快债的过程阻塞。
所有算子都告知JM状态制作完成了,
Checkpoint对作业性能的影响
端到端 Exactly-Once 实现
恢复到一个历史结点,当我从历史结点到发生故障节点,处理的数据sink是往下游发数据的,这部分数据是重复往下发,比如该部分数据是扣费操作,那就重复扣费了。
两阶段提交协议
将这个协议应用到sink中做到端到端的Exaclty-once
- Coordinator:协作者,同步和协调所有节点处理逻辑的中心节点
- Participant:参与者,被中心节点调度的其他执行处理逻辑的业务节点
预提交阶段:
提交阶段(一):
提交阶段(二):
两阶段提交协议在 Flink 中的应用
Flink中的2PC Sink
- Flink 中协作者和参与者的角色分配
- 协作者(JobManager)发起阶段一提交
- 各算子 Checkpoint 的制作
- 提交阶段及 Checkpoint 的制作完成
案例分析
账单计算服务
从Kafka中读取账单消息,进行处理后写入Mysql中
账单计算服务:Flink解决方案
这是场景的意义在于我们在处理类似场景是具有这些特征:1)我们希望在处理数据时可以恢复到处理该数据流的某而过历史结点,所以提出了状态备份与恢复;2)在恢复状态后,我们希望能保证数据流处理只处理一次,在恢复到历史结点操作前,某些处理过一次的算子不再重复处理。
总结
1.该节课我们学习了Flink中数据流与动态表的转化,以及数据流在Flink框架中的执行过程以及数据流的几种常用操作,回溯,连续查询。
2.学习了不同数据处理保证的语义;学习了状态快照的实现与Chandy-Lamport算法来保证数据流处理状态的备份和恢复。
3.学习了端到端 Exactly-Once 实现,其中重点学习了两阶段提交协议以及两阶段提交协议在Flink中的应用。
4.最后了解了实际案例中保证端到端Exaclty-once语义的场景。
标题:Exactly Once语义在Flink中的实现| 青训营笔记
网址:juejin.cn/