您的位置:首页 > 其它

SASE+:一种使用克林闭包应用于事件流的敏捷语言

2011-10-28 17:08 232 查看
翻译自论文: 《SASE+: An Agile Language for Kleene Closure over Event Streams》

  本文并不是原文的逐句翻译,而是提取了原文中的精华,并加入了本人的理解。【】里的内容是我作的注释。不当之处,欢迎指正。

  SASE+是一种复杂事件处理语言,它支持克林闭包来处理事件流。克林闭包已经被很好地研究正则表达式匹配,应用于流处理的克林闭包模式具有如下特征:事件定义,事件选择,终止原则。这些特征使它区别于传统问题中的模式研究。

1.三个特征

  相关事件定义(Relevant Event Definition):丰富的谓词定义了相关事件。这样的谓词可能针对一个单独事件指定某个属性值,也可能指出这个属性值怎样与之前的事件的值作比较,或者指出了该属性值怎样与之前的事件序列的聚集结果作比较。 【注:相关事件就是我们感兴趣的,有用的事件;反之就是无关事件。】

  事件选择策略(Event Selection Strategy):对于一个混合有相关事件和无关事件的事件流,克林闭包需要决定怎样从中选择相关事件。有的查询只需要选择出"连续"的相关事件,也有的需要从无关事件的交错中筛选出相关事件。后者要求对于事件的处理能够跳过无关事件,并选择出"不连续"的相关事件。

  终止原则(Termination Criteria):它指出了克林闭包何时终止计算。输入流是一个无限的事件流,而且某些查询可能要忽略无关事件,然后尽可能多地处理后续事件,因此这里的终止原则也就不同于传统的意义。在传统的意义中,输入是一个有限的字符串,而且不允许忽略任何字符。

2.SASE+事件语言

2.1事件流模型

  输入事件流:无限的事件序列。其中的每个事件是在某个时刻发生的,原子性的。每个事件包含类型名称和属性值的集合。每个事件都有一个时间戳,这个时间戳是离散的,有序的。我们假设在事件进入处理系统之前,时间戳由单独的机制分配。同时我们假设事件的时间戳是单调递增的,因此事件是有序的。时间戳是事件的隐式属性,当执行查询时,只能读取而不能修改它。

  输出事件流:也是事件的序列,每个事件包含一个属性的有限集。输出模型是输入模型的扩展,它允许属性带有复杂数据类型。数据类型可以按照两种方式划分:

  1)原子数据类型和序列数据类型:原子数据类型的值是单一的,不可分割的;序列数据类型的值是一个序列,序列中的每个值可以是原子,也可以是序列。

  2)简单数据类型和组合数据类型:简单数据类型不用其他数据类型定义,组合数据类型是由其他数据类型定义的。

  所以,输出模型中就有四种数据类型:原子-简单,原子-组合,序列-简单,序列-组合。【通俗地讲,序列数据类型就是数组,原子数据类型就是数组中的元素;简单数据类型就是编程语言中的基本数据类型,如int, char, float等,组合数据类型就是结构体或类。】

2.2语言概述

  SASE+的总体结构如下:

  [FROM <input stream>]

  PATTERN <pattern structure>

  [WHERE <pattern matching condition>]

  [WITHIN <sliding window>]

  [HAVING <pattern filtering condition>]

  RETURN <output specification>

   下面是第一个例子。



  Query1 的结果是得到Google股票在4个小时之内,当某个bad消息出现后的交易总量。PATTERN子句声明了模式结构,它使用SEQ结构表示一个有两个组件的序列模式:一个组件引用一个类型为NEWS的事件,另一个组件引用一系列类型为STOCK的事件。后者使用了”克林加“,由"+"标识,它是用来表示1个或多个特定事件。在每个组件中都用一个变量表示对应的事件,这两个变量就是a,b。其中使用了克林加的组件变量必须使用"[]"表示数组。

  WHERE子句,可有可无。它包含了基于值的谓词,进而定义了相关事件。它类似于SQL中的where子句。b[i](i>=1)是指每个STOCK事件,我们称这样的谓词b[i].symbol = ‘GOOG’ 是“单独迭代器”谓词。WITHIN子句在整个模式上指定了时间窗口,限制事件的发生时间是4个小时之内。

  PATTERN,WHERE,WITHIN三个子句完整地定义了一个模式。它们在事件流上的计算会产生模式匹配。每个模式匹配由一个唯一的事件序列组成,这些事件存储在a和b[]中,用来匹配该模式。

  RETURN子句把每个模式匹配转换成一个结果事件。在本例中,b[]在事件数组中使用了一个迭代器,它从每个事件中提取出volume属性,然后聚集函数sum()作用在所有提取出的值上。聚集函数创建了一个类型为”原子-简单“的属性。

  第二个例子:

 


  Query2 得到具有如下特征的股票:在1个小时之内股票价格从10到20,且交易量基本保持稳定。skip till next match是一种事件选择策略,我们稍后介绍,先看{}里的谓词。

  第一个谓词[symbol],要求相关的STOCK事件有相同的symbol属性,这种谓词称为”等值测试“("equivalence test")。它相当于根据特定属性,将事件流划分成”分区“,然后在每个分区上去匹配模式。【具有相同属性值的事件属于同一个分区,分区可以是间断的。”分区“也相当于”分组“的概念】

  后面还有三个谓词。a[1]上的谓词指定了序列的起始条件,下一个谓词指定了序列中每对相邻事件的关系。这种谓词,将每个事件与之前”被选择“的事件作比较,我们称之为”相关迭代器“谓词。最后一个谓词a[a.LEN]定义了序列的结束条件。【序列是由“被选择”的事件组成,即相关事件。】

  在PATTERN,WHERE,WITHIN产生模式匹配之后,HAVING子句通过其后的谓词进一步过滤事件。满足HAVING子句的模式匹配会被保留,然后输出。SASE+中WHERE与HAVING的不同类似于SQL语句。唯一的不同是这里的HAVING应用在每个模式匹配上,然而SQL中的HAVING应用在由Group by创建的每个分组上。

  RETURN子句提取出a[1].symbol和a[].price作为两个属性包含在结果事件中。注意,a[].price表示price值的数组,所以它是"序列-简单"的数据类型。

  第三个例子:



  Query3 针对每种股票捕获一种更加复杂的趋势:在最近的1小时,起始的交易量很大,但经过一段时间之后,当价格上涨或保持相对稳定时,交易量突然下降很多。这个查询的结构类似于Query2,但有几点不同。PATTERN结构有2个组件,它们是同类型的事件STOCK,但是一个是事件数组a[],一个是单一事件b。在WHERE子句中,作用在a[1]上的谓词使用volume属性定义了一个起始条件。相关迭代器,a[i],要求每个事件的价格大于之前选择的事件的价格的平均值。在相关迭代器中使用的聚集称为“运行聚集”("running
aggregates")。这个例子里,没有显式的条件作用在a[a.LEN]上,最后一个谓词将b的volume属性和a[a.LEN]作比较。

  对于每个由a[]和b组成的模式匹配,RETURN把它转换成一个结果事件,其中含有三个属性。a[].(price,volume)表示对于每个a[]中的事件,选择price和volume属性值,并转化成一个组合数据类型。()标识出它是一个组合数据类型。直到把所有的事件都提取出来,最终得到的a[].(price,volume)是一个“序列-组合”数据类型。而b.(price,volume)是"原子-组合"数据类型。

  以上我们描述了SASE+的基本结构。WHERE子句中的谓词定义了与克林闭包相关的事件,这些谓词形成了克林闭包的第一维的定义:相关事件定义(Relevant Event Definition)。

  难点在于第二维:事件选择策略。

2.2.1事件选择策略

  事件选择策略指明了怎么从混合了相关事件和无关事件的事件流中选出相关事件。

  再看Query2。它使用了等值测试[symbol],完整形式应该是a[i].symbo=a[i-1].symbol。还使用了迭代器谓词a[i].price>a[i-1].price。这都定义了前后两个事件的关系。然后有一点没有说明的就是,两个相关事件a[i]和a[i-1]在输入流中的位置关系。可能的位置关系包括:

  严格连续:输入流中的两个相关事件必须是连续的,也就是说,在它们之间不允许有其他事件。

  分区连续:输入流中的两个相关事件可以不是连续的。但是,如果事件流被划分成了分区,后一个相关事件必须与前一个事件位于同一个分区中。例如在Query2中,等值测试为每个股票symbol形成一个分区,然后查询就捕捉每个分区上价格的单调递增趋势。【分区就是按某个属性值分组!!!】用来产生分区的条件可以是谓词的任意组合,但不能使用聚集函数。这就比等值测试更丰富(等值测试就相当于SQL中的GROUP BY或CQL中的PARTITION BY)。

  skip till next match:在该策略中,两个相关事件不是必须是分区连续的。后一个相关事件的选择,可以完全忽略无关事件,且只把当前事件与之前选择的事件作比较。在这种方式下,克林闭包能够一直进行下去,直到终止原则的条件满足。在这个策略下,Query2 有不同的含义:它在捕获价格从10到20的趋势时,就忽略中间的有波动的数值。

  skip till any match:该策略进一步放宽了选择相关事件的要求。对于每一个接收的相关事件,它可以作出非确定的决策:把事件放入克林闭包中,或者忽略事件。当我们为了延长克林闭包的计算,为了得到一个更长的事件序列,而必须忽略某些相关事件时,这个策略就派上用场了。例如,给定一个股票价格序列,“1, 2, 7, 3, 4, 5, 6”,最长的递增价格事件序列是“1, 2, 3, 4, 5, 6”。为了得到这个结果必须忽略7,尽管7也是一个相关事件。

  SASE+中默认的事件选择策略是skip till next match。当定义一个查询时,可以不用显式地声明它,如Query1。当使用分区连续时,查询中出现的等值测试就作为默认的分区条件。当然,也可以使用其他的谓词来定义分区。

2.2.2 终止原则

  终止原则是克林闭包定义中的第三维。

  最后一个事件的选择条件:Query2 展示了这个终止类型。WHERE子句中的a[a.LEN]限定了最后一个被选择的事件的条件。该谓词没有指出当检测到这样一个事件时,应该作出什么动作,是终止还是继续产生更多的匹配?考虑图(a)中的股票价格变化,从1到2的序列产生一个模式匹配。但是,可能后面还有价格等于20的点,如3,这样的话克林闭能够产生更多的匹配。对于不关心这种额外数据(指的是点3)的查询,可以使用a[a.LEN]作为终止原则。这时就要在克林加变量后面添加一个"!"



  模式中下一个组件:Query3 展示了这个终止类型。该查询中没有使用a[a.LEN]这样的谓词,但是它使用b作为后续组件。将图(a)和图(b)放在一起考虑,(a)是价格变化,(b)是交易量变化。克林闭包从1开始启动(1点的volume>1000),然后到达2(通过检查a[i].price>avg(a[..i-1].price))。点3的事件满足b上的谓词(b.volume<80%*a[a.LEN].volume),此时产生一个模式匹配。然而, 点3的事件也可以用来继续克林闭包的执行,因为它同时满足a[i].price>avg(a[..i-1].price;这就导致另一个模式匹配,该模式匹配在点4终止。在SASE+中,当查询中的下一个模式组件匹配时,通过使用"!",可以强制克林闭包终止;或者不使用"!",让克林闭包继续以产生另外的匹配。

  窗口限制:可以使用时间窗口来终止克林闭包,这个最简单,不多说了。

2.2.3 克林闭包中的否定



  Query4 给出了一个例子。物品从NewYork被运到 Amherst,在途中的每个点都会扫描。这个查询是为了监测运输中的异常事件。具体来说,一个物品在起点NewYork被扫描,在终点Amherst被扫描,但是在途中没经过连续的扫描,或者扫描的点大于3个,都被认为是异常。在RETURN子句里使用了AS结构把结果作了一次重命名,IN STREAM结构重命名了输出流,以便给后面的查询使用。

3. 形式化语义模型

  语义模型的基础是带有match buffer的非确定有穷自动机(NFA)。我们称这种组合的自动机为

,它比标准NFA具有更强大的能力。

未完待续......
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐