深入理解Flink Streaming SQL

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
简介: 序言        时效性提升数据的价值,所以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轻松玩转一站式实时仓库
本场景介绍如何利用阿里云MaxCompute、实时计算Flink和交互式分析服务Hologres开发离线、实时数据融合分析的数据大屏应用。
Linux入门到精通
本套课程是从入门开始的Linux学习课程,适合初学者阅读。由浅入深案例丰富,通俗易懂。主要涉及基础的系统操作以及工作中常用的各种服务软件的应用、部署和优化。即使是零基础的学员,只要能够坚持把所有章节都学完,也一定会受益匪浅。
目录
相关文章
|
1月前
|
SQL 资源调度 Oracle
Flink CDC产品常见问题之sql运行中查看日志任务失败如何解决
Flink CDC(Change Data Capture)是一个基于Apache Flink的实时数据变更捕获库,用于实现数据库的实时同步和变更流的处理;在本汇总中,我们组织了关于Flink CDC产品在实践中用户经常提出的问题及其解答,目的是辅助用户更好地理解和应用这一技术,优化实时数据处理流程。
|
1月前
|
SQL 关系型数据库 MySQL
Flink 提供了一种名为 Flink SQL 的查询语言,它支持多种数据库之间的 DDL 语句转换
【2月更文挑战第18天】Flink 提供了一种名为 Flink SQL 的查询语言,它支持多种数据库之间的 DDL 语句转换
171 2
|
1月前
|
SQL 存储 Apache
在 Apache Flink SQL 中,并没有内置的 GROUP_CONCAT 函数
【2月更文挑战第16天】在 Apache Flink SQL 中,并没有内置的 GROUP_CONCAT 函数
186 2
|
1月前
|
SQL 分布式计算 HIVE
基于 Kyuubi 实现分布式 Flink SQL 网关
本文整理自网易互娱资深开发工程师、Apache Kyuubi Committer 林小铂的《基于 Kyuubi 实现分布式 Flink SQL 网关》分享。
104448 64
基于 Kyuubi 实现分布式 Flink SQL 网关
|
2月前
|
SQL 数据采集 JSON
弱结构化日志 Flink SQL 怎么写?SLS SPL 来帮忙
弱结构化日志 Flink SQL 怎么写?SLS SPL 来帮忙
125157 136
|
2月前
|
SQL 监控 API
Flink SQL支持写判断语句
【2月更文挑战第8天】Flink SQL支持写判断语句
236 12
|
2月前
|
SQL 消息中间件 Kafka
flink问题之做实时数仓sql保证分topic区有序如何解决
Apache Flink是由Apache软件基金会开发的开源流处理框架,其核心是用Java和Scala编写的分布式流数据流引擎。本合集提供有关Apache Flink相关技术、使用技巧和最佳实践的资源。
705 3
|
7天前
|
SQL 人工智能 算法
【SQL server】玩转SQL server数据库:第二章 关系数据库
【SQL server】玩转SQL server数据库:第二章 关系数据库
47 10
|
1月前
|
SQL 数据库 数据安全/隐私保护
Sql Server数据库Sa密码如何修改
Sql Server数据库Sa密码如何修改
|
17天前
|
SQL
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
16 0