Flink-CEP论文与源码解读之状态与状态转换

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
简介: Flink CEP的论文与设计 Flink的CEP设计与实现重度参考了论文《Efficient Pattern Matching over Event Streams》。下面我们就来结合论文谈谈Flink CEP的设计。

Flink CEP的论文与设计

Flink的CEP设计与实现重度参考了论文《Efficient Pattern Matching over Event Streams》。下面我们就来结合论文谈谈Flink CEP的设计。

这篇论文探讨的话题是如何在事件流上进行高效地模式匹配。谈及模式匹配,为大众所知的可能是正则表达式匹配,而在流上运用正则表达式进行模式匹配有两个挑战:

  • 要求丰富的语言特性:在事件流上进行模式匹配的语言明显要比用正则表达式进行模式匹配的语言所需要的能力丰富得多。这些事件模式语言需要包含对表达序列、Kleene闭包、否定以及复杂断言的构建,同时还包含从混杂着相关、不相关事件的输入流中提取相关事件的策略;
  • 流上处理的效率:在事件流上进行的模式查询如何被高效地计算,需要新的算法和优化工作;

而这篇论文提出解决方案是:设计并实现了一个正式的计算模型:

NFAb
,它包含一个非确定性的有限自动机(NFA)和一个匹配缓冲区(buffer)。该模型为完整的事件模式查询集合提供了清晰的语义,允许进行优化并且可产生能在事件流上执行的查询计算计划,同时设计了一个共享的基于版本的缓冲区来优化针对每次运行构建独立匹配缓冲区所带来的资源开销。

除此之外,论文还分析了运行时复杂度、展示了运行时的算法实现与优化

NFA-b模型

NFAb
这一计算模型是由Flink CEP所参考的《Efficient Pattern Matching over Event Streams》论文提出的。NFA[^1](nondeterministic finite automaton,全称:非确定有限自动机)是对每个状态和输入符号对可以有多个可能的下一个状态的有限状态自动机。
NFAb
相较于NFA的改进是它配备了一个匹配缓冲区(buffer),用来作为模式的查询、计算模型。

考虑下面这个来自论文中的股票交易业务中的模式:

PATTERN SEQ(Stock+ a[ ], Stock b)
WHERE
 skip_till_next_match(a[ ], b) {
        [symbol]
  and a[1].volume > 1000
  and a[i].price > avg(a[..i-1].price)
  and b.volume < 80% * a[a.LEN].volume }
WITHIN
 1 hour

模式中的”[symbol]”表示分区处理。

上面的这个模式,描述了一个复杂的股票交易趋势:在过去的一段时间内,股票交易量开始升高,但在一个周期之后,当价格增长或者保持相对稳定后,交易量将会暴跌。这个模式有两个输入:在股票事件上的一个“正闭包”,结果存储于a[]中;一个分离的单一的股票事件,存储在b中。作用在a[1]上的断言指定了初始交易量,而作用在a[i](i > 1)上的断言要求其当前事件的价格超过之前被选择事件的平均值,这样的断言会捕获交易的价格增长趋势。最后一个断言将b跟a[a.LEN]进行比较,这里a.LEN关联着a[]中最后一个被选择的事件,它会捕获最终交易量的落差。

状态和状态转换

状态和转移函数(可类比成是衔接状态转换的边)是

NFAb
的两种基本组成要素,用于示例的股票模式的
NFAb
结构如下图所示:

NFA-structure

起始状态a[1],表示匹配过程的开始,它等待“正闭包”的事件输入并选择一个事件到匹配缓冲区中的a[1]单元。在下一个状态a[i],它会尝试选择另一个事件并放入缓冲区中的a[i](i > 1)单元。接下来的状态b表示匹配过程对于a[]已经完成了一个特定的匹配且已经准备好处理下一个模式输入。而最终状态F,则表示处理完成,它将创建一个模式匹配。

CEP代码中以State类表示状态,其完整类图如下:

CEP-State-class-diagram

从类图可见,它主要封装了状态的名称、类型以及跟其有关的状态集合。StateType是枚举类型,枚举值如下:

public enum StateType {
    Start,         // NFA的起始状态
    Final,         // NFA的终止状态
    Normal         // 非起始非终止状态的其他正常状态
}

从模式的状态图中可看到每个状态都关联着一组边,表示在状态上可以发生的转换动作。正如上图所展示的那样,首状态有一个“begin”边,每个a[i]状态有一个“proceed”边以及一个循环的“take”边。每个状态(除了起始状态和终止状态)都有一个循环的“ignore”边。

NFAb
会将模式中的“WHERE”以及“WITHIN”查询子句翻译成相关的语法附加到对应的边上,股票模式的各个边的条件语法如下图所示:

NFA-b-edge-formula

上面的这些转换动作,在代码中通过一个名为StateTransitionAction的枚举类来表示:

public enum StateTransitionAction {
    TAKE,         //获得当前事件并将它分配给新状态
    IGNORE,       //忽略当前事件并做状态转换
    PROCEED       //做状态转换并保留当前状态以为后续处理
}

总结而言,在CEP中以State表示上图中的节点,以StateTransition表示上图中的边,也即状态之间的转化。所以这两个对象之间是互相关联的关系:

State-and-StateTransition-class-diagram

状态将用于NFA中。


原文发布时间为:2017-03-03

本文作者:vinoYang

本文来自云栖社区合作伙伴CSDN博客,了解相关信息可以关注CSDN博客。

相关实践学习
基于Hologres轻松玩转一站式实时仓库
本场景介绍如何利用阿里云MaxCompute、实时计算Flink和交互式分析服务Hologres开发离线、实时数据融合分析的数据大屏应用。
Linux入门到精通
本套课程是从入门开始的Linux学习课程,适合初学者阅读。由浅入深案例丰富,通俗易懂。主要涉及基础的系统操作以及工作中常用的各种服务软件的应用、部署和优化。即使是零基础的学员,只要能够坚持把所有章节都学完,也一定会受益匪浅。
目录
相关文章
|
6月前
|
SQL 算法 API
读Flink源码谈设计:图的抽象与分层
前阵子组里的小伙伴问我“为什么Flink从我们的代码到真正可执行的状态,要经过这么多个graph转换?这样做有什么好处嘛?”我早期看到这里的设计时的确有过相同的疑惑,当时由于手里还在看别的东西,查阅过一些资料后就翻页了。如今又碰到了这样的问题,不妨就在这篇文章中好好搞清楚。
558 0
读Flink源码谈设计:图的抽象与分层
|
6月前
|
存储 消息中间件 缓存
读Flink源码谈设计:有效管理内存之道
在最初接触到Flink时,是来自于业界里一些头部玩家的分享——大家会用其来处理海量数据。在这种场景下,`如何避免JVM GC带来StopTheWorld带来的副作用`这样的问题一直盘绕在我心头。直到用了Flink以后,阅读了相关的源码(以1.14.0为基准),终于有了一些答案。在这篇文章里也是会分享给大家。
583 1
|
6月前
|
流计算
Flink源码解析
Flink源码解析
97 0
|
资源调度 流计算
Flink 指标参数源码解读(读取数量、发送数量、发送字节数、接收字节数等)(下)
Flink 指标参数源码解读(读取数量、发送数量、发送字节数、接收字节数等)(下)
151 1
|
3月前
|
消息中间件 Kubernetes 监控
实时计算 Flink版操作报错合集之在编译源码时遇到报错:无法访问,该如何处理
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
5月前
|
Oracle 关系型数据库 Java
实时计算 Flink版产品使用问题之源码 deploy,生成带有时间戳的jar包,如何修改配置信息
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
6月前
|
监控 Java 流计算
读Flink源码谈设计:Metric
前阵子笔者涉及了些许监控相关的开发工作,在开发过程中也碰到过些许问题,便翻读了Flink相关部分的代码,在读代码的过程中发现了一些好的设计,因此也是写成文章整理上来。
398 0
读Flink源码谈设计:Metric
|
监控 流计算
Flink 指标参数源码解读(读取数量、发送数量、发送字节数、接收字节数等)(上)
Flink 指标参数源码解读(读取数量、发送数量、发送字节数、接收字节数等)(上)
90 1
|
6月前
|
存储 SQL API
读Flink源码谈设计:流批一体的实现与现状
在Dataflow相关的论文发表前,大家都往往认为需要两套API来实现流计算和批计算,典型的实现便是Lambda架构。
619 0
|
6月前
|
存储 算法 Java
读Flink源码谈设计:Exactly Once
将Flink应用至生产已有一段时间,刚上生产的时候有幸排查过因数据倾斜引起的Checkpoint超时问题——当时简单的了解了相关机制,最近正好在读Flink源码,不如趁这个机会搞清楚。 在这里,我们首先要搞清楚两种Exactly-Once的区别: - Exactly Once:在计算引擎内部,数据不丢失不重复。本质是通过Flink开启检查点进行Barrier对齐,即可做到。 - End to End Exactly Once:这意味着从数据读取、引擎处理到写入外部存储的整个过程中,数据都是不丢失不重复的。这要求数据源可重放,写入端支持事务的恢复和回滚或幂等。
566 0