热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入理解FlinkStreamingSQL

序言

       时效性提升数据的价值,所以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

          深入理解Flink Streaming SQL

SQL

         深入理解Flink Streaming SQL 

Sink

         深入理解Flink Streaming SQL

运行结果

         深入理解Flink Streaming SQL

转换Table为Stream

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

转为逻辑计划(Logical Plan)

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

           深入理解Flink Streaming SQL

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

              深入理解Flink Streaming 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。

                  深入理解Flink Streaming SQL                  

下推Filter

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

             深入理解Flink Streaming SQL               

合并Filter   

                 利用结合律,合并Filter。

         深入理解Flink Streaming SQL

转为物理计划(Physical Plan)

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

深入理解Flink Streaming SQL

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

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

        深入理解Flink Streaming SQL

优化Stream Graph

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

Chaining判断条件

            深入理解Flink Streaming SQL

Chaining结果  

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

            深入理解Flink Streaming SQL                        

GROUP BY

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

例子    

Source

        深入理解Flink Streaming SQL

Water Mark

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

深入理解Flink Streaming SQL      

SQL

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

深入理解Flink Streaming SQL      

Sink

深入理解Flink Streaming SQL

转换Table为Stream

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

转为逻辑计划(Logical Plan)

  深入理解Flink Streaming SQL

优化Logical Plan

深入理解Flink Streaming SQL

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

深入理解Flink Streaming SQL

 

转为物理计划(Physical Plan)

      深入理解Flink Streaming SQL

优化Stream Graph

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

深入理解Flink Streaming SQL

 

Streaming各基本概念之间的联系

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

Window和EventTime

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

         深入理解Flink Streaming SQL                 

Window和WaterMark

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

  深入理解Flink Streaming SQL

TimeWindow,EventTime,ProcessTime 和 Watermark

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

       深入理解Flink Streaming SQL        

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

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

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

运行结果

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

数据有序

SUM算子接收到的数据

    数据的Eventtime按升序排列。

深入理解Flink Streaming SQL

WarterMark推进图

   每条新数据都能推进Watermark。

     深入理解Flink Streaming SQL

结果输出

     所有数据都被处理,没有数据被丢弃。      深入理解Flink Streaming SQL 

数据乱序

SUM算子接收到的数据

     第四条事件延时到来。

深入理解Flink Streaming SQL

     

WarterMark推进图

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

深入理解Flink Streaming SQL

输出结果

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

深入理解Flink Streaming SQL

 

JOIN

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

例子

Source

深入理解Flink Streaming SQL

SQL

 广告的展现LEFT JOIN 广告的点击来更新状态:showed 或 clicked。 深入理解Flink Streaming SQL

Sink

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

深入理解Flink Streaming SQL

 

转换Table为Stream

    RetractionStream没有引入特殊变化。

转为逻辑计划(Logical Plan)

   深入理解Flink Streaming SQL

优化Logical Plan  深入理解Flink Streaming SQL

转为物理计划(Physical Plan)

深入理解Flink Streaming SQL

优化Stream Graph

深入理解Flink Streaming SQL

运行结果

    结果数据的首个字段为标志位,True为正常数据,False为Retract数据。
深入理解Flink Streaming SQL

    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流的后续算子的输出。    
深入理解Flink Streaming SQL

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

      深入理解Flink Streaming SQL

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

终止

      最终需要支持Retraction的Sink来终止RetractionStream,比如:
     深入理解Flink Streaming SQL        

      最终输出retractedResults:

      深入理解Flink Streaming SQL

存储

       只有外部存储支持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”针对预期的应用场景在数据准确性,系统稳定性和运行性能上做了合适的折中。

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


推荐阅读
  • Spring Data JdbcTemplate 入门指南
    本文将介绍如何使用 Spring JdbcTemplate 进行数据库操作,包括查询和插入数据。我们将通过一个学生表的示例来演示具体步骤。 ... [详细]
  • 解决Bootstrap DataTable Ajax请求重复问题
    在最近的一个项目中,我们使用了JQuery DataTable进行数据展示,虽然使用起来非常方便,但在测试过程中发现了一个问题:当查询条件改变时,有时查询结果的数据不正确。通过FireBug调试发现,点击搜索按钮时,会发送两次Ajax请求,一次是原条件的请求,一次是新条件的请求。 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 本文节选自《NLTK基础教程——用NLTK和Python库构建机器学习应用》一书的第1章第1.2节,作者Nitin Hardeniya。本文将带领读者快速了解Python的基础知识,为后续的机器学习应用打下坚实的基础。 ... [详细]
  • 本文详细介绍了Java代码分层的基本概念和常见分层模式,特别是MVC模式。同时探讨了不同项目需求下的分层策略,帮助读者更好地理解和应用Java分层思想。 ... [详细]
  • DAO(Data Access Object)模式是一种用于抽象和封装所有对数据库或其他持久化机制访问的方法,它通过提供一个统一的接口来隐藏底层数据访问的复杂性。 ... [详细]
  • 本文介绍了在 Java 编程中遇到的一个常见错误:对象无法转换为 long 类型,并提供了详细的解决方案。 ... [详细]
  • 本文介绍如何使用 Python 的 DOM 和 SAX 方法解析 XML 文件,并通过示例展示了如何动态创建数据库表和处理大量数据的实时插入。 ... [详细]
  • 深入解析 Lifecycle 的实现原理
    本文将详细介绍 Android Jetpack 中 Lifecycle 组件的实现原理,帮助开发者更好地理解和使用 Lifecycle,避免常见的内存泄漏问题。 ... [详细]
  • 如何在Java中使用DButils类
    这期内容当中小编将会给大家带来有关如何在Java中使用DButils类,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。D ... [详细]
  • 在 Ubuntu 中遇到 Samba 服务器故障时,尝试卸载并重新安装 Samba 发现配置文件未重新生成。本文介绍了解决该问题的方法。 ... [详细]
  • 第二十五天接口、多态
    1.java是面向对象的语言。设计模式:接口接口类是从java里衍生出来的,不是python原生支持的主要用于继承里多继承抽象类是python原生支持的主要用于继承里的单继承但是接 ... [详细]
  • 2018年在北航听陈博士讲解时,对重入漏洞有了初步了解。最近重温了慢雾科技的相关文章,发现他们对重入漏洞的解释非常清晰明了。 ... [详细]
  • 在2019中国国际智能产业博览会上,百度董事长兼CEO李彦宏强调,人工智能应务实推进其在各行业的应用。随后,在“ABC SUMMIT 2019百度云智峰会”上,百度展示了通过“云+AI”推动AI工业化和产业智能化的最新成果。 ... [详细]
  • Flutter中计算文本尺寸的方法
    在Flutter开发中,有时需要计算文本的宽度和高度。本文介绍了一种利用TextPainter类实现这一功能的方法。 ... [详细]
author-avatar
搜狐搜不到你的爱_276
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有