深入理解Flink Streaming SQL

简介: 序言        时效性提升数据的价值,所以Flink这样的流式(Streaming)计算系统应用得越来越广泛。        广大的普通用户决定一个产品的界面和接口。       ETL开发者需要简单而有效的开发工具,从而把更多时间花在理业务和对口径上。  &n

序言

       时效性提升数据的价值,所以Flink这样的流式(Streaming)计算系统应用得越来越广泛。

       广大的普通用户决定一个产品的界面和接口。
       ETL开发者需要简单而有效的开发工具,从而把更多时间花在理业务和对口径上。
       因此流式计算系统都趋同以SQL作为唯一开发语言,让用户以Table形式操作Stream。

      程序开发三部曲:First make it work, then make it right, and, finally, make it fast.

      流计算开发者面对的现状及趋势:

      第一步,让程序运行起来。
                     开发者能用SQL方便地表达问题。
                     开发者能通过任务管理系统一体化地管理任务,如:开发,上线,调优,监控和排查任务。

       第二步,让程序运行正确。
                      简单数据清洗之外的流计算开发需求通常会涉及到Streaming SQL的两个核心扩展:Window 和 Emit。
                      开发者深入理解Window和 Emit的语义是正确实现这些业务需求的关键,
                      否则无法在数据时效性和数据准确性上做适合各个业务场景的决策和折中。

       第三步,让程序运行越来越快。
                      苹果每年都会发布新手机:使用了**芯片,性能提升了多少,耗电降低了多少,增加**功能...。
                      当前,流计算系统每年也会有很大的性能提升和功能扩展,但想要深入调优及排错,
                      还是要学习分布式系统的各个组件及原理,各种算子实现方法,性能优化技术等知识。
                      以后,随着系统的进一步成熟和完善,开发者在性能优化上的负担会越来越低,
                      无需了解底层技术实现细节和手动配置各种参数,就能享受性能和稳定性的逐步提升。

      分布式系统的一致性和可用性是一对矛盾。
      流计算系统的数据准确性和数据时效性也是一对矛盾。
      应用开发者都需要认识到这些矛盾,并且知道自己在什么场景下该作何种取舍。

     本文希望通过剖析Flink Streaming SQL的三个具体例子:Union,Group By 和 Join ,
     来依次阐述流式计算模型的核心概念: What, Where, When, How 。
     以便开发者加深对Streaming SQL的Window 和 Emit语义的理解,
     从而能在数据准确性和数据时效性上做适合业务场景的折中和取舍。
     也顺带介绍Streaming SQL的底层实现,以便于SQL任务的开发和调优。

UNION

       通过这个例子来阐述Streaming SQL的底层实现和优化手段:Logical Plan Optimization 和 Operator Chaining。

例子

         改编自Flink StreamSQLExample 。只在最外层加了一个Filter,以便触发Filter下推及合并。

Source

          

SQL

          

Sink

         

运行结果

         

转换Table为Stream

           Flink 会把基于Table的Streaming SQL转为基于Stream的底层算子,并同时完成Logical Plan及Operator Chaining等优化

转为逻辑计划(Logical Plan)

           上述UNION ALL SQL依据Relational Algebra转换为下面的逻辑计划:

           

           SQL字段与逻辑计划有如下的对应关系:

              

                          

优化Logical Plan

理论基础

幂等

                      数学:  19 * 10 * 1  * 1 = 19 * 10 = 190
                      SQL:  SELECT * FROM (SELECT user, product FROM OrderA) =  SELECT user, product FROM OrderA

交换律

                      数学:10 * 19 = 19 * 10 = 190
                      SQL:   tableA UNION ALL tableB  = tableB UNION ALL tableA

结合律

                      数学:
                            (1900 * 0.5)* 0.2 = 1900 * (0.5 * 0.2) = 190                       
                              1900 * (1.0 + 0.01) = 1900 * 1.0 + 1900 * 0.01 = 1919

                      SQL:
                            SELECT * FROM (SELECT user, amount FROM OrderA) WHERE amount > 2 
                            SELECT * FROM (SELECT user, amount FROM OrderA WHERE amount > 2)

优化过程

                      Flink的逻辑计划优化规则清单请见: FlinkRuleSets                  
                      此Union All例子根据幂等,交换律和结合律来完成以下三步优化:

消除冗余的Project

                      利用幂等特性,消除冗余的Project。

                                    

下推Filter

                   利用交换率和结合律特性,下推Filter。

                            

合并Filter   

                 利用结合律,合并Filter。

         

转为物理计划(Physical Plan)

 转换后的Flink的物理执行计划如下:

        有Physical Plan优化这一步骤,但对以上例子没有效果,所以忽略。

        这样,加上Source和Sink,产生了如下的Stream Graph:

        

优化Stream Graph

            通过Task Chaining来减少上下游算子的数据传输消耗,从而提高性能。              

Chaining判断条件

            

Chaining结果  

            按深度优先的顺序遍历Stream Graph,最终产生5个Task任务。

                                    

GROUP BY

       将以滚动窗口的GROUP BY来阐述Streaming SQL里的Window和Emit语义,
       及其背后的Streaming的Where(Window)和When(Watermark和Trigger)的概念及关系。

例子    

Source

        

Water Mark

       简单地把最新的EventTime减去Offset。

      

SQL

       按用户加滚动窗口进行Group By。

      

Sink

转换Table为Stream

      因为Union All例子比较详细地阐述了转换规则,此处只讨论特殊之处。

转为逻辑计划(Logical Plan)

  

优化Logical Plan

       GROUP BY优化:把{“User + Window” -> SUM} 转为 {User -> {Window -> SUM}}。
       新的数据结构确保同一User下所有Window都会被分配到同一个Operator,以便实现SessionWindow的Merge功能。

 

转为物理计划(Physical Plan)

      

优化Stream Graph

       经过Task Chaining优化后,最终生成3个Task。

 

Streaming各基本概念之间的联系

         此处希望以图表的形式阐述各个概念之间的关系。

Window和EventTime

         Flink支持三种Window类型: Tumbling Windows , Sliding Windows 和 Session Windows
         每个事件的EventTime决定事件会落到哪些TimeWindow。
         但只有Window的第一个数据来到时,Window才会被真正创建。

                          

Window和WaterMark

           可以设置TimeWindow的AllowedLateness,从而使Window可以处理延时数据。
           只有当WaterMark超过TimeWindow.end + AllowedLateness时,Window才会被销毁。

  

TimeWindow,EventTime,ProcessTime 和 Watermark

       我们以WaterMark的推进图来阐述这四者之间的关系。
       Window为TumbleWindow,窗口大小为1小时,允许的数据延迟为1小时。

               

WaterMark和EventTime:
       新数据的最新Eventime推进WaterMark。

TimeWindow的生命周期: 

      以下三条数据的EventTime决定TimeWindow的状态转换。
      数据1的Eventtime属于Window[10:00, 11,00),因为Window不存在,所以创建此Window。
      数据2的Eventime推进WaterMark超过11:00(Window.end),所以触发Pass End。
      数据3的Eventime推进WaterMark超过12:00(Window.end + allowedLateness), 所以关闭此Window。

TimeWindow的结果输出

       用户可以通过Trigger来控制窗口结果的输出,按窗口的状态类型有以下三种Trigger。

       

       Flink的Streaming SQL目前只支持PassEnd Trigger,且默认AllowedLateness = 0。

       如果触发频率是Repeated,比如:每分钟, 往下游输出一次。那么这个时间只能是ProcessTime。
       因为WarkMark在不同场景下会有不同推进速度,比如处理一小时的数据,
       可能只需十分钟(重跑),一个小时(正常运行)或 大于1小时(积压)。

运行结果

    允许数据乱序是分布式系统能够并发处理消息的前提。
    当前这个例子,数据如果乱序可以产生不同的输出结果。

数据有序

SUM算子接收到的数据

    数据的Eventtime按升序排列。

WarterMark推进图

   每条新数据都能推进Watermark。

     

结果输出

     所有数据都被处理,没有数据被丢弃。       

数据乱序

SUM算子接收到的数据

     第四条事件延时到来。

     

WarterMark推进图

   延迟的数据不会推进WaterMark,且被丢弃。

输出结果

 没有统计因延迟被丢弃的第四条事件。

 

JOIN

   将通过此例子来阐述Streaming的Retraction语义。

例子

Source

SQL

 广告的展现LEFT JOIN 广告的点击来更新状态:showed 或 clicked。 

Sink

   LEFT JOIN 可能会发送多条数据到下游。
   因此必须转为RetractionStream,让下游算子有机会能撤销前次输出,从而只产生一条最终结果。

 

转换Table为Stream

    RetractionStream没有引入特殊变化。

转为逻辑计划(Logical Plan)

   

优化Logical Plan  

转为物理计划(Physical Plan)

优化Stream Graph

运行结果

    结果数据的首个字段为标志位,True为正常数据,False为Retract数据。

    RetractJoin的执行逻辑请见:NonWindowOuterJoin 

    ImpressionId = 1这条数据的ReactJoin执行过程。
    1: Left流的Show消息先到:  Show("1", "show", "2018-10-10 10:10:10")
        因为之前没有输出,所以无需Retrcact。
        只输出:  (true, 1,2018-10-10 10:10:10,showed)
    2: Right流的Click消息后到:Click("1", "click", "2018-10-10 10:13:11")
        因为之前已输出过结果,所以需要Retract,输出:
        (false, 1,2018-10-10 10:10:10,showed)
        然后再输出新结果,
        (true, 1,2018-10-10 10:10:10,clicked)

   如上可知,Retraction流相当于把一条UPDATE消息分别拆成一条DELETE和一条INSERT消息。

Retraction Stream

     虽然Retraction机制最多增加一倍的数据传输量,但能降低下游算子的存储负担和撤销实现难度。

传递

 我们在Left Join的输出流后加一个GROUP BY,以观察Retraction流的后续算子的输出。    

       可能得到以下的GROUP BY输出:

      

      由此可见,Retraction具有传递性,RetractStream的后续的Stream也会是RetractionStream。

终止

      最终需要支持Retraction的Sink来终止RetractionStream,比如:
             

      最终输出retractedResults:

      

存储

       只有外部存储支持UPDATE或DELETE操作时,才能实现RetractionSink。

       常见的KV存储和数据库,如HBase,Mysql都可实现RetractionSink。
       后续程序总能从这些存储中读取最新数据,上游是否是Retraction流对用户是透明的。

       常见的消息队列,如Kafka,只支持APPEND操作,则不能实现RetractionSink。
       后续程序从这些消息队列可能会读到重复数据,因此用户需要在后续程序中处理重复数据。

总结

      Flink Streaming SQL的实现从上到下共有三层:
      1:Streaming SQL
      2:Streaming 和 Window
      3:Distributed Snapshots
     
    其中
“Streaming Data Model” 和 “Distributed Snapshot” 是Flink这个分布式流计算系统的核心架构设计。
    “Streaming Data Model”的What, Where, When, How 明确了流计算系统的表达能力及预期应用场景。
    “
Distributed Snapshots”针对预期的应用场景在数据准确性,系统稳定性和运行性能上做了合适的折中。

    本文通过实例阐述了流计算开发者需要了解的最上面两层的概念和原理,
    以便流计算开发者能在数据准确性和数据时效性上做适合业务场景的折中和取舍。  

相关实践学习
基于Hologres+Flink搭建GitHub实时数据大屏
通过使用Flink、Hologres构建实时数仓,并通过Hologres对接BI分析工具(以DataV为例),实现海量数据实时分析.
实时计算 Flink 实战课程
如何使用实时计算 Flink 搞定数据处理难题?实时计算 Flink 极客训练营产品、技术专家齐上阵,从开源 Flink功能介绍到实时计算 Flink 优势详解,现场实操,5天即可上手! 欢迎开通实时计算 Flink 版: https://cn.aliyun.com/product/bigdata/sc Flink Forward Asia 介绍: Flink Forward 是由 Apache 官方授权,Apache Flink Community China 支持的会议,通过参会不仅可以了解到 Flink 社区的最新动态和发展计划,还可以了解到国内外一线大厂围绕 Flink 生态的生产实践经验,是 Flink 开发者和使用者不可错过的盛会。 去年经过品牌升级后的 Flink Forward Asia 吸引了超过2000人线下参与,一举成为国内最大的 Apache 顶级项目会议。结合2020年的特殊情况,Flink Forward Asia 2020 将在12月26日以线上峰会的形式与大家见面。
目录
相关文章
|
9月前
|
SQL 人工智能 JSON
Flink 2.1 SQL:解锁实时数据与AI集成,实现可扩展流处理
简介:本文整理自阿里云高级技术专家李麟在Flink Forward Asia 2025新加坡站的分享,介绍了Flink 2.1 SQL在实时数据处理与AI融合方面的关键进展,包括AI函数集成、Join优化及未来发展方向,助力构建高效实时AI管道。
1156 43
|
9月前
|
SQL 人工智能 JSON
Flink 2.1 SQL:解锁实时数据与AI集成,实现可扩展流处理
本文整理自阿里云的高级技术专家、Apache Flink PMC 成员李麟老师在 Flink Forward Asia 2025 新加坡[1]站 —— 实时 AI 专场中的分享。将带来关于 Flink 2.1 版本中 SQL 在实时数据处理和 AI 方面进展的话题。
542 0
Flink 2.1 SQL:解锁实时数据与AI集成,实现可扩展流处理
|
10月前
|
SQL 消息中间件 Kafka
Flink SQL 详解:流批一体处理的强大工具
Flink SQL 是 Apache Flink 提供的 SQL 引擎,支持流批一体处理,统一操作流数据与批数据,具备高性能、低延迟、丰富数据源支持及标准 SQL 兼容性,适用于实时与离线数据分析。
1243 1
|
SQL 大数据 数据处理
Flink SQL 详解:流批一体处理的强大工具
Flink SQL 是为应对传统数据处理框架中流批分离的问题而诞生的,它融合了SQL的简洁性和Flink的强大流批处理能力,降低了大数据处理门槛。其核心工作原理包括生成逻辑执行计划、查询优化和构建算子树,确保高效执行。Flink SQL 支持过滤、投影、聚合、连接和窗口等常用算子,实现了流批一体处理,极大提高了开发效率和代码复用性。通过统一的API和语法,Flink SQL 能够灵活应对实时和离线数据分析场景,为企业提供强大的数据处理能力。
2374 27
|
SQL 存储 缓存
Flink SQL Deduplication 去重以及如何获取最新状态操作
Flink SQL Deduplication 是一种高效的数据去重功能,支持多种数据类型和灵活的配置选项。它通过哈希表、时间窗口和状态管理等技术实现去重,适用于流处理和批处理场景。本文介绍了其特性、原理、实际案例及源码分析,帮助读者更好地理解和应用这一功能。
1340 14
|
关系型数据库 MySQL 网络安全
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
|
SQL 存储 监控
SQL Server的并行实施如何优化?
【7月更文挑战第23天】SQL Server的并行实施如何优化?
859 13
解锁 SQL Server 2022的时间序列数据功能
【7月更文挑战第14天】要解锁SQL Server 2022的时间序列数据功能,可使用`generate_series`函数生成整数序列,例如:`SELECT value FROM generate_series(1, 10)。此外,`date_bucket`函数能按指定间隔(如周)对日期时间值分组,这些工具结合窗口函数和其他时间日期函数,能高效处理和分析时间序列数据。更多信息请参考官方文档和技术资料。
590 9
|
SQL 存储 网络安全
关系数据库SQLserver 安装 SQL Server
【7月更文挑战第26天】
371 6
|
SQL Oracle 关系型数据库
MySQL、SQL Server和Oracle数据库安装部署教程
数据库的安装部署教程因不同的数据库管理系统(DBMS)而异,以下将以MySQL、SQL Server和Oracle为例,分别概述其安装部署的基本步骤。请注意,由于软件版本和操作系统的不同,具体步骤可能会有所变化。
1418 3