The world beyond batch: Streaming 101(第一节)

The world beyond batch: Streaming 101(第一节)

在流式计算方面,有两篇经典文章是必读的:The world beyond batch: Streaming 101The world beyond batch: Streaming 102。这两篇文章的作者是Google流式系统的负责人Tyler Akidau,他是MillWheel与DataFlow的开发者,在流式系统方面十分权威。这两篇文章非常详细并且适合初学者,可以帮助我们理清流式系统的各种概念与面临的挑战,是十分难得的佳作。其中Streaming101主要介绍了流式系统的一些基本概念和困境,同时提出了一个核心观点:设计优良的流式系统完全可以代替批量系统。在Streaming102这篇文章中,作者以实际的流式系统(DataFlow)的设计为例,列举了多个场景,具体讲解了如何设计流式系统,解决这些问题。本文是Streaming101的中译版,后续会继续翻译Streaming102.

背景

一开始,我会介绍一些重要的背景信息,这有助于理解后面我想讨论的主题。我们会从三个部分来介绍:

  • 术语:为了准确地讨论复杂的主题需要精确的术语定义。当前有一些术语被赋予了过多解释,当我使用这些术语时会明确说明我的的意思。
  • 能力边界:我会列举流式系统的常见的缺点。我也会提出一个我认为数据处理系统构建者需要采用的想法,来达到解决现代数据处理需求的目的。
  • 时间概念:我将会介绍两个基础的与数据处理相关的时间概念,介绍它们之间的关系,并且指出这两个概念相关的一些难题。

术语:什么是streaming?

在深入介绍之前,我想先解决一个问题:什么是streaming?如今术语”streaming”意味着很多不同的东西,这会导致我们误解streaming真正的含义,或者误解 streaming 系统真正的功能。所以,我会精确的定义这个术语。

问题的本质是本来很多术语应该是描述它们是什么(例如无界数据处理,近似结果等等),却被描述成它们是如何实现的(也就是通过流式计算引擎)。没有精确定义的 streaming,被人们狭隘的认为 streaming 的功能只是被限制在某些被称作”streaming”的特性,例如近似或者推测结果。一个设计良好的流式系统可以跟现在的批量引擎一样,可以生成正确、一致、可重复计算的结果。我对术语 streaming 的定义是:一种被设计用于处理无穷数据的数据处理引擎。(为了完整性,这个定义包含了真正的流式和微批两种实现)。

下面是一些经常和”streaming”联系在一起的几个术语,我分别为它们给出了更精确,更清楚的定义,我建议整个工业界都应该采纳它们:

  1. Unbounded data:一种持续产生无穷的数据。它们经常被称为”streaming data”。然而, 用术语 streaming 或者 batch 描述数据都是有问题的,正如上面提到的,它们的含义是用某种类型的计算引擎来处理这些数据。这两种类型数据的关键区别是它们的有限性,所以使用能够表名它们的区别的术语是更好的。因此,我将无穷的”streaming”数据称为unbounded data,将有限的”batch”数据称为bounded data。
  2. Unbounded data processing:一种持续的数据处理模式,应用于前面提到的unbounded data。我自己也常使用术语 streaming 来描述这种类型的数据处理,但是在本文中 streaming 还是意味着流式计算引擎,这会造成误解;重复执行批量引擎也可以处理 unbounded data(相反,良好设计的流式系统也可以处理 bounded data)。因此,为了清楚,我会使用unbounded data processing这个术语。
  3. Low-latency, approximate, and/or speculative results:这些类型的结果通常都与流式引擎相关。批量系统通常不是设计用来解决低延迟或者近似结果的只是一种历史观念。事实上,批量引擎也可以生成近似结果。因此,使用上面这些术语可以更好的描述它们是什么(低延迟,近似或者推测结果),而不是通过流式引擎代表它们。

从此开始,每当我使用术语”streaming”,我都是在说一个为无界数据设计的计算引擎。当我要表达上面的其它术语时,我都会说unbounded data, unbounded data processing, 或者 low-latency / approximate / speculative results。这些术语都是在Cloud Dataflow中采用的,我也希望其他人可以采用它们。

streaming 被夸大的能力限制

下面,让我们讨论下流式系统能做和不能做的,重点看看能做的;在这篇文章里我想介绍的是一个设计良好的流式系统能做什么。流式系统长久以来被认为是提供低延迟、不准确/推测的结果,通常与一个提供最终准确结果的批量系统协作配合,也就是说 Lambda 架构

Lambda 架构基本的理念就是同时运行一个流式系统和一个批量系统,二者都执行本质上相同的计算。流式系统提供低延迟但是不准确的结果(或者是由于使用近似算法,或者是由于流式系统本身不提供准确性保证),过段时间之后批量系统会提供准确的输出。 Lambda 架构最开始由 Twitter 的Nathan MarzStorm 的作者)提出,在当时是很奇妙的想法,也是相当成功的;流式引擎在正确性上不能令人满意,批量引擎天生不够灵活,所以Lambda提供了一种短期的解决方案。不幸的是,维护一个 Lambda 系统很麻烦:你需要构建维护两个独立的系统,而且还要在最后合并两个系统的结果。

作为研究强一致流式引擎多年的从业者,我也发现 Lambda 架构的整个原则是有问题的。我是Jay Kreps的文章《Questioning the Lambda Architecture》的粉丝。这篇文章是最早质疑双引擎模式的必要性的。Kreps 使用一个像 Kafka 这样的可重放系统作为流式系统的内部连接来解决可重复性的问题,他提出 Kappa 架构,基本思想就是用一个设计良好的系统作为单系统来运行。我不认为这个概念需要一个新名字,但是我完全支持他的思想。

我认为应该更进一步。我认为设计良好的流式系统提供的功能应该是批量系统的超集。除去资源利用率方面的考虑,现在完全可以不需要批量系统了。Flink 就是采用这种想法构建的完全的 streaming系统,并且支持”batch”模式,我非常喜欢它。

随着流式系统越来越成熟,它提供一种为无界数据处理的健壮架构,将会使 Lambda 架构消失在大数据的历史中。我相信这正在变成现实。如果想打败批量系统,我们只需要做两件事:

1. 正确性 – 这使streaming 能够和 batch 等同。

本质上,正确性取决于一致性存储。流式系统需要一个定期的持久化状态的方法(就是 Kreps 在他的文章中讨论的为什么在流式处理中本地状态是基础),并且它必须设计的足够好,即使机器故障后也能保持一致性。当几年前Spark Streaming首先出现在公共大数据视野中时,它就是黑暗的流式世界中的一个灯塔。一切都在向前发展,但是仍有很多流式系统不能提供强一致性;我实在不理解为啥at-most-once处理仍然存在,但是实际情况是它确实存在。

再重申一次,因为这一点很重要:强一致是exactly-once处理所必须的,是正确性所必须的,是任何有机会赶超批量系统的系统所必须的。除非你真的不关心结果,我都建议你放弃那些不提供强一致状态的流式系统,不要在它们身上浪费你的时间。

如果你想学习在流式系统中如何做到强一致性,我建议你阅读MillWheelSpark Streaming的论文。二者都花费了很多时间讨论一致性。本文时间有限,我就不再此详述了。

2. 推导时间的工具 – 这令 streaming 超越 batch。

处理无界、无序数据时,好的时间推导工具是基础。越来越多的需求需要我们处理无界无序的数据,但是目前的批量系统(包括大多数流式系统)缺少必要的工具来解决这些问题。我会用本文剩余的篇幅,以及下一篇文章着重介绍它。

我们首先会理解时间方面中一些重要的概念,然后深入分析无界无序数据的 event-time skew。之后会介绍对于有界和无界数据处理的通用方法,包括批量和流式系统。

Event time vs. processing time

为了透彻地讲解无界数据处理,需要对于涉及的时间概念有清晰的理解。在任何数据处理系统中,有两种典型的时间概念需要我们关心:

  • Event time,就是事件真正发生的时间。

  • Processing time,就是事件进入系统被处理的时间。

不是所有的业务都关心event times(如果你的不关心,则你的生活会简单很多),但是很多业务都要关心。例如为带时序的用户行为刻画特征,大部分付费应用,以及很多类型的异常检测。

理想情况下,event time 和 processing time 总是相同的,也就是事件一发生立刻就被处理了。而现实是残酷的,event time 和 processing time 之间的 skew 不仅不是0,而是一个与输入源、执行引擎以及硬件相关的函数。可以影响 skew 的因素包括:

  • 共享资源限制,例如网络拥塞,网络分区,或者非独占环境中的共享 CPU。
  • 软件原因,例如分布式系统逻辑,竞争等等。
  • 数据本身的特征,包括 key 的分布,吞吐量差异,无序。

如果将真实系统中的 event time 和 processing time 的绘制出来,将会得到图1中的红线。

enter image description here

图1:时间映射举例。X 轴代表 event time。Y 轴代表 processing time。

黑色虚线代表理想情况,也就是 processing time 与 event time 完全相同;红线代表真实情况。在这个例子中,系统在 processing time 的开始有一点延迟,中间阶段接近理想情况,在最后又有一点延迟。在理想情况和红线之间的水平距离就是 processing time 和 event time 的skew。skew基本都是由处理管道的延迟引入的。

由于 event time 和 processing time 之间的映射关系不是固定的,这意味着如果你关心数据的 event times(也就是事件真正发生的时间),你就不能用 processing time 来分析数据。不幸的是,这是目前大部分系统为无界数据设计的处理方法。为了处理无界数据的无穷特性,这些系统提供了一些将数据按时间窗口划分的概念。我们会在下面深入讨论时间窗口,它的基本含义就是将数据沿着临时的分界线切分成有限的分片。

如果你关心正确性,并且需要用 event time 来分析数据,你就不能像大部分已有的系统那样,用 processing time 来定义这些临时分界线(也就是 processing time 窗口);由于processing time 和 event time 之间没有一致性的关联关系,一些数据就会被划分到错误的 processing time 窗口中(由于分布式系统内在的延迟,很多类型的输入源的在线/离线等原因),导致无正确性可言。我们会在下面看到更多这样的例子。

不幸的是,即使按 event time 划分窗口也不是那么完美的。在无界数据环境中,无序和变化的skew会为 event time 窗口带来完整性问题: processing time 和 event time 之间缺少可预测的映射关系,那你如何确定对于某个 event time 时刻为 X 的数据是否已经都进入系统处理过了?对于很多真实世界中的数据源,你是无法确定的。现在大部分数据处理系统都依赖某种完整性,但是当应用到无界数据时它们就遇到了严重的问题。

我建议应该设计工具能够让我们处理这种由复杂的数据带来的不确定性,而不是将无界数据划分成最终会变成完整的有限的数据片。新数据将会到达,老数据可能会被撤销或者更新,我们构建的任何系统都应该能够独立处理这些情况。在这些系统中完备性的概念只是一个辅助而非一个必要条件。

在深入介绍如何实现Cloud Dataflow数据模型前,我们先了解一个更有用的背景:常见数据处理模式。

下一篇:The world beyond batch: Streaming 101(第二节)

发表评论

电子邮件地址不会被公开。 必填项已用*标注