1.3 流式数据架构基本概念

1.3.1 流

流往往代表事物的无尽特征,它丰富的内涵往往会造成人们对流式数据处理是什么的误解,以及对流式数据处理系统特征(能做什么、不能做什么)的混淆。在开始详述流式数据处理理论之前,我们先定义流。

最初,流式数据处理是通过批处理系统实现的,如Spark Streaming,其原理是将多个微批处理任务串接起来构建流式数据处理任务。但是这种采用微批重复运行的机制,牺牲了延迟和吞吐,引发了Spark Streaming是不是真正流式数据处理引擎的争议。为此,业界便开始构建用于处理没有时间边界数据(无界数据集,Unbounded Data)的实时数据系统。

因此,从这个角度可以定义流是一种为无界数据集设计的数据处理引擎,这种引擎具备以下特征:

(1)具备强一致性,即支持exactly-once语义。

(2)提供丰富的时间工具,如事件时间、处理时间、窗口。

(3)保证系统具有可弹性、伸缩性。

(4)同时保证高吞吐、低延迟与容错。

(5)支持高层语义,如流式关系型API(SQL)、复杂事件处理(CEP,Complex Event Processing)。

此外,本书中还用流式数据处理系统、流式数据处理架构及流处理等具有相同内涵的术语指代streaming,其中流式数据处理架构用在描述系统架构的语境中。虽然“流处理”这个词用得较为广泛,但是本书只在和批处理对比分析的语境中使用流处理这个口语化称呼。

1.3.2 时间

在流式数据处理理论中,经常使用事件或记录表示从所处理的数据集中拉取的数据,在Flink中通常以有结构的对象表示事件。

在无界数据处理中,主要有两类事件概念。

(1)事件时间(Event Time):事件实际发生的时间。

(2)处理时间(Processing Time):事件被处理的时间。

并不是所有应用场景都关注事件时间,但其重要性是不言而喻的。例如,在用户行为特征分析、异常检测、基于信贷历史的风控模型等分析中,事件时间起到了决定性的作用。

用户行为特征分析

用户浏览网页或App时会产生一系列页面点击与浏览时长数据,这些数据被称为用户行为数据。用户行为数据可以用来判断用户的产品喜好,因此可以用在精准营销、产品功能迭代等环节。

我们可以从这种点击流数据中抽取很多行为指标,如访问频率、平均停留时长、消费行为、信息互动行为、内容发布行为等,从这些指标可以分析出用户的黏性、活跃度,以及产出。

(1)黏性是衡量用户在一段时间内持续访问情况的指标,如访问频率、访问间隔时间。

(2)活跃度指标表征用户访问网页/App的频次,如平均停留时间、平均访问页面数。

(3)产出指标用来衡量用户的购买价值,如订单数、客单价。

可以对这些指标进一步建模创造商业价值。

异常检测

异常检测(Anomaly Detection)是指找出与大部分对象不同的对象,这种异常对象也被称为离群点。异常检测的应用领域很广,例如可用于数据预处理、病毒木马检测、工业制造产品检测、网络流量检测。

常见的异常检测有以下两类方法。

(1)基于模型的方法:可以通过参数估计的方法创建数据的概率分布模型,以剔除一个不服从该分布的对象。

(2)基于距离的方法:该方法定义对象之间的距离度量,据此检测离群点。

基于信贷历史的风控模型

金融的核心在于控制风险,消费信贷领域也不例外。基于信贷历史的风控模型主要用于反欺诈、判定客户逾期风险、确定用户授信额度。针对消费金融产品的特性,每个公司都有自己的风控模型,这些模型的核心变量是贷款用户的信贷历史数据,包括贷前申请与审核、贷中还款、逾期与催收情况等。除了信贷历史数据,用户个人的其他数据也是模型的输入变量,如个人身份信息(学历、年龄等)、社交信息、电商购物信息等。

在现实世界里,事件时间与处理时间往往并不一致,两者的偏差也因数据源特性、处理引擎及硬件的差别而千差万别,而这种变化给处理引擎的设计带来了不小的挑战。图1-15描述了星球大战系列电影的上映时间。

在这个例子中,事件时间指这是第几部星球大战电影,处理时间指上映时间,如《星球大战1:幽灵的威胁》这部电影的事件时间为1,处理时间为1999年。从图1-15中可以看出,事件时间和处理时间是不一致的。

图1-15 事件时间与处理时间

事件时间与处理时间有所偏差的主要原因如下。

(1)受共享资源局限:如网络阻塞时延、网络分区(参考 CAP 定理)、共享CPU等。

(2)软件构架:如分布式系统中的并发竞争、时钟不一致等。

(3)数据自身特性:如key的特殊分布、吞吐量的快速涨落、乱序等。

CAP定理

CAP定理指出:一个分布式系统最多能具备一致性(Consistency)、可用性(Availability)及分区容错性(Partition tolerance)中的两个特性,而不可能同时具备这三个特性。

(1)一致性:在分布式系统中同一数据的所有备份,在同一时刻,其值是相同的,或者说,所有客户端读取的值是相同的。

(2)可用性:在集群的部分节点出现故障后,集群还能正常响应客户端的读写请求。

(3)分区容错性:分区是对分布式系统通信时限的要求,即如果不能在有限时间内达成数据一致,则系统发生分区。所谓分区容错性,是指即便发生了分区,分布式系统仍然能正确响应客户端的读写请求。

1.3.3 窗口

窗口(window)是将(有界或无界)数据集拆分成一个个有限长度数据区间的机制,即在数据集中增加临时处理边界,用于将事件按照时间或其他特征分组分析,其中临时这个定语说明窗口并没有物理地改变数据集。通常有三类窗口,以下举例详细说明。

(1)滚动窗口(Tumbling Window):将时间拆分成固定长度。如图1-16所示,圆点表示事件,属于每个user(user 1、user 2、user 3)的事件被划到不重叠且等时长(window size)的5个窗口(window 1、window 2、window 3、window 4、window 5)中,其中时间(time)可以是事件时间或处理时间。

图1-16 滚动窗口

(2)滑动窗口(Sliding Window):按照滑动步长(window slide)将时间拆分成固定的长度,当滑动步长小于窗口长度时,相邻窗口间会有重叠。如图1-17所示,4个窗口之间有重叠区域。

图1-17 滑动窗口

(3)会话窗口(Session Window):以活动时间间隔为边界,将一系列连续事件拆分到不同的会话中。会话窗口的长度是动态的。图1-18中的session gap为窗口的活动时间间隔,user 1和user 2的数据仍被划分为4个窗口,但user 3的数据被划到了3个窗口中。

图1-18 会话窗口

1.3.4 水印

水印(watermark)是嵌入在事件时间轴上用于判断事件时间窗口内所有数据均已到达引擎的一种时间推理工具,是一种既可以在流处理引擎侧嵌入,又可以在消息系统侧嵌入的时间戳。

水印的语义是事件时间小于水印标记时间的事件不会再出现,因此水印是事件的推进器(metric of progress)。

时空穿梭是另一个相关概念。出于调试或审计目的,数据处理程序有时需要将事件时间倒回至过去某个时间点重新开始数据处理任务。

1.3.5 触发器

触发器(trigger)决定在窗口的什么时间点启动应用程序定义的数据处理任务。

水印迟到会拉长窗口生存期,水印早到会导致数据处理结果不准确,触发器就是为解决这两个问题而被引入的。

1.3.6 数据处理模式

1.有界数据处理

通常,我们使用批处理引擎处理有界数据集(尽管流处理引擎也具备这个功能)。在Hadoop的WordCount程序中,WordCountMapper负责遍历数据集的每一行,切分出以空格为间隔的单词,并输出格式为(word,1)的中间处理数据;WordCountReducer读入shuffle后的中间数据集,聚合输出每个单词的出现次数,代码如下:

这类数据处理模式的特征是将有界数据集处理成规整的形式并输出,可用图1-19形象地描述。

图1-19 有界数据处理

2.无界数据批处理

在流处理引擎没有出现之前,业界通常使用窗口机制将无界数据集分割成一系列有界数据块,使用批处理方式分析每个数据块,即微批处理模式,如图1-20所示。

图1-20 无界数据批处理

3.无界数据流式处理

基于微批模式的无界数据批处理的原理是,将多个微批处理任务串接起来构建流式数据处理任务,这通常是以牺牲延迟和吞吐为代价的。解决这种缺陷是流处理引擎的发展目标之一,解决方案建立在分析无界数据集的无序和事件时间偏差特性的基础上。

(1)无序意味着引擎需要时间处理机制。

(2)事件时间偏差意味着引擎不能假定在某个时间窗口内能够观察到所有事件。

下面分4种情况分析无界数据的流式处理模式。

1)时间无关

流处理引擎能成功应用于需要时间机制的输出处理任务中,也能用于解决与时间无关的数据处理任务,如过滤、数据源连接。

(1)过滤:用于过滤给定规则的事件,如从网站后台日志中过滤出给定源地址的请求。

(2)连接:将两个数据源中相关联的记录连接成一条记录,如图1-21所示。

图1-21 时间无关数据处理

2)近似计算

近似计算是另一种与时间无关的流式数据处理应用,优点是系统开销小。由于算法过于复杂,这类流式数据处理模式应用范围较窄。下面以Streaming k-means为例加以说明。

Streaming k-means算法的基本思想是以空间中k个点为中心进行聚类,该算法在流式数据处理应用中的扩展方式如下。

(1)初始以随机位置作为聚类的中心点,因为此时还没有观察到任何数据。

(2)收到新的数据后,调用Streaming k-means算法更新中心点。

(3)以更新后的中心点为初始中心点,跳转至步骤2。

3)根据处理时间开滚动窗口

这种窗口是根据事件被观察的时间设计的,优点有以下3个。

● 使用起来简单。

● 窗口边界易于确定。

● 易于提供与事件时间无关的语义。

根据处理时间开滚动窗口的数据处理模式,如图1-22所示。

图1-22 根据处理时间开滚动窗口的数据处理模式

4)根据事件时间开滚动窗口

根据事件时间开滚动窗口的数据处理模式,如图1-23所示。

图1-23 根据事件时间开滚动窗口的数据处理模式

事件时间窗口提供了更灵活的机制,但与处理时间窗口相比,事件时间窗口通常需要更长的生存期,这会给引擎的架构设计带来诸多挑战,例如需要大容量的缓存以持久化状态;窗口边界难以确定,事件迟到导致确定窗口结束点较为困难。

1.3.7 如何理解流式数据架构的内在机制

可以通过以下4个问题深入理解流式数据处理的内在机制。

● what:定义数据处理是什么,即对数据进行怎样的转换操作,如Spark的算子。

● where:定义转换操作的输入数据取自什么时间区间,窗口是这个问题的答案。

● when:定义转换操作发生在时间轴的什么时间点,水印和触发器是这个问题的答案。

● how:定义如何刻画同一窗口内多次转换操作结果的关系,累加模式是这个问题的答案。

其中,转换操作有时也用聚合代替,转换内涵更丰富,而聚合用于在数据集(如窗口)上计算某个值的场合(如窗口内数据的求和)。