热门标签 | 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”针对预期的应用场景在数据准确性,系统稳定性和运行性能上做了合适的折中。

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


推荐阅读
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • ejava,刘聪dejava
    本文目录一览:1、什么是Java?2、java ... [详细]
  • 抽空写了一个ICON图标的转换程序
    抽空写了一个ICON图标的转换程序,支持png\jpe\bmp格式到ico的转换。具体的程序就在下面,如果看的人多,过两天再把思路写一下。 ... [详细]
  • 基于事件驱动的并发编程及其消息通信机制的同步与异步、阻塞与非阻塞、IO模型的分类
    本文介绍了基于事件驱动的并发编程中的消息通信机制,包括同步和异步的概念及其区别,阻塞和非阻塞的状态,以及IO模型的分类。同步阻塞IO、同步非阻塞IO、异步阻塞IO和异步非阻塞IO等不同的IO模型被详细解释。这些概念和模型对于理解并发编程中的消息通信和IO操作具有重要意义。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文介绍了在MySQL8.0中如何查看性能并解析SQL执行顺序。首先介绍了查询性能工具的开启方法,然后详细解析了SQL执行顺序中的每个步骤,包括from、on、join、where、group by、having、select distinct、union、order by和limit。同时还介绍了虚拟表的概念和生成过程。通过本文的解析,读者可以更好地理解MySQL8.0中的性能查看和SQL执行顺序。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • 解决.net项目中未注册“microsoft.ACE.oledb.12.0”提供程序的方法
    在开发.net项目中,通过microsoft.ACE.oledb读取excel文件信息时,报错“未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序”。本文提供了解决这个问题的方法,包括错误描述和代码示例。通过注册提供程序和修改连接字符串,可以成功读取excel文件信息。 ... [详细]
  • Explain如何助力SQL语句的优化及其分析方法
    本文介绍了Explain如何助力SQL语句的优化以及分析方法。Explain是一个数据库SQL语句的模拟器,通过对SQL语句的模拟返回一个性能分析表,从而帮助工程师了解程序运行缓慢的原因。文章还介绍了Explain运行方法以及如何分析Explain表格中各个字段的含义。MySQL 5.5开始支持Explain功能,但仅限于select语句,而MySQL 5.7逐渐支持对update、delete和insert语句的模拟和分析。 ... [详细]
  • 用Vue实现的Demo商品管理效果图及实现代码
    本文介绍了一个使用Vue实现的Demo商品管理的效果图及实现代码。 ... [详细]
  • 本文详细介绍了Android中的坐标系以及与View相关的方法。首先介绍了Android坐标系和视图坐标系的概念,并通过图示进行了解释。接着提到了View的大小可以超过手机屏幕,并且只有在手机屏幕内才能看到。最后,作者表示将在后续文章中继续探讨与View相关的内容。 ... [详细]
  • 本文介绍了如何在Jquery中通过元素的样式值获取元素,并将其赋值给一个变量。提供了5种解决方案供参考。 ... [详细]
  • MySQL多表数据库操作方法及子查询详解
    本文详细介绍了MySQL数据库的多表操作方法,包括增删改和单表查询,同时还解释了子查询的概念和用法。文章通过示例和步骤说明了如何进行数据的插入、删除和更新操作,以及如何执行单表查询和使用聚合函数进行统计。对于需要对MySQL数据库进行操作的读者来说,本文是一个非常实用的参考资料。 ... [详细]
  • 本文介绍了关于Java异常的八大常见问题,包括异常管理的最佳做法、在try块中定义的变量不能用于catch或finally的原因以及为什么Double.parseDouble(null)和Integer.parseInt(null)会抛出不同的异常。同时指出这些问题是由于不同的开发人员开发所导致的,不值得过多思考。 ... [详细]
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社区 版权所有