《Streaming 101》: 当我谈流计算时,我谈些什么

最近正在看Streaming Systems这本书、这本书前两章基本是从作者的博客Streaming 101和Streaming 102整理得到的。这两篇博客实在是太经典,强烈建议每个做数据处理领域的工程师都仔细学习、反复体会。

Streaming 101这篇文章可以用一句话概括:“当我谈流计算时,我谈些什么”。
Streaming 102可以用另一句话概括:Beam模型/DataFlow模型如何处理流计算。

这篇博客,就让我们回味一下经典。

一、流是什么

当我谈流计算时,我谈些什么。

在开始讨论 流式系统(Streaming System) 之前,我们有必要澄清概念,当我们讨论流式计算时,我们究竟在讨论什么?
我们听说过很多关于流的描述:无限数据集、近似结果、推测结果、Storm、Spark Streaming、Flink等等。这些描述都是流也都不是流。在开始讨论之前,我们有必要澄清一下流式系统的含义。

流式系统是在设计时考虑无限数据集的数据处理引擎。

刻画数据集有两个重要(并且正交)的维度,基数(cardinality)构造(constitution)。基数描述了数据的量、而构造描述了数据的组成结构。在量的角度来看,数据可以分为 有界数据(bounded data)无界数据(unbounded data) ; 在组成结构的角度来看,数据可以分成 表(table)流(stream)。流式计算的表和流的问题,我们有机会在后面的文章中再展开讨论。

二、流的能力

流式计算能做什么、不能做什么,这是个大问题。

现在的流式系统,往往是提供了低延迟、不精确的结果,同时也提供更精确的批处理系统,最终得到精确结果。而作者认为,流式系统是批处理系统的超集,批处理是流式系统的一种特例,良好设计的纯流式系统最终会提供精确的结果从而取代批处理,Flink的设计就很契合上述思路。

两种架构观点:

  1. Lambda架构 同时维护流处理和批处理、结果需要合并,该架构方案由Apache Storm作者Nathan Marz提出。Lambda架构使用批处理视图(batch view)解决了计算结果准确性的问题,使用实时视图(real-time view)解决了计算延迟的问题,在实践中非常成功。Lambda架构的缺点也很突出,下游查询需要合并处理两份结果,批处理结果和流式结果的合并复杂,维护成本很高。
    Lambda架构图
  2. Kappa架构 使用Kafka这种可重演的数据引擎、只维护一条流式处理系统,不需要批处理,计算结果通过反复重算,无限趋近于真实精确结果。该架构方案由Kafka作者Jay Kreps提出,在Kafka的公司内部也维护了一套这样的系统。Flink在一定程度上也实现了一版符合该架构的引擎。Kappa架构由于具有更大的想象空间更受大家的关注,而Structured Streaming也在强调上游数据可回溯。
    Kappa架构图

目前Lambda架构是主流,因为纯流式系统存在局限,主要体现在正确性(或者一致性),如果不能保证数据被精准处理一次,那数据就没办法保证正确。除了正确性,流式系统还需要提供时间工具,用来处理变化的事件时间倾斜,无界的,无序的数据。如果有一天,流式计算可以解决正确性和时间原语的问题,那么Lambda架构就可以退出历史舞台了。

  • 时间倾斜问题
    由于种种原因,事件真实发生的时间和数据被处理的时间,两者中间一定存在差值,而且这个差值随各种因素在不断变化,这种差值不为0的事实称为事件时间倾斜(time skew),或者简称为倾斜;参考下图,理想中的情况是事件发生后流式系统立即处理,现实情况却是数据处理时间大于事件发生时间而且差值在不断变化。
    在这里插入图片描述

  • 无序问题
    举个简单的例子,假设手机上的一个app收集用户统计信息。当手机未连上网络时,这段时间内收集到的数据就无法上传。这就意味着数据可能比真实的发生时间晚几分钟、几个小时甚至更长。接收数据有延迟,先发生的事件可能在后发生的事件之后出现,这就是流式计算中事件时间无序的特点。

  • 事件时间 v.s. 处理时间
    事件时间 v.s. 处理时间,这是个基础问题。
    建立事件时间和处理时间的概念,这是入门流式计算的重要前提。事件时间是指事件真实发生的时间,处理时间是指事件在系统中被接收到的时间。不是所有需求都需要区分事件时间和处理时间,有些需求可能只区分地域、设备、来源渠道这些维度,根本不关心时间。Spark Streaming是基于处理时间的,而Structured Streaming是基于事件时间的。

三、解决之道

这些问题现在都是怎么解决的呢?

首先,我们需要把无界数据切分变成有界数据,这就是所谓的划分窗口(windowing)。基于处理时间划分窗口(windowing by processing time)、或基于事件时间划分窗口(windowing by event time),两种方式都存在,而且都有其存在的道理。

1. 无界数据的批处理

比如一个网站的访问日志,日志量有一定的规模,我们会把前一天的数据按时间拆分,写到不同的路径,形成所谓的时间窗口。例如hour=2019110100, hour=2019110101, …, hour=2019110123。

到第二天20191102,等待几个小时,再晚到的数据就不参与批计算了。启动一个批计算任务,计算昨天每个小时的统计指标。

套路一、固定窗口

批处理无界数据固定窗口

套路二、会话

批处理(或者离线计算)的切分会话,大体可以用下面的图来表示。注意数据计算批次是每小时一次,这样做的代价就是,如果一个会话在前面的处理批次中尚未完成,由于计算周期的原因,实际发生的一次会话被拆分到两次“会话”。现在市面上很多分析类产品都是这样做的,不一一点名了。
批计算划分session

2. 无界数据的流处理

无界数据的流式处理也不都难,很多无界数据的处理是 时间无关(time-agnostic) 的。例如流式计算的过滤就很容易、流式计算 内连接(inner join) 两条流也不难,比如我有两条数据流、一条流代表微信小程序访问行为日志、一条流代表微信公众号访问行为日志、某些小程序和公众号有相同的认证公司主体,在同一个认证公司主体下的微信unionId是相同的。现在有个营销活动,我想统计在活动开始后有多少pv、uv同时访问了我的小程序mp和我的公众号wp。这就是一个流的内连接(inner join)问题。但是,两条流的外连接(outer join)或者三条流的内连接问题,就不那么容易解决。具体内容有机会单独开一篇文章写。

此外甚至有一类流式近似算法,把时间相关的需求强行采用时间无关的方式计算,得到误差范围可控的近似结果,例如近似top-n算法,流式k-means算法等,这类问题在业界的应用案例还不太多,就不展开了。

套路三、基于处理时间划分窗口

按处理时间划分窗口很简单,因为不用区分事件时间和处理时间,和各种复杂的流式处理过程相比它太容易实现了。按处理时间划分窗口也有先天的弊端,那就是要求数据到来的顺序严格按照事件发生顺序,迟到的乱序数据会被抛弃,流式计算的统计结果也往往小于真实结果。按处理时间划分窗口不能接受太大比例的数据延迟,否则统计指标会存在较大的误差。
基于处理时间划分窗口

套路四、基于事件时间划分窗口

三种窗口划分策略见下图。图中的例子是三种无界数据切分过程,它们之间的区别主要是在切分规则是否针对所有数据保持一致。假如我们的数据按某个维度分成了key1, key2, key3三个部分,切分规则一致,就叫做对齐切分,切分规则不一致,就叫做不对齐切分。

举几个例子,按移动设备操作系统分成iOS、安卓、其他,在三个key上的切分规则都一样,这叫做固定窗口。按时区区分数据,可能需求想要按当地时间做分析,那么窗口切分规则需要错开对应的时差,这样的窗口切分叫做滑动窗口。还有一种切分是按用户的一次连续访问行为,超过一定时间未操作自动断开,就是所谓的会话窗口
窗口划分策略
用另一种描述方式再看看窗口划分。基于事件时间、固定窗口见下图。
基于事件时间划分固定窗口
基于事件时间、会话窗口见下图。
基于事件时间、会话窗口

通过上面的内容,我们在做流式计算时的基础信息就说完了。Streaming 101这篇文章的主体内容就是这些,更多的技术细节和解决方案,我们下回Streaming 102再聊。

四、参考

  1. Streaming Systems
  2. Streaming 101
  3. Streaming 101 中文翻译
  4. DataFlow编程模型与Spark Structured streaming
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值